Regions¶
Regions are ‘groups’ of atoms within a ChemicalSystem. Regions are used for some of the AMS driver and its engines features, but they can also be useful tools for bookkeeping and manipulations (see also the AMS documentation on Regions).
Here is a simple example showing how to create and use regions:
from scm.libbase import ChemicalSystem
import numpy as np
# Create a ChemicalSystem and define two regions (one for each water molecule)
mol = ChemicalSystem(
"""
System
Atoms
O -2.676678 0.759085 0.370636 region=water_1
H -3.468900 0.415690 0.814339 region=water_1
H -3.005004 1.433129 -0.246320 region=water_1
O 0.039085 0.303872 1.265871 region=water_2
H -0.874303 0.483757 0.975166 region=water_2
H 0.293563 -0.534617 0.849654 region=water_2
End
End
"""
)
# Translate all the atoms in the region "water_2"
for i_atom in mol.get_atoms_in_region("water_2"):
mol.atoms[i_atom].coords += np.array([1, 0, 0])
Region names are case-sensitive and may not include certain characters.
If a string is a valid name for a region can be checked with the is_valid_region_name method:
- classmethod ChemicalSystem.is_valid_region_name(name: str) bool
Checks if a string is a valid region name.
Valid region names do not contain any of the following characters:
, + - * / \ | $ & ^ < > ( ) [ ] { } " 'Valid region names do not have leading or trailing whitespace. Note that region names are case-sensitive, so “A” and “a” correspond to different regions.
There are various methods for querying region information:
- property ChemicalSystem.num_regions: int
Returns the number of regions used in the system.
Note that there is no such thing as an empty region. Every region contains at least one atom.
- property ChemicalSystem.region_names: List[str]
Returns an ASCIIbetically ordered list of the names of all regions in the system.
Note that there is no such thing as an empty region. Every region contains at least one atom.
- ChemicalSystem.has_region(region: str) bool
Checks if a region exists in the system, given its region name.
Note that region should be a valid region name, not a region expression. If you want to check if a region expression contains any atoms, use
num_atoms_in_region(...) > 0instead.
- ChemicalSystem.do_regions_intersect(regionA: str, regionB: str) bool
Checks if two regions or region expressions intersect, i.e. have at least one atom in common.
- ChemicalSystem.num_atoms_in_region(region: str) int
Returns the number of atoms in a region or region expression.
Returns zero if the region does not exist at all, or if the region expression evaluates to an empty set.
- ChemicalSystem.num_atoms_outside_region(region: str) int
Returns the number of atoms outside of a region or region expression.
Returns the total number of atoms in the system if the region does not exist at all, or if the region expression evaluates to an empty set.
- ChemicalSystem.get_atoms_in_region(region: str) ndarray[Any, dtype[int64]]
Returns a sorted array of atom indices of all atoms in a region or region expression.
- ChemicalSystem.get_atoms_outside_region(region: str) ndarray[Any, dtype[int64]]
Returns a sorted array of atom indices of all atoms outside of a region or region expression.
- ChemicalSystem.is_atom_in_region(atom: int | Atom, region: str) bool
Checks if an atom is in a region or region expression.
- ChemicalSystem.is_atom_outside_region(atom: int | Atom, region: str) bool
Checks if an atom is outside of a region or region expression.
- ChemicalSystem.get_regions_of_atom(atom: int | Atom) List[str]
Returns an ASCIIbetically sorted list of the names of all regions an atom is part of.
Almost all methods for querying region information also support so called region expressions in addition to plain
region names. Region expressions may include region names, the parentheses (), as well as the operators
+ for union, - for set difference and & for set intersection. Additionally the wildcard * means all
atoms, while $ stands for the set of selected atoms.
# number of atoms that are either in region A or B (or both)
num_at_AB = mol.num_atoms_in_region("A + B")
# loop over all atoms that are not in the intersection of region A and B
for atidx in mol.get_atoms_in_region("* - (A & B)"):
...
The following method can be used to extract the used regions from a region expression:
- classmethod ChemicalSystem.get_operands_in_region_expression(region_expression: str) List[str]
Returns an ASCIIbetically ordered list of all unique operands used in a region expression.
Operands are either names of regions, or the special operands
*representing all atoms, or$representing the set of selected atoms.
The following methods can be used to change the assignment of atoms to regions:
- ChemicalSystem.set_atoms_in_region(atom_indices: ArrayLike, region: str) None
Creates or sets an entire region given the indices of the atoms to be part of the region.
If atom_indices is empty and the region previously existed, it will effectively be deleted.
- ChemicalSystem.add_atoms_to_region(atom_indices: ArrayLike, region: str) None
Adds multiple atoms to a region, given their atom indices.
- ChemicalSystem.add_all_atoms_to_region(region: str) None
Adds all of the system’s atoms to a region.
- ChemicalSystem.remove_atoms_from_region(atom_indices: ArrayLike, region: str) None
Removes multiple atoms from a region, given their atom indices.
No error is raised if any of the atoms is not part of the region.
- ChemicalSystem.remove_region(region: str) None
Removes a region. Atoms in that region will keep existing, but will not longer be part of that region.
- ChemicalSystem.remove_all_regions() None
All atoms will keep existing, but will not longer be part of any region.
- ChemicalSystem.add_atom_to_region(atom: int | Atom, region: str) None
Adds an atom to a region.
- ChemicalSystem.remove_atom_from_region(atom: int | Atom, region: str) None
Removes an atom from a region.
Throws a ChemicalSystemError if the atom was not part of the region it should be removed from.
- ChemicalSystem.remove_atom_from_all_regions(atom: int | Atom) None
Removes an atom from all regions.