diff --git a/simulationworkflowschema/molecular_dynamics.py b/simulationworkflowschema/molecular_dynamics.py index 306591f..857b680 100644 --- a/simulationworkflowschema/molecular_dynamics.py +++ b/simulationworkflowschema/molecular_dynamics.py @@ -48,6 +48,7 @@ ) from nomad.utils import get_logger from nomad.units import ureg +from nomad import atomutils from .general import ( SimulationWorkflowMethod, SimulationWorkflowResults, @@ -1181,6 +1182,46 @@ def get_composition(children_names: List[str]) -> str: return formula +def mda_universe_from_nomad_atoms(system, logger=None): + """Returns an instance of mda.Universe from a NOMAD Atoms-section. + + Args: + system: The atoms to transform + + Returns: + A new mda.Universe created from the given data. + """ + n_atoms = len(system.positions) + n_residues = 1 + atom_resindex = [0] * n_atoms + residue_segindex = [0] + + universe = MDAnalysis.Universe.empty( + n_atoms, + n_residues=n_residues, + atom_resindex=atom_resindex, + residue_segindex=residue_segindex, + trajectory=True, + ) + + # Add positions + universe.atoms.positions = system.positions.to(ureg.angstrom).magnitude + + # Add atom attributes + atom_names = system.labels + universe.add_TopologyAttr('name', atom_names) + universe.add_TopologyAttr('type', atom_names) + universe.add_TopologyAttr('element', atom_names) + + # Add the box dimensions + if system.lattice_vectors is not None: + universe.atoms.dimensions = atomutils.cell_to_cellpar( + system.lattice_vectors.to(ureg.angstrom).magnitude, degrees=True + ) + + return universe + + class ThermostatParameters(ArchiveSection): """ Section containing the parameters pertaining to the thermostat for a molecular dynamics run.