diff --git a/mbuild/compound.py b/mbuild/compound.py index 261f3b8ea..70f15fa42 100644 --- a/mbuild/compound.py +++ b/mbuild/compound.py @@ -127,17 +127,10 @@ class Compound(object): compound is the root of the containment hierarchy. referrers : set Other compounds that reference this part with labels. - rigid_id : int, default=None - The ID of the rigid body that this Compound belongs to. Only Particles - (the bottom of the containment hierarchy) can have integer values for - `rigid_id`. Compounds containing rigid particles will always have - `rigid_id == None`. See also `contains_rigid`. boundingbox : mb.Box The bounds (xmin, xmax, ymin, ymax, zmin, zmax) of particles in Compound center - contains_rigid mass - max_rigid_id n_particles n_bonds root @@ -183,10 +176,6 @@ def __init__( self.port_particle = port_particle - self._rigid_id = None - self._contains_rigid = False - self._check_if_contains_rigid_bodies = False - self.element = element if mass and float(mass) < 0.0: raise ValueError("Cannot set a Compound mass value less than zero") @@ -583,230 +572,6 @@ def charge(self, value): "not at the bottom of the containment hierarchy." ) - @property - def rigid_id(self): - """Get the rigid_id of the Compound.""" - return self._rigid_id - - @rigid_id.setter - def rigid_id(self, value): - if self._contains_only_ports(): - self._rigid_id = value - for ancestor in self.ancestors(): - ancestor._check_if_contains_rigid_bodies = True - else: - raise AttributeError( - "rigid_id is immutable for Compounds that are " - "not at the bottom of the containment hierarchy." - ) - - @property - def contains_rigid(self): - """Return True if the Compound contains rigid bodies. - - If the Compound contains any particle with a rigid_id != None - then contains_rigid will return True. If the Compound has no - children (i.e. the Compound resides at the bottom of the containment - hierarchy) then contains_rigid will return False. - - Returns - ------- - bool, - True if the Compound contains any particle with a rigid_id != None - - Notes - ----- - The private variable '_check_if_contains_rigid_bodies' is used to help - cache the status of 'contains_rigid'. - If '_check_if_contains_rigid_bodies' is False, then the rigid body - containment of the Compound has not changed, and the particle tree is - not traversed, boosting performance. - """ - if self._check_if_contains_rigid_bodies: - self._check_if_contains_rigid_bodies = False - if any(p.rigid_id is not None for p in self._particles()): - self._contains_rigid = True - else: - self._contains_rigid = False - return self._contains_rigid - - @property - def max_rigid_id(self): - """Return the maximum rigid body ID contained in the Compound. - - This is usually used by compound.root to determine the maximum - rigid_id in the containment hierarchy. - - Returns - ------- - int or None - The maximum rigid body ID contained in the Compound. If no - rigid body IDs are found, None is returned - """ - try: - return max( - [p.rigid_id for p in self.particles() if p.rigid_id is not None] - ) - except ValueError: - return - - def rigid_particles(self, rigid_id=None): - """Generate all particles in rigid bodies. - - If a rigid_id is specified, then this function will only yield particles - with a matching rigid_id. - - Parameters - ---------- - rigid_id : int, optional - Include only particles with this rigid body ID - - Yields - ------ - mb.Compound - The next particle with a rigid_id that is not None, or the next - particle with a matching rigid_id if specified - """ - for particle in self.particles(): - if rigid_id is not None: - if particle.rigid_id == rigid_id: - yield particle - else: - if particle.rigid_id is not None: - yield particle - - def label_rigid_bodies(self, discrete_bodies=None, rigid_particles=None): - """Designate which Compounds should be treated as rigid bodies. - - If no arguments are provided, this function will treat the compound - as a single rigid body by providing all particles in `self` with the - same rigid_id. If `discrete_bodies` is not None, each instance of - a Compound with a name found in `discrete_bodies` will be treated as a - unique rigid body. If `rigid_particles` is not None, only Particles - (Compounds at the bottom of the containment hierarchy) matching this - name will be considered part of the rigid body. - - Parameters - ---------- - discrete_bodies : str or list of str, optional, default=None - Name(s) of Compound instances to be treated as unique rigid bodies. - Compound instances matching this (these) name(s) will be provided - with unique rigid_ids - rigid_particles : str or list of str, optional, default=None - Name(s) of Compound instances at the bottom of the containment - hierarchy (Particles) to be included in rigid bodies. Only Particles - matching this (these) name(s) will have their rigid_ids altered to - match the rigid body number. - - Examples - -------- - Creating a rigid benzene - - >>> import mbuild as mb - >>> from mbuild.utils.io import get_fn - >>> benzene = mb.load(get_fn('benzene.mol2')) - >>> benzene.label_rigid_bodies() - - Creating a semi-rigid benzene, where only the carbons are treated as - a rigid body - - >>> import mbuild as mb - >>> from mbuild.utils.io import get_fn - >>> benzene = mb.load(get_fn('benzene.mol2')) - >>> benzene.label_rigid_bodies(rigid_particles='C') - - Create a box of rigid benzenes, where each benzene has a unique rigid - body ID. - - >>> import mbuild as mb - >>> from mbuild.utils.io import get_fn - >>> benzene = mb.load(get_fn('benzene.mol2')) - >>> benzene.name = 'Benzene' - >>> filled = mb.fill_box(benzene, - ... n_compounds=10, - ... box=[0, 0, 0, 4, 4, 4]) - >>> filled.label_rigid_bodies(distinct_bodies='Benzene') - - Create a box of semi-rigid benzenes, where each benzene has a unique - rigid body ID and only the carbon portion is treated as rigid. - - >>> import mbuild as mb - >>> from mbuild.utils.io import get_fn - >>> benzene = mb.load(get_fn('benzene.mol2')) - >>> benzene.name = 'Benzene' - >>> filled = mb.fill_box(benzene, - ... n_compounds=10, - ... box=[0, 0, 0, 4, 4, 4]) - >>> filled.label_rigid_bodies(distinct_bodies='Benzene', - ... rigid_particles='C') - """ - if discrete_bodies is not None: - if isinstance(discrete_bodies, str): - discrete_bodies = [discrete_bodies] - if rigid_particles is not None: - if isinstance(rigid_particles, str): - rigid_particles = [rigid_particles] - - if self.root.max_rigid_id is not None: - rigid_id = self.root.max_rigid_id + 1 - warn( - f"{rigid_id} rigid bodies already exist. Incrementing 'rigid_id'" - f"starting from {rigid_id}." - ) - else: - rigid_id = 0 - - for successor in self.successors(): - if discrete_bodies and successor.name not in discrete_bodies: - continue - for particle in successor.particles(): - if rigid_particles and particle.name not in rigid_particles: - continue - particle.rigid_id = rigid_id - if discrete_bodies: - rigid_id += 1 - - def unlabel_rigid_bodies(self): - """Remove all rigid body labels from the Compound.""" - self._check_if_contains_rigid_bodies = True - for child in self.children: - child._check_if_contains_rigid_bodies = True - for particle in self.particles(): - particle.rigid_id = None - - def _increment_rigid_ids(self, increment): - """Increment the rigid_id of all rigid Particles in a Compound. - - Adds `increment` to the rigid_id of all Particles in `self` that - already have an integer rigid_id. - """ - for particle in self.particles(): - if particle.rigid_id is not None: - particle.rigid_id += increment - - def _reorder_rigid_ids(self): - """Reorder rigid body IDs ensuring consecutiveness. - - Primarily used internally to ensure consecutive rigid_ids following - removal of a Compound. - """ - max_rigid = self.max_rigid_id - unique_rigid_ids = sorted( - set([p.rigid_id for p in self.rigid_particles()]) - ) - n_unique_rigid = len(unique_rigid_ids) - if max_rigid and n_unique_rigid != max_rigid + 1: - missing_rigid_id = ( - unique_rigid_ids[-1] * (unique_rigid_ids[-1] + 1) - ) / 2 - sum(unique_rigid_ids) - for successor in self.successors(): - if successor.rigid_id is not None: - if successor.rigid_id > missing_rigid_id: - successor.rigid_id -= 1 - if self.rigid_id: - if self.rigid_id > missing_rigid_id: - self.rigid_id -= 1 - def add( self, new_child, @@ -815,7 +580,6 @@ def add( replace=False, inherit_periodicity=None, inherit_box=False, - reset_rigid_ids=True, check_box_size=True, ): """Add a part to the Compound. @@ -840,11 +604,6 @@ def add( Compound being added inherit_box: bool, optional, default=False Replace the box of self with the box of the Compound being added - reset_rigid_ids : bool, optional, default=True - If the Compound to be added contains rigid bodies, reset the - rigid_ids such that values remain distinct from rigid_ids - already present in `self`. Can be set to False if attempting - to add Compounds to an existing rigid body. check_box_size : bool, optional, default=True Checks and warns if compound box is smaller than its bounding box after adding new_child. """ @@ -894,15 +653,10 @@ def add( self.add( child, label=label_list[i], - reset_rigid_ids=reset_rigid_ids, check_box_size=False, ) else: - self.add( - child, - reset_rigid_ids=reset_rigid_ids, - check_box_size=False, - ) + self.add(child, check_box_size=False) return @@ -919,13 +673,6 @@ def add( ) self._mass = 0 - if new_child.contains_rigid or new_child.rigid_id is not None: - if self.contains_rigid and reset_rigid_ids: - new_child._increment_rigid_ids(increment=self.max_rigid_id + 1) - self._check_if_contains_rigid_bodies = True - if self.rigid_id is not None: - self.rigid_id = None - # Create children and labels on the first add operation if self.children is None: self.children = list() @@ -1067,7 +814,7 @@ def _check_if_empty(child): for particle in particles_to_remove: _check_if_empty(particle) - # Fix rigid_ids and remove obj from bondgraph + # Remove obj from bondgraph for removed_part in to_remove: self._remove(removed_part) @@ -1077,11 +824,6 @@ def _check_if_empty(child): removed_part.parent.children.remove(removed_part) self._remove_references(removed_part) - # Check and reorder rigid id - for _ in particles_to_remove: - if self.contains_rigid: - self.root._reorder_rigid_ids() - # Remove ghost ports self._prune_ghost_ports() @@ -1148,10 +890,7 @@ def _prune_ghost_ports(self): self._remove_references(port) def _remove(self, removed_part): - """Worker for remove(). Fixes rigid IDs and removes bonds.""" - if removed_part.rigid_id is not None: - for ancestor in removed_part.ancestors(): - ancestor._check_if_contains_rigid_bodies = True + """Worker for remove(). Removes bonds.""" if self.root.bond_graph.has_node(removed_part): for neighbor in nx.neighbors( self.root.bond_graph.copy(), removed_part @@ -3600,12 +3339,7 @@ def _clone(self, clone_of=None, root_container=None): newone._pos = deepcopy(self._pos) newone.port_particle = deepcopy(self.port_particle) newone._box = deepcopy(self._box) - newone._check_if_contains_rigid_bodies = deepcopy( - self._check_if_contains_rigid_bodies - ) newone._periodicity = deepcopy(self._periodicity) - newone._contains_rigid = deepcopy(self._contains_rigid) - newone._rigid_id = deepcopy(self._rigid_id) newone._charge = deepcopy(self._charge) newone._mass = deepcopy(self._mass) if hasattr(self, "index"): diff --git a/mbuild/conversion.py b/mbuild/conversion.py index 6d42091ab..7cb168017 100644 --- a/mbuild/conversion.py +++ b/mbuild/conversion.py @@ -36,7 +36,6 @@ def load( relative_to_module=None, compound=None, coords_only=False, - rigid=False, smiles=False, infer_hierarchy=True, backend=None, @@ -68,8 +67,6 @@ def load( will be added to the existing compound as a sub compound. coords_only : bool, optional, default=False Only load the coordinates into an existing compound. - rigid : bool, optional, default=False - Treat the compound as a rigid body backend : str, optional, default=None Backend used to load structure from file or string. If not specified, a default backend (extension specific) will be used. @@ -103,7 +100,6 @@ def load( obj=filename_or_object, compound=compound, coords_only=coords_only, - rigid=rigid, infer_hierarchy=infer_hierarchy, **kwargs, ) @@ -126,7 +122,6 @@ def load( relative_to_module=relative_to_module, compound=compound, coords_only=coords_only, - rigid=rigid, backend=backend, infer_hierarchy=infer_hierarchy, **kwargs, @@ -137,7 +132,6 @@ def load_object( obj, compound=None, coords_only=False, - rigid=False, infer_hierarchy=True, **kwargs, ): @@ -156,8 +150,6 @@ def load_object( The host mbuild Compound coords_only : bool, optional, default=False Only load the coordinates into existing compound. - rigid : bool, optional, default=False - Treat the compound as a rigid body infer_hierarchy : bool, optional, default=True If True, infer hiereachy from chains and residues **kwargs : keyword arguments @@ -200,8 +192,6 @@ def load_object( infer_hierarchy=infer_hierarchy, **kwargs, ) - if rigid: - compound.label_rigid_bodies() return compound # If nothing is return raise an error @@ -323,7 +313,6 @@ def load_file( relative_to_module=None, compound=None, coords_only=False, - rigid=False, backend=None, infer_hierarchy=True, **kwargs, @@ -348,8 +337,6 @@ def load_file( will be added to the existing compound as a sub compound. coords_only : bool, optional, default=False Only load the coordinates into an existing compound. - rigid : bool, optional, default=False - Treat the compound as a rigid body backend : str, optional, default=None Backend used to load structure from file. If not specified, a default backend (extension specific) will be used. @@ -462,8 +449,6 @@ def load_file( ) # Note: 'Input not supported' error will be handled # by the corresponding backend - if rigid: - compound.label_rigid_bodies() return compound @@ -1199,7 +1184,6 @@ def to_hoomdsnapshot( identify_connections=True, ref_distance=1.0, ref_mass=1.0, - rigid_bodies=None, shift_coords=True, write_special_pairs=True, **kwargs, @@ -1216,11 +1200,6 @@ def to_hoomdsnapshot( Reference distance for conversion to reduced units ref_mass : float, optional, default=1.0 Reference mass for conversion to reduced units - rigid_bodies : list of int, optional, default=None - List of rigid body information. An integer value is required for each - atom corresponding to the index of the rigid body the particle is to be - associated with. A value of None indicates the atom is not part of a - rigid body. shift_coords : bool, optional, default=True Shift coordinates from (0, L) to (-L/2, L/2) if necessary. write_special_pairs : bool, optional, default=True @@ -1249,7 +1228,6 @@ def to_hoomdsnapshot( snapshot, refs = to_gsd_snapshot( top=gmso_top, base_units=base_units, - rigid_bodies=rigid_bodies, shift_coords=shift_coords, parse_special_pairs=write_special_pairs, auto_scale=False, diff --git a/mbuild/tests/base_test.py b/mbuild/tests/base_test.py index e58394dd1..2bcfd4697 100644 --- a/mbuild/tests/base_test.py +++ b/mbuild/tests/base_test.py @@ -23,13 +23,6 @@ def methane(self): return Methane() - @pytest.fixture - def benzene(self): - benzene = mb.load("C1=CC=CC=C1", smiles=True) - benzene.name = "Benzene" - - return benzene - @pytest.fixture def h2o(self): from mbuild.lib.moieties import H2O @@ -123,10 +116,15 @@ def sixpoints(self): return molecule @pytest.fixture - def rigid_benzene(self): + def benzene(self): compound = mb.load(get_fn("benzene.mol2")) compound.name = "Benzene" - compound.label_rigid_bodies() + return compound + + @pytest.fixture + def benzene_from_SMILES(self): + compound = mb.load("c1ccccc1", smiles=True) + compound.name = "Benzene" return compound @pytest.fixture @@ -166,27 +164,8 @@ def box_of_benzenes(self, benzene): filled = mb.fill_box( benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] ) - filled.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) return filled - @pytest.fixture - def rigid_ch(self): - ch = mb.load(get_fn("ch.mol2")) - ch.name = "CH" - ch.label_rigid_bodies() - ch.translate(-ch[0].pos) - ch.add(mb.Port(anchor=ch[0]), "a") - ch["a"].translate([0, 0.07, 0]) - ch["a"].rotate(120.0 * (np.pi / 180.0), around=np.asarray([0, 0, 1])) - - ch.add(mb.Port(anchor=ch[0]), "b") - ch["b"].translate([0, 0.07, 0]) - ch["b"].rotate(-120.0 * (np.pi / 180.0), around=np.asarray([0, 0, 1])) - - return ch - @pytest.fixture def silane(self): from mbuild.lib.moieties import Silane diff --git a/mbuild/tests/test_compound.py b/mbuild/tests/test_compound.py index 376f1eb6f..aee4490db 100644 --- a/mbuild/tests/test_compound.py +++ b/mbuild/tests/test_compound.py @@ -1452,7 +1452,7 @@ def test_resnames_parmed(self, h2o, ethane): struct.atoms ) - def test_resnames_parmed_cg(self, benzene, hexane, propyl): + def test_resnames_parmed_cg(self, benzene_from_SMILES, hexane, propyl): particles = [propyl.__class__] cg = mb.coarse_grain(hexane, particle_classes=particles) @@ -1507,7 +1507,11 @@ def test_resnames_parmed_cg(self, benzene, hexane, propyl): # test mixed cg atomistic systems mixed_molecules_box = mb.Compound( - [mb.clone(bonded_beads), mb.clone(bonded_beads), benzene] + [ + mb.clone(bonded_beads), + mb.clone(bonded_beads), + benzene_from_SMILES, + ] ) struct = mixed_molecules_box.to_parmed( infer_residues=True, @@ -1520,8 +1524,8 @@ def test_resnames_parmed_cg(self, benzene, hexane, propyl): [ mb.clone(two_bonded_beads), mb.clone(two_bonded_beads), - mb.clone(benzene), - mb.clone(benzene), + mb.clone(benzene_from_SMILES), + mb.clone(benzene_from_SMILES), mb.fill_box(hexane, 2, box=mb.Box([5, 5, 5])), ] ) @@ -1551,7 +1555,7 @@ def test_resnames_parmed_cg(self, benzene, hexane, propyl): # hexane is goes from polymer down to monomer level. Made from two propyl groups which gives two monomers (4 total) assert len( struct.residues - ) == 2 * two_bonded_beads.n_particles + 2 * benzene.n_particles + 2 * len( + ) == 2 * two_bonded_beads.n_particles + 2 * benzene_from_SMILES.n_particles + 2 * len( hexane.children ) @@ -2560,9 +2564,9 @@ def test_elements_from_smiles(self, backend): for particle in mol.particles(): assert particle.element is not None - def test_mins_maxs(self, rigid_benzene): - assert np.allclose(rigid_benzene.mins, [-0.2267, -0.15422, 0.0]) - assert np.allclose(rigid_benzene.maxs, [0.20318, 0.34207, 0.0]) + def test_mins_maxs(self, ethane): + assert np.allclose(ethane.mins, [-0.10699999, -0.21690001, -0.0993]) + assert np.allclose(ethane.maxs, [0.10699999, 0.07690001, 0.0653]) def test_periodicity_raises(self): with pytest.raises(ValueError): diff --git a/mbuild/tests/test_rigid.py b/mbuild/tests/test_rigid.py deleted file mode 100644 index d3739bd0a..000000000 --- a/mbuild/tests/test_rigid.py +++ /dev/null @@ -1,618 +0,0 @@ -import numpy as np -import pytest - -import mbuild as mb -from mbuild.tests.base_test import BaseTest -from mbuild.utils.io import has_hoomd - - -class TestRigid(BaseTest): - def test_load_rigid(self, rigid_benzene): - assert rigid_benzene.contains_rigid is True - assert rigid_benzene[0].contains_rigid is False - assert rigid_benzene.rigid_id is None - assert rigid_benzene.max_rigid_id is 0 - assert len(list(rigid_benzene.rigid_particles(rigid_id=0))) == 12 - - def test_load_nonrigid(self, benzene): - assert benzene.contains_rigid is False - assert benzene.rigid_id is None - assert benzene.max_rigid_id is None - assert len(list(benzene.rigid_particles())) == 0 - - def test_rigid_from_parts(self, rigid_ch): - rigid_ch_copy = mb.clone(rigid_ch) - benzene = mb.Compound() - benzene.add(rigid_ch_copy) - current = rigid_ch_copy - - for _ in range(5): - ch_new = mb.clone(rigid_ch) - mb.force_overlap( - move_this=ch_new, - from_positions=ch_new["a"], - to_positions=current["b"], - ) - current = ch_new - benzene.add(ch_new, reset_rigid_ids=False) - - carbons = [p for p in benzene.particles_by_name("C")] - benzene.add_bond((carbons[0], carbons[-1])) - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene.children[0].contains_rigid == True - assert benzene.children[0].rigid_id is None - assert len(list(benzene.rigid_particles(rigid_id=0))) == 12 - - def test_rigid_from_parts2(self, rigid_ch): - rigid_ch_copy = mb.clone(rigid_ch) - benzene = mb.Compound() - benzene.add(rigid_ch_copy, reset_rigid_ids=False) - current = rigid_ch_copy - - for _ in range(5): - ch_new = mb.clone(rigid_ch) - mb.force_overlap( - move_this=ch_new, - from_positions=ch_new["a"], - to_positions=current["b"], - ) - current = ch_new - benzene.add(ch_new, reset_rigid_ids=False) - - carbons = [p for p in benzene.particles_by_name("C")] - benzene.add_bond((carbons[0], carbons[-1])) - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene.children[0].contains_rigid == True - assert benzene.children[0].rigid_id is None - assert len(list(benzene.rigid_particles(rigid_id=0))) == 12 - - def test_rigid_from_parts3(self, rigid_ch): - rigid_ch_copy = mb.clone(rigid_ch) - benzene = mb.Compound() - benzene.add(rigid_ch_copy) - current = rigid_ch_copy - - for _ in range(5): - ch_new = mb.clone(rigid_ch) - mb.force_overlap( - move_this=ch_new, - from_positions=ch_new["a"], - to_positions=current["b"], - ) - current = ch_new - benzene.add(ch_new) - - carbons = [p for p in benzene.particles_by_name("C")] - benzene.add_bond((carbons[0], carbons[-1])) - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 5 - assert benzene.children[0].contains_rigid == True - assert benzene.children[0].rigid_id is None - for rigid_id in range(6): - assert len(list(benzene.rigid_particles(rigid_id=rigid_id))) == 2 - - def test_nonrigid_from_parts(self, benzene_from_parts): - assert benzene_from_parts.contains_rigid is False - assert benzene_from_parts.rigid_id is None - assert benzene_from_parts.max_rigid_id is None - assert len(list(benzene_from_parts.rigid_particles())) == 0 - - def test_label_rigid_bodies_single_partial(self, benzene): - benzene.label_rigid_bodies(rigid_particles="C") - - assert benzene.contains_rigid == True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert len(list(benzene.rigid_particles())) == 6 - assert len(list(benzene.rigid_particles(rigid_id=0))) == 6 - - @pytest.mark.skipif(not has_hoomd, reason="HOOMD not installed.") - def test_save_non_sequential_rigid_ids(self, benzene): - n_benzenes = 10 - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies(discrete_bodies="Benzene") - filled.children[0]._increment_rigid_ids(increment=3) - with pytest.warns(UserWarning): - filled.save("benzene-box.gsd") - - def test_increment_rigid_id(self, rigid_benzene): - compound = mb.Compound() - rigid_benzene2 = mb.clone(rigid_benzene) - compound.add(rigid_benzene) - compound.add(rigid_benzene2) - - assert rigid_benzene.contains_rigid is True - assert rigid_benzene.rigid_id is None - assert rigid_benzene.max_rigid_id is 0 - assert rigid_benzene2.contains_rigid is True - assert rigid_benzene2.rigid_id is None - assert rigid_benzene2.max_rigid_id is 1 - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 1 - assert len(list(compound.rigid_particles(rigid_id=0))) == 12 - assert len(list(compound.rigid_particles(rigid_id=1))) == 12 - - def test_increment_rigid_id_partial(self, benzene): - compound = mb.Compound() - benzene.label_rigid_bodies(rigid_particles="C") - benzene2 = mb.clone(benzene) - compound.add(benzene) - compound.add(benzene2) - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is True - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is 1 - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 1 - assert len(list(compound.rigid_particles())) == 12 - assert len(list(compound.rigid_particles(rigid_id=0))) == 6 - assert len(list(compound.rigid_particles(rigid_id=1))) == 6 - - def test_turn_into_rigid_after_add(self, benzene): - compound = mb.Compound() - benzene2 = mb.clone(benzene) - compound.add(benzene) - compound.add(benzene2) - benzene.label_rigid_bodies() - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is False - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is None - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 0 - assert len(list(compound.rigid_particles())) == 12 - assert len(list(compound.rigid_particles(rigid_id=0))) == 12 - assert len(list(benzene.rigid_particles(rigid_id=0))) == 12 - assert len(list(benzene2.rigid_particles())) == 0 - - def test_turn_into_rigid_after_add_multi(self, benzene): - compound = mb.Compound() - benzene2 = mb.clone(benzene) - compound.add(benzene) - compound.add(benzene2) - benzene.label_rigid_bodies() - benzene2.label_rigid_bodies() - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is True - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is 1 - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 1 - assert len(list(compound.rigid_particles())) == 24 - assert len(list(compound.rigid_particles(rigid_id=0))) == 12 - assert len(list(compound.rigid_particles(rigid_id=1))) == 12 - assert len(list(benzene.rigid_particles(rigid_id=0))) == 12 - assert len(list(benzene2.rigid_particles(rigid_id=1))) == 12 - - def test_turn_into_rigid_after_add_parent(self, benzene): - compound = mb.Compound() - benzene2 = mb.clone(benzene) - compound.add(benzene) - compound.add(benzene2) - compound.label_rigid_bodies() - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is True - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is 0 - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 0 - assert len(list(compound.rigid_particles())) == 24 - assert len(list(compound.rigid_particles(rigid_id=0))) == 24 - assert len(list(benzene.rigid_particles(rigid_id=0))) == 12 - assert len(list(benzene2.rigid_particles(rigid_id=0))) == 12 - - def test_label_rigid_bodies_multi(self, benzene): - compound = mb.Compound() - benzene2 = mb.clone(benzene) - compound.add(benzene) - compound.add(benzene2) - compound.label_rigid_bodies(discrete_bodies="Benzene") - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is True - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is 1 - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 1 - assert len(list(compound.rigid_particles())) == 24 - assert len(list(compound.rigid_particles(rigid_id=0))) == 12 - assert len(list(compound.rigid_particles(rigid_id=1))) == 12 - assert len(list(benzene.rigid_particles(rigid_id=0))) == 12 - assert len(list(benzene2.rigid_particles(rigid_id=1))) == 12 - - def test_label_rigid_bodies_multi_partial(self, benzene): - compound = mb.Compound() - benzene2 = mb.clone(benzene) - compound.add(benzene) - compound.add(benzene2) - compound.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) - - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is True - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is 1 - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 1 - assert len(list(compound.rigid_particles())) == 12 - assert len(list(compound.rigid_particles(rigid_id=0))) == 6 - assert len(list(compound.rigid_particles(rigid_id=1))) == 6 - assert len(list(benzene.rigid_particles(rigid_id=0))) == 6 - assert len(list(benzene2.rigid_particles(rigid_id=1))) == 6 - - def test_fill_box_rigid(self, rigid_benzene): - n_benzenes = 10 - filled = mb.fill_box( - rigid_benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - - assert filled.contains_rigid is True - assert filled.rigid_id is None - assert filled.max_rigid_id == n_benzenes - 1 - assert ( - len(list(filled.rigid_particles())) - == n_benzenes * rigid_benzene.n_particles - ) - - def test_fill_box_semi_rigid(self, benzene): - n_benzenes = 10 - benzene.label_rigid_bodies(rigid_particles="C") - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - - assert filled.contains_rigid is True - assert filled.rigid_id is None - assert filled.max_rigid_id == n_benzenes - 1 - assert len(list(filled.rigid_particles())) == n_benzenes * 6 - - def test_label_rigid_bodies_after_fill(self, benzene): - n_benzenes = 10 - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies(discrete_bodies="Benzene") - - assert filled.contains_rigid is True - assert filled.rigid_id is None - assert filled.max_rigid_id == n_benzenes - 1 - assert ( - len(list(filled.rigid_particles())) - == n_benzenes * benzene.n_particles - ) - - def test_label_rigid_bodies_list(self, benzene): - n_benzenes = 10 - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.children[0].name = "Benzene0" - filled.children[1].name = "Benzene1" - filled.label_rigid_bodies(discrete_bodies=["Benzene0", "Benzene1"]) - - assert filled.contains_rigid is True - assert filled.rigid_id is None - assert filled.max_rigid_id == 1 - assert len(list(filled.rigid_particles())) == 2 * benzene.n_particles - - def test_label_rigid_bodies_list_particle_list(self, benzene): - n_benzenes = 10 - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.children[0].name = "Benzene0" - filled.children[1].name = "Benzene1" - filled.label_rigid_bodies( - discrete_bodies=["Benzene0", "Benzene1"], rigid_particles=["C", "H"] - ) - - assert filled.contains_rigid is True - assert filled.rigid_id is None - assert filled.max_rigid_id == 1 - assert len(list(filled.rigid_particles())) == 2 * benzene.n_particles - - def test_label_rigid_bodies_duplicate_warn(self, rigid_benzene): - with pytest.warns(UserWarning): - n_benzenes = 10 - filled = mb.fill_box( - rigid_benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies(discrete_bodies="Benzene") - - def test_label_semi_rigid_bodies_after_fill(self, benzene): - n_benzenes = 10 - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) - - assert filled.max_rigid_id == n_benzenes - 1 - assert len(list(filled.rigid_particles())) == n_benzenes * 6 - - def test_create_semi_rigid_bodies_hierarchy(self, benzene_from_parts): - n_benzenes = 10 - filled = mb.fill_box( - benzene_from_parts, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.name = "Benzene box" - filled2 = mb.clone(filled) - compound = mb.Compound(subcompounds=[filled, filled2]) - - compound.label_rigid_bodies(discrete_bodies="Benzene box") - assert compound.max_rigid_id == 1 - assert filled.max_rigid_id == 0 - assert filled2.max_rigid_id == 1 - assert len(list(compound.rigid_particles())) == n_benzenes * 2 * 12 - - compound.unlabel_rigid_bodies() - compound.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) - assert compound.max_rigid_id == (n_benzenes * 2) - 1 - assert filled.max_rigid_id == n_benzenes - 1 - assert filled2.max_rigid_id == (n_benzenes * 2) - 1 - assert len(list(compound.rigid_particles())) == n_benzenes * 2 * 6 - assert len(list(filled.rigid_particles())) == n_benzenes * 6 - assert len(list(filled2.rigid_particles())) == n_benzenes * 6 - - compound.unlabel_rigid_bodies() - compound.label_rigid_bodies(discrete_bodies="CH") - assert compound.max_rigid_id == (n_benzenes * 2 * 6) - 1 - assert filled.max_rigid_id == (n_benzenes * 6) - 1 - assert filled2.max_rigid_id == (n_benzenes * 2 * 6) - 1 - assert len(list(compound.rigid_particles())) == n_benzenes * 2 * 12 - assert len(list(filled.rigid_particles())) == n_benzenes * 12 - assert len(list(filled2.rigid_particles())) == n_benzenes * 12 - - def test_create_semi_rigid_bodies_filled_clone(self, benzene_from_parts): - n_benzenes = 10 - filled = mb.fill_box( - benzene_from_parts, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) - filled2 = mb.clone(filled) - filled.add(filled2) - - assert filled.max_rigid_id == (n_benzenes * 2) - 1 - assert len(list(filled.rigid_particles())) == n_benzenes * 2 * 6 - for rigid_id in range(n_benzenes * 2): - assert len(list(filled.rigid_particles(rigid_id=rigid_id))) == 6 - - def test_create_semi_rigid_bodies_filled_no_increment( - self, benzene_from_parts - ): - n_benzenes = 10 - filled = mb.fill_box( - benzene_from_parts, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) - filled2 = mb.clone(filled) - filled.add(filled2, reset_rigid_ids=False) - - assert filled.max_rigid_id == n_benzenes - 1 - assert len(list(filled.rigid_particles())) == n_benzenes * 2 * 6 - for rigid_id in range(n_benzenes): - assert len(list(filled.rigid_particles(rigid_id=rigid_id))) == 12 - - def test_delete_body(self, rigid_benzene): - n_benzenes = 10 - filled = mb.fill_box( - rigid_benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.remove(filled.children[0]) - - assert filled.max_rigid_id == n_benzenes - 2 - assert ( - len(list(filled.rigid_particles())) - == (n_benzenes - 1) * rigid_benzene.n_particles - ) - - def test_delete_body_particle_by_particle(self, rigid_benzene): - n_benzenes = 10 - filled = mb.fill_box( - rigid_benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - for particle in list(filled.children[0].particles()): - filled.remove(particle) - - assert filled.max_rigid_id == n_benzenes - 2 - assert ( - len(list(filled.rigid_particles())) - == (n_benzenes - 1) * rigid_benzene.n_particles - ) - - def test_delete_body_multiple(self, rigid_benzene): - n_benzenes = 10 - filled = mb.fill_box( - rigid_benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.remove([filled.children[0], filled.children[1]]) - - assert filled.max_rigid_id == n_benzenes - 3 - assert ( - len(list(filled.rigid_particles())) - == (n_benzenes - 2) * rigid_benzene.n_particles - ) - - def test_delete_body_all(self, rigid_benzene): - n_benzenes = 10 - filled = mb.fill_box( - rigid_benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - for i, child in enumerate(filled.children[:-1]): - filled.remove(child) - assert filled.max_rigid_id == n_benzenes - 1 - (i + 1) - assert ( - len(list(filled.rigid_particles())) - == (n_benzenes - (i + 1)) * rigid_benzene.n_particles - ) - assert filled.contains_rigid is True - - filled.remove(filled.children[0]) - assert filled.contains_rigid is False - assert filled.max_rigid_id is None - - def test_delete_body_semi_rigid(self, benzene): - n_benzenes = 10 - filled = mb.fill_box( - benzene, n_compounds=n_benzenes, box=[0, 0, 0, 4, 4, 4] - ) - filled.label_rigid_bodies( - discrete_bodies="Benzene", rigid_particles="C" - ) - filled.remove(filled.children[0]) - - assert filled.max_rigid_id == n_benzenes - 2 - assert len(list(filled.rigid_particles())) == (n_benzenes - 1) * 6 - - def test_rigid_with_subcompounds1(self, rigid_benzene): - compound = mb.Compound(subcompounds=rigid_benzene) - - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 0 - assert rigid_benzene.contains_rigid is True - assert rigid_benzene.rigid_id is None - assert rigid_benzene.max_rigid_id is 0 - assert len(list(compound.rigid_particles())) == 12 - assert len(list(compound.rigid_particles(rigid_id=0))) == 12 - - def test_rigid_with_subcompounds2(self, rigid_benzene): - rigid_benzene2 = mb.clone(rigid_benzene) - compound = mb.Compound(subcompounds=[rigid_benzene, rigid_benzene2]) - - assert compound.max_rigid_id is 1 - assert rigid_benzene.max_rigid_id is 0 - assert rigid_benzene2.max_rigid_id is 1 - assert len(list(compound.rigid_particles())) == 24 - assert len(list(compound.rigid_particles(rigid_id=0))) == 12 - assert len(list(compound.rigid_particles(rigid_id=1))) == 12 - - def test_rigid_with_subcompounds3(self, benzene): - benzene.label_rigid_bodies(rigid_particles="C") - compound = mb.Compound(subcompounds=benzene) - - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 0 - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert len(list(compound.rigid_particles())) == 6 - assert len(list(compound.rigid_particles(rigid_id=0))) == 6 - - def test_rigid_with_subcompounds4(self, benzene): - benzene.label_rigid_bodies(rigid_particles="C") - benzene2 = mb.clone(benzene) - compound = mb.Compound(subcompounds=[benzene, benzene2]) - - assert compound.contains_rigid is True - assert compound.rigid_id is None - assert compound.max_rigid_id is 1 - assert benzene.contains_rigid is True - assert benzene.rigid_id is None - assert benzene.max_rigid_id is 0 - assert benzene2.contains_rigid is True - assert benzene2.rigid_id is None - assert benzene2.max_rigid_id is 1 - assert len(list(compound.rigid_particles())) == 12 - assert len(list(compound.rigid_particles(rigid_id=0))) == 6 - assert len(list(compound.rigid_particles(rigid_id=1))) == 6 - - def test_rigid_with_subcompounds5(self, rigid_benzene): - rigid_benzene2 = mb.clone(rigid_benzene) - double = mb.Compound(subcompounds=[rigid_benzene, rigid_benzene2]) - double2 = mb.clone(double) - compound = mb.Compound(subcompounds=[double, double2]) - - assert compound.max_rigid_id is 3 - assert len(list(compound.rigid_particles())) == 48 - for rigid_id in range(4): - assert len(list(compound.rigid_particles(rigid_id=rigid_id))) == 12 - - def test_set_rigid_not_particle(self, benzene_from_parts): - benzene_from_parts.label_rigid_bodies(rigid_particles=["C", "H"]) - - assert benzene_from_parts.contains_rigid is True - assert benzene_from_parts.rigid_id is None - assert benzene_from_parts.max_rigid_id is 0 - assert len(list(benzene_from_parts.rigid_particles())) == 12 - assert len(list(benzene_from_parts.rigid_particles(rigid_id=0))) == 12 - - def test_manual_set_rigid_id(self, benzene): - benzene[0].rigid_id = 0 - assert benzene.contains_rigid is True - assert benzene[0].contains_rigid is False - assert benzene.max_rigid_id is 0 - assert len(list(benzene.rigid_particles())) == 1 - - def test_manual_set_rigid_id_error(self, benzene): - with pytest.raises(AttributeError): - benzene.rigid_id = 0 - - def test_build_from_single_particle(self): - compound = mb.Compound() - compound.rigid_id = 0 - atom = mb.Compound(name="atom") - atom.rigid_id = 0 - atom2 = mb.clone(atom) - compound.add([atom, atom2], reset_rigid_ids=False) - - assert compound.contains_rigid == True - assert compound.rigid_id is None - assert compound.max_rigid_id is 0 - assert len(list(compound.rigid_particles())) == 2 - - def test_build_from_single_particle2(self): - compound = mb.Compound() - compound.rigid_id = 0 - atom = mb.Compound(name="atom") - atom.rigid_id = 0 - atom2 = mb.clone(atom) - compound.add(atom) - compound.add(atom2, reset_rigid_ids=False) - - assert compound.contains_rigid == True - assert compound.rigid_id is None - assert compound.max_rigid_id is 0 - assert len(list(compound.rigid_particles())) == 2