Example #1
0
 def testIAdd(self):
     """ Tests in-place addition of two Structure instances """
     s1 = create_random_structure(parametrized=True)
     s2 = create_random_structure(parametrized=True)
     s1cp = copy(s1)
     s1 += s2
     self._check_sum(s1, s1cp, s2)
Example #2
0
 def testAddParametrized(self):
     """ Tests addition of two parametrized Structure instances """
     s1 = create_random_structure(parametrized=True)
     s2 = create_random_structure(parametrized=True)
     self.assertTrue(bool(s1.bond_types))
     self.assertTrue(bool(s2.bond_types))
     s = s1 + s2
     self._check_sum(s, s1, s2)
 def test_ub_select(self):
     """ Tests selection when "blank" Urey-Bradley terms present """
     struct = utils.create_random_structure(parametrized=True)
     struct.urey_bradleys[0].type = pmd.NoUreyBradley
     s = struct[:]
     self.assertEqual(len(s.urey_bradleys), len(struct.urey_bradleys))
     self.assertIs(s.urey_bradleys[0].type, pmd.NoUreyBradley)
 def test_ub_select(self):
     """ Tests selection when "blank" Urey-Bradley terms present """
     struct = utils.create_random_structure(parametrized=True)
     struct.urey_bradleys[0].type = pmd.NoUreyBradley
     s = struct[:]
     self.assertEqual(len(s.urey_bradleys), len(struct.urey_bradleys))
     self.assertIs(s.urey_bradleys[0].type, pmd.NoUreyBradley)
Example #5
0
 def testBoxHandling(self):
     """ Tests that Structure.box is always the expected type """
     s = create_random_structure(parametrized=False)
     self.assertIs(s.box, None)
     s.box = [10, 10, 10, 90, 90, 90]
     self.assertIsInstance(s.box, np.ndarray)
     self.assertEqual(s.box[0], 10)
     self.assertEqual(s.box[1], 10)
     self.assertEqual(s.box[2], 10)
     self.assertEqual(s.box[3], 90)
     self.assertEqual(s.box[4], 90)
     self.assertEqual(s.box[5], 90)
     s.box = np.array([10, 10, 10, 90, 90, 90], dtype=np.float64)
     self.assertIsInstance(s.box, np.ndarray)
     self.assertEqual(s.box[0], 10)
     self.assertEqual(s.box[1], 10)
     self.assertEqual(s.box[2], 10)
     self.assertEqual(s.box[3], 90)
     self.assertEqual(s.box[4], 90)
     self.assertEqual(s.box[5], 90)
     s.box = [10*u.angstroms, 10*u.angstroms, 10*u.angstroms,
              90*u.degrees, 90*u.degrees, 90*u.degrees]
     self.assertIsInstance(s.box, np.ndarray)
     self.assertEqual(s.box[0], 10)
     self.assertEqual(s.box[1], 10)
     self.assertEqual(s.box[2], 10)
     self.assertEqual(s.box[3], 90)
     self.assertEqual(s.box[4], 90)
     self.assertEqual(s.box[5], 90)
