Convert#

Converting a molecular system into another form or multiple forms.

In MolSysMT, a molecular system can be represented in many different forms (files, third-party objects, or native data structures). The function molsysmt.basic.convert() provides a form-agnostic way to convert a molecular system from any supported input form into any target form.

Added in version 1.0.0.

Basic usage#

Let’s explore how conversion works starting with single-item conversions, moving to composite multi-item inputs, and concluding with splitting systems into multiple output forms:

import molsysmt as msm

Let’s start with a single molecular system from the local dataset (181l.bcif.gz) and convert it across several forms:

molsys_A = msm.systems['T4 lysozyme L99A']['181l.bcif.gz']
molsys_B = msm.convert(molsys_A, to_form='molsysmt.MolSys')
molsys_C = msm.convert(molsys_B, to_form='string:pdb_text')
molsys_D = msm.convert(molsys_B, to_form='mdtraj.Trajectory')
molsys_E = msm.convert(molsys_D, to_form='openmm.Topology')

We can inspect the form of any converted system using molsysmt.basic.get_form() or msm.info():

msm.info(molsys_B)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_waters n_ions n_small_molecules n_proteins n_structures
molsysmt.MolSys 1441 302 141 6 141 5 136 2 2 1 1
msm.get_form(molsys_D)
'mdtraj.Trajectory'

Conversion can also be restricted to a specific atom selection. Here we convert only the benzene ligand of T4 lysozyme into a PDB text string:

molsys_sel = msm.convert(molsys_B, to_form='string:pdb_text', selection='molecule_name=="BENZENE"')
print(molsys_sel)
HEADER    MOLECULAR SYSTEM                        01-OCT-26       
REMARK   1 Created by MolSysMT version 1.0 on 01-OCT-2026 at 01:21:32
CRYST1   60.900   60.900   97.000  90.00  90.00 120.00
ATOM      1  C1  BNZ A 400      25.978   5.327   4.779  0.00 20.05           C  
ATOM      2  C2  BNZ A 400      26.395   5.074   3.499  0.00 21.25           C  
ATOM      3  C3  BNZ A 400      27.340   5.860   2.902  0.00 26.80           C  
ATOM      4  C4  BNZ A 400      27.837   6.921   3.569  0.00 21.02           C  
ATOM      5  C5  BNZ A 400      27.420   7.196   4.856  0.00 25.56           C  
ATOM      6  C6  BNZ A 400      26.498   6.379   5.469  0.00 26.48           C  
CONECT    1    2
CONECT    1    6
CONECT    2    3
CONECT    3    4
CONECT    4    5
CONECT    5    6
END

Multiple items into one#

Often a molecular system is split across multiple complementary files or objects—for instance, a topology file paired with coordinate or trajectory files. msm.convert accepts a list of items and merges their information into a single system.

First, consider an Amber topology (.prmtop) and its corresponding single-structure coordinate file (.inpcrd):

Complementary partial H5MSM 0.5 files and their loaded MolSys objects can also be composed before selections. Supplying the list declares positional correspondence; each domain has one provider and analysis names are distinct. Full atom/frame conflicts fail before extraction. Topology is copied for its single-owner contract, even when full-axis copy_if_all=False shares structures. Conversion loads the stored arrays. See H5MSM 0.5 for file composition and supported boundaries.

prmtop_file = msm.systems['pentalanine']['pentalanine.prmtop']
inpcrd_file = msm.systems['pentalanine']['pentalanine.inpcrd']

Let’s inspect the two input items individually:

msm.info(prmtop_file)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_waters n_peptides n_structures
file:prmtop 5207 1722 1716 1 1716 2 1715 1 None
msm.info(inpcrd_file)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_structures
file:inpcrd 5207 None None None None None 1

By passing both items as a list to msm.convert, we combine them into a single molsysmt.MolSys:

molsys_composite = msm.convert([prmtop_file, inpcrd_file], to_form='molsysmt.MolSys')
msm.info(molsys_composite)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_waters n_peptides n_structures
molsysmt.MolSys 5207 1722 1716 1 1716 2 1715 1 1

The same mechanism applies when combining a topology file (which may hold a single reference structure) with an item containing multiple structures (such as a DCD, XTC, or multi-conformer file). In this case, the multi-structure item dictates the resulting structure axis.

Let’s see this in action using a PSF topology and a DCD trajectory from the POPC membrane dataset:

psf_file = msm.systems['POPC membrane']['popc_membrane.psf']
dcd_file = msm.systems['POPC membrane']['popc_membrane.dcd']

When converting [psf_file, dcd_file], notice that the resulting system contains 5 structures (matching the DCD multi-structure file):

