Module 9: Physical Unit Safety#
Welcome back, Apprentice Master. In Module 8: Extracting Molecular Attributes, you learned how to programmatically extract numerical attributes and 3D coordinate tensors using msm.get(). Now we address a fundamental requirement of physical simulation: Physical Unit Safety.
In computational structural biology, raw numbers without explicit physical units are dangerous. Is a coordinate value expressed in Angstroms or Nanometers? Is a simulation timestep in Picoseconds or Femtoseconds? A single unit ambiguity can ruin a trajectory or lead to physical catastrophes.
MolSysMT integrates PyUnitWizard (molsysmt.pyunitwizard) as its universal physical quantity engine. PyUnitWizard guarantees that every physical input is interpreted safely and every output maintains explicit dimensional integrity.
Learning Outcomes
By the end of this module, you will be able to:
Understand quantity agnosticism on input (passing strings or physical quantities).
Inspect and manage physical quantities using
puw.is_quantity(),puw.get_value(), andpuw.get_unit().Convert physical quantities between unit systems (
puw.convert()).Configure standard unit defaults for MolSysMT output (
puw.configure.set_standard_units()).Perform dimensionally safe physical arithmetic.
1. Quantity Agnosticism#
Let’s begin by importing MolSysMT, PyUnitWizard, and loading our T4 Lysozyme demonstration system.
import molsysmt as msm
from molsysmt import pyunitwizard as puw
from molsysmt import systems
# Load T4 Lysozyme as native MolSys
lysozyme = msm.convert(systems['T4 lysozyme L99A']['181l.bcif.gz'])
MolSysMT functions are quantity-agnostic on input. When a function expects a physical value (such as coordinates, box lengths, or temperature), you can pass a formal quantity object from any supported library (Pint, OpenMM, Astropy, etc. — see the PyUnitWizard Documentation for the complete list of supported quantity types) or a simple string with explicit unit names:
Let’s set the coordinates of atom index 45 using a string containing Angstrom units:
# Set coordinates of atom index 45 using a string representation with Angstroms
msm.set(lysozyme, element='atom', selection=45, coordinates='[1.0, 4.0, -2.0] angstroms')
# Retrieve the updated coordinates using msm.get()
coords_45 = msm.get(lysozyme, element='atom', selection=45, coordinates=True)
print(f"Retrieved coordinates: {coords_45}")
print(f"Is retrieved output a physical quantity? {puw.is_quantity(coords_45)}")
Retrieved coordinates: [[[0.09999999999999999 0.39999999999999997 -0.19999999999999998]]] nanometer
Is retrieved output a physical quantity? True
2. Inspecting and Converting#
PyUnitWizard provides utilities to extract raw numerical values, inspect unit strings, or convert values to different unit systems:
# Extract numerical value and unit representation
raw_value = puw.get_value(coords_45)
unit_name = puw.get_unit(coords_45)
print(f"Raw numerical value: {raw_value}")
print(f"Associated unit: {unit_name}")
# Convert coordinates from nanometers to Angstroms
coords_in_angstroms = puw.convert(coords_45, to_unit='angstrom')
print(f"Converted coordinates: {coords_in_angstroms}")
Raw numerical value: [[[ 0.1 0.4 -0.2]]]
Associated unit: nanometer
Converted coordinates: [[[0.9999999999999999 3.9999999999999996 -1.9999999999999998]]] angstrom
Note
PyUnitWizard Documentation: PyUnitWizard is the universal physical quantity engine across all tools in the MolSysSuite. For detailed guides on supported quantity types, unit syntax, and conversion functions, visit the PyUnitWizard Documentation.
3. Standard Units#
By default, MolSysMT returns physical quantities using standard scientific units (nanometers for length, picoseconds for time, kelvin for temperature). You can inspect or modify these global defaults directly via PyUnitWizard configuration:
# Inspect standard registered units
print(f"Default standard units: {puw.configure.get_standard_units()}")
# Temporarily set standard unit for length to Angstroms
puw.configure.set_standard_units(['angstrom', 'ps', 'mol', 'K', 'nm**2', 'rad'])
# Now msm.get() returns coordinates in Angstroms
coords_ang = msm.get(lysozyme, element='atom', selection=45, coordinates=True)
print(f"Coordinates with Angstrom default: {coords_ang}")
# Reset standard unit for length back to nanometers
puw.configure.set_standard_units(['nm', 'ps', 'mol', 'K', 'nm**2', 'rad'])
Default standard units: {'nm': {'[L]': 1, '[M]': 0, '[T]': 0, '[K]': 0, '[mol]': 0, '[A]': 0, '[Cd]': 0}, 'ps': {'[L]': 0, '[M]': 0, '[T]': 1, '[K]': 0, '[mol]': 0, '[A]': 0, '[Cd]': 0}, 'K': {'[L]': 0, '[M]': 0, '[T]': 0, '[K]': 1, '[mol]': 0, '[A]': 0, '[Cd]': 0}, 'mole': {'[L]': 0, '[M]': 0, '[T]': 0, '[K]': 0, '[mol]': 1, '[A]': 0, '[Cd]': 0}, 'dalton': {'[L]': 0, '[M]': 1, '[T]': 0, '[K]': 0, '[mol]': 0, '[A]': 0, '[Cd]': 0}, 'e': {'[L]': 0, '[M]': 0, '[T]': 1, '[K]': 0, '[mol]': 0, '[A]': 1, '[Cd]': 0}, 'kJ/mol': {'[L]': 2, '[M]': 1, '[T]': -2, '[K]': 0, '[mol]': -1, '[A]': 0, '[Cd]': 0}, 'kJ/(mol*nm)': {'[L]': 1, '[M]': 1, '[T]': -2, '[K]': 0, '[mol]': -1, '[A]': 0, '[Cd]': 0}, 'kJ/(mol*nm**2)': {'[L]': 0, '[M]': 1, '[T]': -2, '[K]': 0, '[mol]': -1, '[A]': 0, '[Cd]': 0}, 'radians': {'[L]': 0, '[M]': 0, '[T]': 0, '[K]': 0, '[mol]': 0, '[A]': 0, '[Cd]': 0}}
Coordinates with Angstrom default: [[[0.9999999999999999 3.9999999999999996 -1.9999999999999998]]] angstrom
4. Dimensional Arithmetic#
PyUnitWizard prevents invalid physical operations at runtime. You can perform arithmetic on compatible physical quantities, but attempting to add incompatible dimensions (e.g. adding length to time) raises a dimensional error:
# Perform safe arithmetic on compatible length quantities
d1 = puw.quantity(1.0, 'nm')
d2 = puw.quantity(5.0, 'angstrom')
total_distance = d1 + d2
print(f"Safe physical addition (1.0 nm + 5.0 Å): {total_distance}")
Safe physical addition (1.0 nm + 5.0 Å): 1.5 nanometer
🏆 Challenge 9: The Unit Master#
Define a time quantity of 10.0 Nanoseconds using
puw.quantity().Convert it to Picoseconds using
puw.convert().Extract the coordinates of atom index 0 from
lysozymeand convert them to Angstroms.Verify that trying to add your time quantity to the coordinates array raises a dimensional error.
With physical unit safety established, you can perform quantitative operations with complete mathematical confidence. In Module 10: Modifying Molecular Attributes, we will learn how to modify system attributes and structural data with msm.set().
See also
API Documentation for Functions in this Module:
molsysmt.pyunitwizard.quantity()— PyUnitWizard quantity constructor.molsysmt.pyunitwizard.convert()— Physical unit conversion engine.
Related Course Modules & Guides:
Previous Module: Module 8: Extracting Molecular Attributes
Next Module: Module 10: Modifying Molecular Attributes
User Guide: user-foundations