Example #6
0
 def testMultiplyNotParametrized(self):
     """ Tests replicating a non-parametrized Structure instance """
     s1 = create_random_structure(parametrized=False)
     multfac = random.randint(2, 5)
     s2 = s1 * multfac
     self.assertIsNot(s1, s2)
     self.assertEqual(len(s2.atoms), len(s1.atoms) * multfac)
     self._check_mult(s2, s1, multfac)
    def test_bond_serialization(self):
        """ Tests the serialization of Bond """
        struct = utils.create_random_structure(True)
        bond = struct.bonds[0]
        fobj = BytesIO()
        pickle.dump(bond, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self.assertIsInstance(bond, pmd.Bond)
    def test_bond_serialization(self):
        """ Tests the serialization of Bond """
        struct = utils.create_random_structure(True)
        bond = struct.bonds[0]
        fobj = BytesIO()
        pickle.dump(bond, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self.assertIsInstance(bond, pmd.Bond)
Example #9
0
 def testCoordinates(self):
     """ Tests coordinate handling in Structure """
     s = create_random_structure(parametrized=False)
     self.assertIs(s.coordinates, None)
     natom = len(s.atoms)
     # Make sure coordinates will be generated from Atom.xx, xy, xz if not
     # otherwise generated
     xyz = np.random.random((natom, 3))
     for a, x in zip(s.atoms, xyz):
         a.xx, a.xy, a.xz = x
     self.assertEqual(s.coordinates.shape, (natom, 3))
     np.testing.assert_equal(s.coordinates, xyz[:,:])
     self.assertIs(s._coordinates, None)
     # Now set multiple frames
     xyz = np.random.random((5, natom, 3)).tolist()
     s.coordinates = xyz
     self.assertIsInstance(s.coordinates, np.ndarray)
     self.assertEqual(s.coordinates.shape, (natom, 3))
     for a, x in zip(s.atoms, xyz[0]):
         self.assertEqual(a.xx, x[0])
         self.assertEqual(a.xy, x[1])
         self.assertEqual(a.xz, x[2])
     np.testing.assert_equal(s.get_coordinates('all'), xyz)
     for i in range(5):
         np.testing.assert_equal(s.get_coordinates(i), xyz[i])
     # Now try setting with units
     xyz = u.Quantity(np.random.random((3, natom, 3)), u.nanometers)
     s.coordinates = xyz
     self.assertIsInstance(s.coordinates, np.ndarray)
     self.assertEqual(s.coordinates.shape, (natom, 3))
     for a, x in zip(s.atoms, xyz[0]._value):
         self.assertEqual(a.xx, x[0]*10)
         self.assertEqual(a.xy, x[1]*10)
         self.assertEqual(a.xz, x[2]*10)
     # Now check setting None
     s.coordinates = None
     for a in s.atoms:
         self.assertFalse(hasattr(a, 'xx'))
         self.assertFalse(hasattr(a, 'xy'))
         self.assertFalse(hasattr(a, 'xz'))
     self.assertIs(s.coordinates, None)
     # Now check setting flattened arrays
     s.coordinates = np.random.random((natom, 3))
     self.assertEqual(s.coordinates.shape, (natom, 3))
     s.coordinates = np.random.random(natom*3)
     self.assertEqual(s.coordinates.shape, (natom, 3))
     s.coordinates = np.random.random(natom*3*10)
     self.assertEqual(s.coordinates.shape, (natom, 3))
     # Now check other iterables
     old_crds = s.coordinates
     s.coordinates = (random.random() for i in range(3*len(s.atoms)))
     self.assertEqual(s.coordinates.shape, (natom, 3))
     diff = (old_crds - s.coordinates).ravel()**2
     self.assertGreater(diff.sum(), 0.01)
    def test_structure_serialization(self):
        """ Tests the serialization of Structure """
        structure = utils.create_random_structure(parametrized=True)
        # Make sure we copy over exclusions
        structure.atoms[0].exclude(structure.atoms[10])
        fobj = BytesIO()
        pickle.dump(structure, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self._compare_structures(unpickled, structure)
    def test_structure_serialization(self):
        """ Tests the serialization of Structure """
        structure = utils.create_random_structure(parametrized=True)
        # Make sure we copy over exclusions
        structure.atoms[0].exclude(structure.atoms[10])
        fobj = BytesIO()
        pickle.dump(structure, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self._compare_structures(unpickled, structure)
Example #12
0
 def testLoadDataFrameStructureView(self):
     """ Tests the load_dataframe method on StructureView """
     struct = create_random_structure(parametrized=True).view[:10, :]
     charges = [a.charge for a in struct.atoms]
     self.assertTrue(not all(x == 0 for x in charges))
     df = struct.to_dataframe()
     # First zero-out all of the charges
     struct.load_dataframe(dict(charge=[0 for a in struct.atoms]))
     self.assertTrue(all(a.charge == 0 for a in struct.atoms))
     # Now re-load the dataframe to restore the original charges
     struct.load_dataframe(df)
     self.assertTrue(
         all(a.charge == x for a, x in zip(struct.atoms, charges)))
     # Change the first atomic properties of *everything* now to
     # make sure that they all get updated
     df_orig = df.copy()
     df.loc[0, 'number'] = 1
     df.loc[0, 'name'] = 'HAHA'
     df.loc[0, 'type'] = 'FUNY'
     df.loc[0, 'atomic_number'] = 92  # uranium
     df.loc[0, 'charge'] *= 2
     df.loc[0, 'mass'] *= 10
     df.loc[0, 'nb_idx'] = 10
     df.loc[0, 'solvent_radius'] *= 2
     df.loc[0, 'screen'] = 0.5
     df.loc[0, 'occupancy'] = 0.1
     df.loc[0, 'bfactor'] = 0.5
     df.loc[0, 'altloc'] = 'X'
     df.loc[0, 'tree'] = 'BLU'
     df.loc[0, 'join'] = 1.0
     df.loc[0, 'irotat'] = 2.0
     df.loc[0, 'rmin'] *= 2
     df.loc[0, 'epsilon'] /= 2
     struct.load_dataframe(df)
     atom = struct.atoms[0]
     self.assertEqual(atom.number, 1)
     self.assertEqual(atom.name, 'HAHA')
     self.assertEqual(atom.type, 'FUNY')
     self.assertEqual(atom.atomic_number, 92)
     self.assertEqual(atom.charge, charges[0] * 2)
     self.assertEqual(atom.mass, 10 * df_orig.loc[0, 'mass'])
     self.assertEqual(atom.nb_idx, 10)
     self.assertEqual(atom.solvent_radius,
                      2 * df_orig.loc[0, 'solvent_radius'])
     self.assertEqual(atom.screen, 0.5)
     self.assertEqual(atom.occupancy, 0.1)
     self.assertEqual(atom.bfactor, 0.5)
     self.assertEqual(atom.altloc, 'X')
     self.assertEqual(atom.tree, 'BLU')
     self.assertEqual(atom.join, 1.0)
     self.assertEqual(atom.irotat, 2.0)
     self.assertEqual(atom.rmin, 2 * df_orig.loc[0, 'rmin'])
     self.assertEqual(atom.epsilon, df_orig.loc[0, 'epsilon'] / 2)
    def test_residue_serialization(self):
        """ Tests the serialization of Residue """
        struct = utils.create_random_structure(parametrized=True)
        res = struct.residues[0]

        fobj = BytesIO()
        pickle.dump(res, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self.assertEqual(len(res.atoms), len(unpickled.atoms))
        for a1, a2 in zip(res, unpickled):
            self._equal_atoms(a1, a2)
    def test_bondtype_serialization(self):
        """ Tests the serialization of BondType """
        struct = utils.create_random_structure(True)
        bt = struct.bond_types[0]

        fobj = BytesIO()
        pickle.dump(bt, fobj)
        fobj.seek(0)

        unpickled = pickle.load(fobj)

        self.assertEqual(unpickled, bt)
        self.assertIsNot(unpickled, bt)
 def test_structure_view_coordinates(self):
     """ Tests handling of coordinates on a StructureView """
     s = utils.create_random_structure(parametrized=True)
     self.assertIs(s.view[:len(s.atoms)//2].coordinates, None)
     self.assertIs(s.view[:len(s.atoms)//2].positions, None)
     # Make sure it's an even number of atoms
     if len(s.atoms) % 2 == 1:
         s.strip('@1')
     x = np.random.rand(len(s.atoms)//2, 3)
     s.coordinates = np.vstack([x.flatten(), x.flatten()])
     np.testing.assert_equal(s.view[:len(s.atoms)//2].coordinates, x)
     np.testing.assert_equal(
             s.view[:len(s.atoms)//2].positions.value_in_unit(u.angstroms), x)
    def test_bondtype_serialization(self):
        """ Tests the serialization of BondType """
        struct = utils.create_random_structure(True)
        bt = struct.bond_types[0]

        fobj = BytesIO()
        pickle.dump(bt, fobj)
        fobj.seek(0)

        unpickled = pickle.load(fobj)

        self.assertEqual(unpickled, bt)
        self.assertIsNot(unpickled, bt)
 def test_structure_view_coordinates(self):
     """ Tests handling of coordinates on a StructureView """
     s = utils.create_random_structure(parametrized=True)
     self.assertIs(s.view[:len(s.atoms)//2].coordinates, None)
     self.assertIs(s.view[:len(s.atoms)//2].positions, None)
     # Make sure it's an even number of atoms
     if len(s.atoms) % 2 == 1:
         s.strip('@1')
     x = np.random.rand(len(s.atoms)//2, 3)
     s.coordinates = np.vstack([x.flatten(), x.flatten()])
     np.testing.assert_equal(s.view[:len(s.atoms)//2].coordinates, x)
     np.testing.assert_equal(
             s.view[:len(s.atoms)//2].positions.value_in_unit(u.angstroms), x)
Example #18
0
 def testLoadDataFrameStructureView(self):
     """ Tests the load_dataframe method on StructureView """
     struct = create_random_structure(parametrized=True).view[:10,:]
     charges = [a.charge for a in struct.atoms]
     self.assertTrue(not all(x == 0 for x in charges))
     df = struct.to_dataframe()
     # First zero-out all of the charges
     struct.load_dataframe(dict(charge=[0 for a in struct.atoms]))
     self.assertTrue(all(a.charge == 0 for a in struct.atoms))
     # Now re-load the dataframe to restore the original charges
     struct.load_dataframe(df)
     self.assertTrue(all(a.charge == x for a, x in zip(struct.atoms, charges)))
     # Change the first atomic properties of *everything* now to
     # make sure that they all get updated
     df_orig = df.copy()
     df.loc[0, 'number'] = 1
     df.loc[0, 'name'] = 'HAHA'
     df.loc[0, 'type'] = 'FUNY'
     df.loc[0, 'atomic_number'] = 92 # uranium
     df.loc[0, 'charge'] *= 2
     df.loc[0, 'mass'] *= 10
     df.loc[0, 'nb_idx'] = 10
     df.loc[0, 'radii'] *= 2
     df.loc[0, 'screen'] = 0.5
     df.loc[0, 'occupancy'] = 0.1
     df.loc[0, 'bfactor'] = 0.5
     df.loc[0, 'altloc'] = 'X'
     df.loc[0, 'tree'] = 'BLU'
     df.loc[0, 'join'] = 1.0
     df.loc[0, 'irotat'] = 2.0
     df.loc[0, 'rmin'] *= 2
     df.loc[0, 'epsilon'] /= 2
     struct.load_dataframe(df)
     atom = struct.atoms[0]
     self.assertEqual(atom.number, 1)
     self.assertEqual(atom.name, 'HAHA')
     self.assertEqual(atom.type, 'FUNY')
     self.assertEqual(atom.atomic_number, 92)
     self.assertEqual(atom.charge, charges[0]*2)
     self.assertEqual(atom.mass, 10*df_orig.loc[0, 'mass'])
     self.assertEqual(atom.nb_idx, 10)
     self.assertEqual(atom.radii, 2*df_orig.loc[0, 'radii'])
     self.assertEqual(atom.screen, 0.5)
     self.assertEqual(atom.occupancy, 0.1)
     self.assertEqual(atom.bfactor, 0.5)
     self.assertEqual(atom.altloc, 'X')
     self.assertEqual(atom.tree, 'BLU')
     self.assertEqual(atom.join, 1.0)
     self.assertEqual(atom.irotat, 2.0)
     self.assertEqual(atom.rmin, 2*df_orig.loc[0, 'rmin'])
     self.assertEqual(atom.epsilon, df_orig.loc[0, 'epsilon']/2)
Example #19
0
    def testAddNoValence(self):
        """ Tests addition of two minimal Structure instances """
        s1 = create_random_structure(parametrized=False, novalence=True)
        s2 = create_random_structure(parametrized=False, novalence=True)
        s = s1 + s2
        self.assertIsNot(s, s1)
        self.assertIsNot(s, s2)
        # Make sure that s is really the sum of s1 and s2
        self.assertEqual(len(s.atoms), len(s1.atoms) + len(s2.atoms))
        self.assertEqual(len(s.residues), len(s1.residues) + len(s2.residues))

        def cmp_atoms(a1, a2):
            self.assertIsNot(a1, a2)
            self.assertEqual(a1.name, a2.name)
            self.assertEqual(a1.type, a2.type)
            self.assertEqual(a1.atom_type, a2.atom_type)
            self.assertEqual(a1.mass, a2.mass)
            self.assertEqual(a1.charge, a2.charge)
            self.assertEqual(a1.atomic_number, a2.atomic_number)
            self.assertEqual(a1.radii, a2.radii)
            self.assertEqual(a1.screen, a2.screen)
            self.assertEqual(a1.residue.name, a2.residue.name)
            self.assertEqual(a1.residue.insertion_code, a2.residue.insertion_code)
            self.assertEqual(len(a1.bond_partners), len(a2.bond_partners))
            self.assertEqual(len(a1.angle_partners), len(a2.angle_partners))
            self.assertEqual(len(a1.dihedral_partners), len(a2.dihedral_partners))
            self.assertEqual(len(a1.bonds), len(a2.bonds))
            self.assertEqual(len(a1.angles), len(a2.angles))
            self.assertEqual(len(a1.dihedrals), len(a2.dihedrals))
            self.assertEqual(len(a1.impropers), len(a2.impropers))

        for a1, a2 in zip(s.atoms, s1.atoms + s2.atoms):
            cmp_atoms(a1, a2)
        for r1, r2 in zip(s.residues, s1.residues + s2.residues):
            self.assertEqual(len(r1), len(r2))
            self.assertEqual(r1.name, r2.name)
            self.assertEqual(r1.chain, r2.chain)
            self.assertEqual(r1.insertion_code, r2.insertion_code)
    def test_residue_serialization(self):
        """ Tests the serialization of Residue """
        struct = utils.create_random_structure(parametrized=True)
        res = struct.residues[0]

        fobj = BytesIO()
        pickle.dump(res, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self.assertEqual(len(res.atoms), len(unpickled.atoms))
        for a1, a2 in zip(res, unpickled):
            self._equal_atoms(a1, a2)
            self.assertIs(a1.residue, res)
            self.assertIs(a2.residue, unpickled)
Example #21
0
 def testBadBoxHandling(self):
     """ Tests error handling when Structure.box is improperly assigned """
     s = create_random_structure(parametrized=True)
     def wrong_number_of_args():
         s.box = [0, 1, 2, 3, 4]
     def wrong_number_of_args2():
         s.box = [0, 1, 2, 3, 4, 5, 6]
     self.assertRaises(ValueError, wrong_number_of_args)
     self.assertRaises(ValueError, wrong_number_of_args2)
     try:
         wrong_number_of_args()
     except ValueError as err:
         self.assertIn('6', str(err))
     # Try wrong units
     for i in range(6):
         box = [10, 10, 10, 90, 90, 90]
         box[i] *= u.liters
         def func():
             s.box = box
         self.assertRaises(TypeError, func)
Example #22
0
 def testAddToEmptyStructure(self):
     """ Tests addition to empty Structure """
     s1 = create_random_structure(parametrized=True)
     s2 = structure.Structure()
     s2 += s1
     self._check_sum(s2, structure.Structure(), s1)
Example #23
0
    def testAddNotParametrized(self):
        """ Tests addition of two non-parametrized Structure instances """
        s1 = create_random_structure(parametrized=False)
        s2 = create_random_structure(parametrized=False)
        self.assertFalse(bool(s1.bond_types))
        self.assertFalse(bool(s2.bond_types))
        s = s1 + s2
        self.assertIsNot(s, s1)
        self.assertIsNot(s, s2)
        # Make sure that s is really the sum of s1 and s2
        self.assertEqual(len(s.atoms), len(s1.atoms) + len(s2.atoms))
        self.assertEqual(len(s.residues), len(s1.residues) + len(s2.residues))

        def cmp_atoms(a1, a2):
            self.assertIsNot(a1, a2)
            self.assertEqual(a1.name, a2.name)
            self.assertEqual(a1.type, a2.type)
            self.assertEqual(a1.atom_type, a2.atom_type)
            self.assertEqual(a1.mass, a2.mass)
            self.assertEqual(a1.charge, a2.charge)
            self.assertEqual(a1.atomic_number, a2.atomic_number)
            self.assertEqual(a1.radii, a2.radii)
            self.assertEqual(a1.screen, a2.screen)
            self.assertEqual(a1.residue.name, a2.residue.name)
            self.assertEqual(a1.residue.insertion_code, a2.residue.insertion_code)
            self.assertEqual(len(a1.bond_partners), len(a2.bond_partners))
            self.assertEqual(len(a1.angle_partners), len(a2.angle_partners))
            self.assertEqual(len(a1.dihedral_partners), len(a2.dihedral_partners))
            self.assertEqual(len(a1.bonds), len(a2.bonds))
            self.assertEqual(len(a1.angles), len(a2.angles))
            self.assertEqual(len(a1.dihedrals), len(a2.dihedrals))
            self.assertEqual(len(a1.impropers), len(a2.impropers))

        for a1, a2 in zip(s.atoms, s1.atoms + s2.atoms):
            cmp_atoms(a1, a2)
        for r1, r2 in zip(s.residues, s1.residues + s2.residues):
            self.assertEqual(len(r1), len(r2))
            self.assertEqual(r1.name, r2.name)
            self.assertEqual(r1.chain, r2.chain)
            self.assertEqual(r1.insertion_code, r2.insertion_code)
        self.assertEqual(len(s.bonds), len(s1.bonds)+len(s2.bonds))
        self.assertEqual(len(s.angles), len(s1.angles)+len(s2.angles))
        self.assertEqual(len(s.dihedrals), len(s1.dihedrals)+len(s2.dihedrals))
        self.assertEqual(len(s.urey_bradleys), len(s1.urey_bradleys)+len(s2.urey_bradleys))
        self.assertEqual(len(s.impropers), len(s1.impropers)+len(s2.impropers))
        self.assertEqual(len(s.rb_torsions), len(s1.rb_torsions)+len(s2.rb_torsions))
        self.assertEqual(len(s.cmaps), len(s1.cmaps)+len(s2.cmaps))
        self.assertEqual(len(s.stretch_bends), len(s1.stretch_bends)+len(s2.stretch_bends))
        self.assertEqual(len(s.trigonal_angles), len(s1.trigonal_angles)+len(s2.trigonal_angles))
        self.assertEqual(len(s.out_of_plane_bends), len(s1.out_of_plane_bends)+len(s2.out_of_plane_bends))
        self.assertEqual(len(s.torsion_torsions), len(s1.torsion_torsions)+len(s2.torsion_torsions))
        self.assertEqual(len(s.acceptors), len(s1.acceptors)+len(s2.acceptors))
        self.assertEqual(len(s.donors), len(s1.donors)+len(s2.donors))
        self.assertEqual(len(s.pi_torsions), len(s1.pi_torsions)+len(s2.pi_torsions))
        self.assertEqual(len(s.chiral_frames), len(s1.chiral_frames)+len(s2.chiral_frames))
        self.assertEqual(len(s.multipole_frames), len(s1.multipole_frames)+len(s2.multipole_frames))
        self.assertEqual(len(s.groups), len(s1.groups)+len(s2.groups))
        self.assertEqual(len(s.adjusts), len(s1.adjusts)+len(s2.adjusts))
        self.assertEqual(len(s.adjust_types), len(s1.adjust_types)+len(s2.adjust_types))
        # Check all valence terms
        def chk_valence(val1, val2):
            self.assertIs(type(val1[0]), type(val2[0]))
            self.assertEqual(len(val1), len(val2))
            attrs = [attr for attr in dir(val1[0]) if attr.startswith('atom')]
            for v1, v2 in zip(val1, val2):
                at1 = [getattr(v1, attr) for attr in attrs]
                at2 = [getattr(v2, attr) for attr in attrs]
                self.assertIsNot(v1, v2)
                for a1, a2 in zip(at1, at2):
                    cmp_atoms(a1, a2)
        chk_valence(s.bonds, s1.bonds+s2.bonds)
        chk_valence(s.angles, s1.angles+s2.angles)
        chk_valence(s.dihedrals, s1.dihedrals+s2.dihedrals)
        chk_valence(s.rb_torsions, s1.rb_torsions+s2.rb_torsions)
        chk_valence(s.urey_bradleys, s1.urey_bradleys+s2.urey_bradleys)
        chk_valence(s.impropers, s1.impropers+s2.impropers)
        chk_valence(s.cmaps, s1.cmaps+s2.cmaps)
        chk_valence(s.trigonal_angles, s1.trigonal_angles+s2.trigonal_angles)
        chk_valence(s.out_of_plane_bends, s1.out_of_plane_bends+s2.out_of_plane_bends)
        chk_valence(s.pi_torsions, s1.pi_torsions+s2.pi_torsions)
        chk_valence(s.torsion_torsions, s1.torsion_torsions+s2.torsion_torsions)
        chk_valence(s.stretch_bends, s1.stretch_bends+s2.stretch_bends)
        chk_valence(s.chiral_frames, s1.chiral_frames+s2.chiral_frames)
        chk_valence(s.multipole_frames, s1.multipole_frames+s2.multipole_frames)
        chk_valence(s.donors, s1.donors+s2.donors)
        chk_valence(s.acceptors, s1.acceptors+s2.acceptors)
        chk_valence(s.groups, s1.groups+s2.groups)