diff --git a/package/CHANGELOG b/package/CHANGELOG index 41a3a09a4fa..03115e7ddff 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -61,6 +61,7 @@ Enhancements * added unwrap keyword to center_of_mass (PR #2286) * added unwrap keyword to moment_of_inertia (PR #2287) * added unwrap keyword to asphericity (PR #2290) + * added unwrap keyword to radius_of_gyration (PR #2299) Changes * added official support for Python 3.7 (PR #1963) diff --git a/package/MDAnalysis/core/topologyattrs.py b/package/MDAnalysis/core/topologyattrs.py index 5366bca67c8..4b571bd39f3 100644 --- a/package/MDAnalysis/core/topologyattrs.py +++ b/package/MDAnalysis/core/topologyattrs.py @@ -937,6 +937,7 @@ def moment_of_inertia(group, **kwargs): ('moment_of_inertia', moment_of_inertia)) @warn_if_not_unique + @check_pbc_and_unwrap def radius_of_gyration(group, **kwargs): """Radius of gyration. @@ -945,6 +946,10 @@ def radius_of_gyration(group, **kwargs): pbc : bool, optional If ``True``, move all atoms within the primary unit cell before calculation. [``False``] + unwrap : bool, optional + If ``True``, compounds will be unwrapped before computing their centers. + compound : {'group', 'segments', 'residues', 'molecules', 'fragments'}, optional + Which type of component to keep together during unwrapping. Note ---- @@ -953,15 +958,23 @@ def radius_of_gyration(group, **kwargs): .. versionchanged:: 0.8 Added *pbc* keyword + .. versionchanged:: 0.20.0 Added *unwrap* and *compound* parameter """ atomgroup = group.atoms pbc = kwargs.pop('pbc', flags['use_pbc']) masses = atomgroup.masses + unwrap = kwargs.pop('unwrap', False) + compound = kwargs.pop('compound', 'group') + + com = atomgroup.center_of_mass(pbc=pbc, unwrap=unwrap, compound=compound) + if compound is not 'group': + com = (com * group.masses[:, None]).sum(axis=0) / group.masses.sum() - com = atomgroup.center_of_mass(pbc=pbc) if pbc: recenteredpos = atomgroup.pack_into_box(inplace=False) - com + elif unwrap: + recenteredpos = atomgroup.unwrap(compound=compound) - com else: recenteredpos = atomgroup.positions - com diff --git a/testsuite/MDAnalysisTests/core/test_atomgroup.py b/testsuite/MDAnalysisTests/core/test_atomgroup.py index c17c3013233..72074c51666 100644 --- a/testsuite/MDAnalysisTests/core/test_atomgroup.py +++ b/testsuite/MDAnalysisTests/core/test_atomgroup.py @@ -859,6 +859,7 @@ def ref_noUnwrap_residues(self): [-211.8997285, 7059.07470427, -91.32156884], [-721.50785456, -91.32156884, 6509.31735029]]), 'Asph': 0.02060121, + 'ROG': 27.713009, } @pytest.fixture() @@ -874,6 +875,7 @@ def ref_Unwrap_residues(self): [-1330.489, 19315.253, 3306.212], [ 2938.243, 3306.212, 8990.481]]), 'Asph': 0.2969491080, + 'ROG': 40.686541, } @pytest.fixture() @@ -886,6 +888,7 @@ def ref_noUnwrap(self): [0.0, 98.6542, 0.0], [0.0, 0.0, 98.65421327]]), 'Asph': 1.0, + 'ROG': 0.9602093, } @pytest.fixture() @@ -898,6 +901,7 @@ def ref_Unwrap(self): [0.0, 132.673, 0.0], [0.0, 0.0, 132.673]]), 'Asph': 1.0, + 'ROG': 1.1135230, } def test_default_residues(self, ag, ref_noUnwrap_residues): @@ -905,12 +909,14 @@ def test_default_residues(self, ag, ref_noUnwrap_residues): assert_almost_equal(ag.center_of_mass(compound='residues'), ref_noUnwrap_residues['COM'], self.prec) assert_almost_equal(ag.moment_of_inertia(compound='residues'), ref_noUnwrap_residues['MOI'], self.prec) assert_almost_equal(ag.asphericity(compound='residues'), ref_noUnwrap_residues['Asph'], self.prec) + assert_almost_equal(ag.radius_of_gyration(compound='residues'), ref_noUnwrap_residues['ROG'], self.prec) def test_UnWrapFlag_residues(self, ag, ref_Unwrap_residues): assert_almost_equal(ag.center_of_geometry(unwrap=True, compound='residues'), ref_Unwrap_residues['COG'], self.prec) assert_almost_equal(ag.center_of_mass(unwrap=True, compound='residues'), ref_Unwrap_residues['COM'], self.prec) assert_almost_equal(ag.moment_of_inertia(unwrap=True, compound='residues'), ref_Unwrap_residues['MOI'], self.prec) assert_almost_equal(ag.asphericity(unwrap=True, compound='residues'), ref_Unwrap_residues['Asph'], self.prec) + assert_almost_equal(ag.radius_of_gyration(unwrap=True, compound='residues'), ref_Unwrap_residues['ROG'], self.prec) def test_default(self, ref_noUnwrap): u = UnWrapUniverse(is_triclinic=False) @@ -922,6 +928,7 @@ def test_default(self, ref_noUnwrap): assert_almost_equal(group.center_of_mass(), ref_noUnwrap['COM'], self.prec) assert_almost_equal(group.moment_of_inertia(), ref_noUnwrap['MOI'], self.prec) assert_almost_equal(group.asphericity(), ref_noUnwrap['Asph'], self.prec) + assert_almost_equal(group.radius_of_gyration(), ref_noUnwrap['ROG'], self.prec) def test_UnWrapFlag(self, ref_Unwrap): u = UnWrapUniverse(is_triclinic=False) @@ -932,6 +939,7 @@ def test_UnWrapFlag(self, ref_Unwrap): assert_almost_equal(group.center_of_mass(unwrap=True), ref_Unwrap['COM'], self.prec) assert_almost_equal(group.moment_of_inertia(unwrap=True), ref_Unwrap['MOI'], self.prec) assert_almost_equal(group.asphericity(unwrap=True), ref_Unwrap['Asph'], self.prec) + assert_almost_equal(group.radius_of_gyration(unwrap=True), ref_Unwrap['ROG'], self.prec) class TestPBCFlag(object):