molsys_traj1 = msm.convert([psf_file, dcd_file], to_form='molsysmt.MolSys')
msm.info(molsys_traj1)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_waters n_small_molecules n_lipids n_structures
molsysmt.MolSys 78974 13532 13532 3 13239 70 13170 68 294 5

Crucially, the order in which items are listed is transparent. Swapping the order to [dcd_file, psf_file] produces the exact same system:

molsys_traj2 = msm.convert([dcd_file, psf_file], to_form='molsysmt.MolSys')
msm.compare(molsys_traj1, molsys_traj2, coordinates=True)
True

You can also combine separately held chemical states and structures without constructing a topology inventory. Here the dictionary preserves the chemical state collection, and the native Structures object supplies coordinates:

chemical_states = msm.convert(molsys_composite.chemical_states,
                              to_form='molsysmt.ChemicalStatesDict')
molsys_domains = msm.convert([chemical_states, molsys_composite.structures],
                            to_form='molsysmt.MolSys',
                            selection=[2, 0], structure_indices=[0])
print('Topology absent:', molsys_domains.topology is None)
print('Selected coordinate shape:', molsys_domains.structures.coordinates.shape)
print('Reference chemical state:',
      molsys_domains.chemical_states.reference_chemical_state_index)
assert molsys_domains.topology is None
assert molsys_domains.structures.coordinates.shape == (1, 2, 3)
Topology absent: True
Selected coordinate shape: (1, 2, 3)
Reference chemical state: 0

Supplying this pair declares that its atom indices correspond. MolSysMT checks full axis sizes before selection; it cannot authenticate independently obtained molecular identities. Both input orders work. Atom index 2 becomes output index 0 in this example, while nonconsecutive and repeated structure indices retain their requested order. The default result is independent of the inputs.

Several chemical states keep their reference state but acquire no automatic per-structure assignment. With both selections set to 'all', the explicit option copy_if_all=False instead shares native domains through the new container.

One item into multiple#

You can also split a single input system into multiple target forms simultaneously by passing a list to to_form:

molsys_h5 = msm.systems['pentalanine']['traj_pentalanine.h5']
topology, structures = msm.convert(molsys_h5, to_form=['molsysmt.Topology', 'molsysmt.Structures'])
msm.info(topology)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_peptides n_structures
molsysmt.Topology 62 7 1 1 1 1 1 None
msm.info(structures)
form n_atoms n_groups n_components n_chains n_molecules n_entities n_structures
molsysmt.Structures 62 None None None None None 5000

Let’s visualize the composite system formed by [topology, structures] interactively:

msm.view([topology, structures], structure_indices=3500)

Supported conversions#

To query available conversion paths, use molsysmt.supported.conversions():

Single-record file:sdf conversion now uses a native V2000/V3000 reader and writer without RDKit. It retains explicitly drawn hydrogens and chemistry, but rejects unsupported stereo/query encodings and multiple records. Writing needs exactly one selected structure; ctfile_version='V3000' removes V2000 count/field limits and permits directed coordination bonds. Their native donor/acceptor roles determine output orientation; loss of separate orders, component-joining overrides and source drawing styles appears in conversion reports. SD properties require explicit discard_properties=True to convert into native domains; strict=True still rejects their loss. See Reading and writing native SDF for units, selections, source copies and reports.

Unselected SDF-to-SDF conversion preserves original bytes after checking only the single-record envelope, including chemistry outside the native profile. Its exact strict report certifies byte preservation, not chemical validity; native projection and selected copies still require supported interpretation.

GRO-to-MDTraj conversions reuse native GRO connectivity inference on the full first structure before selection, while MDTraj reads all requested coordinate structures, times and boxes. GRO has no declared bonds: template/distance candidates do not certify complete chemistry. See the GRO guide for the policy and its limits.

msm.supported.conversions(from_form='mdtraj.Trajectory', to_form_type='string')
  string:alphafold_id string:amino_acids_1 string:amino_acids_3 string:pdb_id string:pdb_text string:smiles string:uniprot_id
mdtraj.Trajectory False True True False False False False
msm.supported.conversions(from_form='mdtraj.Trajectory', to_form_type='file', as_rows='to')
  mdtraj.Trajectory
file:bcif False
file:bcif.gz False
file:cif False
file:cif.gz False
file:crd False
file:dcd False
file:fasta False
file:gro False
file:h5 False
file:h5msm False
file:inpcrd False
file:mdcrd False
file:mol2 False
file:molsys_yaml False
file:pdb True
file:pir False
file:prmtop False
file:psf False
file:smi False
file:structures_yaml False
file:top False
file:topology_yaml False
file:trjpk False
file:xtc True
file:xyz False
file:xyznpy False