Add#

Adding elements of a molecular system into another molecular system.

Elements coming from different molecular systems can be added to a given system with the molsysmt.basic.add() function.

Added in version 1.0.0.

How this function works#

API documentation

Follow this link for a detailed description of the input arguments, raised errors, and returned objects of this function: molsysmt.basic.add().

Let’s show how this function works with three peptides defined as three different molecular systems: proline dipeptide (\(A\)), valine dipeptide (\(B\)), and lysine dipeptide (\(C\)).

import molsysmt as msm
molsys_A = msm.build.build_peptide('AceProNme')
molsys_B = msm.build.build_peptide('AceValNme')
molsys_C = msm.build.build_peptide('AceLysNme')

Basic usage#

The molecular systems \(B\) and \(C\) need to be translated to avoid spatial overlap once their elements are added to \(A\) (since all systems are built centered around the origin).

molsys_B = msm.structure.translate(molsys_B, translation='[-1.0, 0.0, 0.0] nanometers')
molsys_C = msm.structure.translate(molsys_C, translation='[1.0, 0.0, 0.0] nanometers')

Let’s inspect how \(A\) is defined before adding \(B\) and \(C\):

msm.info(molsys_A)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_peptides n_structures
molsysmt.MolSys 26 3 1 1 1 1 1 1

Now let’s add the elements of \(B\) and \(C\) into \(A\):

msm.add(molsys_A, molsys_B)
msm.add(molsys_A, molsys_C)

Tip

All methods defined in the molsysmt.basic module can be invoked also from the main level of the library. Hence, molsysmt.add() is the same method as molsysmt.basic.add().

After the addition, we inspect \(A\) again. Notice the larger count of atoms, groups, and molecules:

msm.info(molsys_A, element='system')
form n_atoms n_groups n_components n_chains n_molecules n_entities n_peptides n_structures
molsysmt.MolSys 88 9 3 3 3 3 3 1

We can also visualize the combined system interactively. Try rotating and zooming to observe the spatial separation between \(A\), \(B\), and \(C\).

msm.view(molsys_A, standard=True)

Creating a new system (in_place=False)#

By default, msm.add modifies the target system in place. If you prefer not to modify the original system, pass in_place=False to return a new molecular system containing the combined elements:

molsys_D = msm.add(molsys_B, molsys_C, in_place=False)
msm.get(molsys_B, n_peptides=True)
1
msm.get(molsys_C, n_peptides=True)
1
msm.get(molsys_D, n_peptides=True)
2

Adding selected elements (selection)#

Instead of adding all elements from the source system, you can restrict the addition to a specific selection of atoms or residues using selection. For example, let’s add only the Lysine residue from \(C\) into \(B\):

molsys_E = msm.add(molsys_B, molsys_C, selection='group_name=="LYS"', in_place=False)
msm.info(molsys_E)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_peptides n_structures
molsysmt.MolSys 50 4 2 2 2 2 2 1

Specifying structure indices (structure_indices)#

When adding elements from a multi-structure source system into a target system with fewer structures, pass structure_indices to select which frame’s coordinates to add:

molsys_A1 = msm.build.build_peptide('AceProNme')
molsys_A2 = msm.structure.translate(molsys_A1, translation='[0.1, 0.1, 0.1] nanometers')
molsys_multi = msm.concatenate_structures([molsys_A1, molsys_A2])
molsys_F = msm.add(molsys_B, molsys_multi, structure_indices=0, in_place=False)
msm.info(molsys_F)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_peptides n_structures
molsysmt.MolSys 54 6 2 2 2 2 2 1

What is kept and what is dropped#

Adding atoms changes the system, and not every piece of structural data can survive that change. MolSysMT decides by what each value describes, not by how it is stored.

Data attached to each atom — coordinates, velocities, B factors, occupancy, force-field parameters — is concatenated when both systems have it. When only one of the two has it, there is no honest way to build a column covering all the atoms of the result, so the whole attribute is dropped and a StructuralAttributeDropWarning says which ones.

Data describing the structure axisstructure_id, time, time_step — is untouched, because msm.add grows the atom axis and leaves the structure axis exactly as it was.

The periodic box stays the one of the target system: msm.add never reinterprets the unit cell. If the two systems disagree, or if one is periodic and the other is not, an IncompatibleBoxWarning reports it. Coordinates expressed under a different box are not directly comparable, and combining them quietly would hide that from you.

Values describing the whole systemtemperature, potential_energy, kinetic_energy — are dropped. The energy of the target was computed for the target, and after adding atoms it is no longer the energy of anything. It is not the sum of the two either.

Let’s see it with a real case: T4 lysozyme read from a PDB file, which carries B factors and a unit cell, and a small peptide built from scratch, which carries neither.

molsys_G = msm.convert(msm.systems['T4 lysozyme L99A']['181l.pdb'], to_form='molsysmt.MolSys')
molsys_H = msm.build.build_peptide('AceAlaNme')

print('lysozyme has B factors:', msm.get(molsys_G, b_factor=True) is not None)
print('built peptide has B factors:', msm.get(molsys_H, b_factor=True) is not None)
lysozyme has B factors: True
built peptide has B factors: False
molsys_I = msm.add(molsys_G, molsys_H, in_place=False)

print('atoms in the result:', msm.get(molsys_I, n_atoms=True))
print('B factors survived:', msm.get(molsys_I, b_factor=True) is not None)
atoms in the result: 1463
B factors survived: False

The atoms were added and the B factors are gone: the peptide had none, and a column describing only the lysozyme half of the result would not be a B-factor series.

Refusing instead of dropping (attribute_policy)#

If losing the target’s data silently is not acceptable for your workflow, pass attribute_policy='strict'. The operation is then rejected before anything is modified, and both systems are left exactly as they were:

from molsysmt import StructuralInconsistencyError

try:
    msm.add(molsys_G, molsys_H, in_place=False, attribute_policy='strict')
except StructuralInconsistencyError as error:
    print('rejected:', error)

print('lysozyme still intact:', msm.get(molsys_G, n_atoms=True), 'atoms')
rejected: Structural inconsistency detected: These atom-aligned attributes are present on only one side, so the result would cover part of the atom axis: b_factor, occupancy; use attribute_policy='intersection' to discard them instead. Ensure that the atoms, residues, or frames match between the systems being compared or merged. Docs: https://www.uibcdf.org/MolSysMT
lysozyme still intact: 1441 atoms

Warning

msm.add takes one target and one source. A list is read as a single molecular system split into complementary items — a topology file next to a coordinate file, exactly as molsysmt.basic.convert() reads it — and is assembled before the addition. It is never a sequence of systems to add one after another. To add several sources, call molsysmt.basic.add() once per source.

A molecular system given as complementary items cannot be grown in place, because the assembled result is a new object. Use in_place=False in that case.

To combine several systems into a new one in a single call, see molsysmt.basic.merge() instead.

See also

Build peptide:
Build natural peptides with or without terminal caps.

Translate:
Translate entire molecular systems or specific selections in space.

Info:
Display a summary of the contents, topology, and structural data of a molecular system.

View:
Visualize a molecular system.

Get:
Retrieve attribute values from a molecular system.

Select:
Select elements from a molecular system to work with subsets of atoms, groups, or molecules.

Merge:
Combine multiple molecular systems by merging their elements into a new system.