Skip to content

Commit

Permalink
Make VACF test work with MockTrajectory
Browse files Browse the repository at this point in the history
  • Loading branch information
MBartkowiakSTFC committed Jan 26, 2024
1 parent 05a4db2 commit e804586
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 30 deletions.
23 changes: 17 additions & 6 deletions MDANSE/Src/MDANSE/Framework/Configurable.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Configurable(object):

settings = collections.OrderedDict()

def __init__(self, settings=None, mdmc_input_override=False):
def __init__(self, settings=None, trajectory_input="mdasne"):
"""
Constructor
"""
Expand All @@ -56,17 +56,28 @@ def __init__(self, settings=None, mdmc_input_override=False):
if settings is not None:
self.set_settings(settings)

if mdmc_input_override:
self.override_trajectory_input()
if trajectory_input == "mdmc":
self.mdmc_trajectory_input()
elif trajectory_input == "mock":
self.mock_trajectory_input()

def override_trajectory_input(self):
def mdmc_trajectory_input(self):
"""Remove the hdf_trajectory (file-based) from settings,
and introduce an MDMC trajectory instead.
"""
for key, value in self.settings.items():
if key == "trajectory":
if value[0] == "hdf_trajectory":
self.settings[key] = ("mdmc_trajectory", {})
if value[0] == "HDFTrajectoryConfigurator":
self.settings[key] = ("MDMCTrajectoryConfigurator", {})

def mock_trajectory_input(self):
"""Remove the hdf_trajectory (file-based) from settings,
and introduce a mock trajectory instead.
"""
for key, value in self.settings.items():
if key == "trajectory":
if value[0] == "HDFTrajectoryConfigurator":
self.settings[key] = ("MockTrajectoryConfigurator", {})

def build_configuration(self):
self._configuration.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

import os

from MDANSE import PLATFORM, REGISTRY

from MDANSE.Framework.Configurators.IConfigurator import IConfigurator


Expand Down Expand Up @@ -86,6 +84,3 @@ def get_information(self):
info.append("The trajectory does not contain atomic velocities\n")

return "".join(info)


REGISTRY["mdmc_trajectory"] = MDMCTrajectoryConfigurator
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# **************************************************************************
#
# MDANSE: Molecular Dynamics Analysis for Neutron Scattering Experiments
#
# @file Src/Framework/Configurators/MDMCTrajectoryConfigurator.py
# @brief A way to take in a trajectory from MDMC in a wrapper
#
# @homepage https://www.isis.stfc.ac.uk/Pages/MDANSEproject.aspx
# @license GNU General Public License v3 or higher (see LICENSE)
# @copyright Institut Laue Langevin 2013-now
# @copyright ISIS Neutron and Muon Source, STFC, UKRI 2021-now
# @authors Scientific Computing Group at ILL (see AUTHORS)
#
# **************************************************************************

import os

from MDANSE.Framework.Configurators.IConfigurator import IConfigurator
from MDANSE.MolecularDynamics.MockTrajectory import MockTrajectory


class MockTrajectoryConfigurator(IConfigurator):
"""
This is a replacement for a trajectory stored in and HDF5 file.
It is intended to be a drop-in replacement for HDFTrajectoryConfigurator,
even though it is NOT file-based.
"""

_default = None

def __init__(self, name, wildcard="JSON file|*.json", **kwargs):
"""
Initializes the configurator object.
:param name: the name of the configurator as it will appear in the configuration.
:type name: str
:param wildcard: the wildcard used to filter the file. This will be used in MDANSE GUI when
browsing for the input file.
:type wildcard: str
"""

# The base class constructor.
IConfigurator.__init__(self, name, **kwargs)

self._wildcard = wildcard

def configure(self, value: str):
"""
Configure a mock trajectory file.
:param value: a JSON file with a MockTrajectory definition
:type value: str
"""

self["value"] = value
self["filename"] = "Mock"

self["instance"] = MockTrajectory.from_json(value)

self["basename"] = "Mock"

self["length"] = len(self["instance"])

self["md_time_step"] = self["instance"]._time_step

self["has_velocities"] = self["instance"].has_velocities

def get_information(self):
"""
Returns some basic informations about the contents of the HDF trajectory file.
:return: the informations about the contents of the HDF trajectory file.
:rtype: str
"""

info = ["Mock trajectory used as input"]
info.append("Number of steps: %d\n" % self["length"])
info.append(
"Size of the chemical system: %d\n"
% self["instance"].chemical_system.number_of_atoms
)
if self["has_velocities"]:
info.append("The trajectory contains atomic velocities\n")
else:
info.append("The trajectory does not contain atomic velocities\n")

return "".join(info)
4 changes: 2 additions & 2 deletions MDANSE/Src/MDANSE/Framework/Jobs/IJob.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ def define_unique_name():

return name

def __init__(self, mdmc_input_override=False):
def __init__(self, trajectory_input="mdanse"):
"""
The base class constructor.
"""

Configurable.__init__(self, mdmc_input_override=mdmc_input_override)
Configurable.__init__(self, trajectory_input=trajectory_input)

self._outputData = OutputData()

Expand Down
8 changes: 6 additions & 2 deletions MDANSE/Src/MDANSE/MolecularDynamics/MockTrajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def __getitem__(self, frame):
configuration = {}
configuration["coordinates"] = self.coordinates(frame).astype(np.float64)
configuration["time"] = self._time_axis[frame]
configuration["unit_cell"] = self.unit_cell(frame).astype(np.float64)
configuration["unit_cell"] = self.unit_cell(frame)._unit_cell.astype(np.float64)

return configuration

Expand Down Expand Up @@ -226,7 +226,7 @@ def unit_cell(self, frame):
:rtype: ndarray
"""

return UnitCell(self._full_box_size)._unit_cell
return UnitCell(self._full_box_size)

def __len__(self):
"""Returns the length of the trajectory.
Expand Down Expand Up @@ -451,6 +451,10 @@ def filename(self):

return "nonexistent_file.h5"

@property
def has_velocities(self):
return "velocities" in self._variables.keys()

def variables(self):
"""Return the configuration variables stored in this trajectory.
Expand Down
14 changes: 3 additions & 11 deletions MDANSE/Tests/UnitTests/Analysis/test_mock_dynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@

mock_json = os.path.join(file_wd, "..", "Data", "mock.json")

@pytest.fixture(scope="module")
def mock_trajectory():
"""Returns a trajectory containing muiltiple atoms,
in a supercell, which move periodically.
"""
traj = MockTrajectory.from_json(mock_json)
return traj


@pytest.mark.parametrize(
"interp_order, normalise",
Expand All @@ -44,16 +36,16 @@ def mock_trajectory():
(3, False),
],
)
def test_vacf(mock_trajectory, interp_order, normalise):
def test_vacf(interp_order, normalise):
temp_name = tempfile.mktemp()
parameters = {}
parameters["frames"] = (0, 10, 1)
parameters["interpolation_order"] = interp_order
parameters["output_files"] = (temp_name, ("MDAFormat",))
parameters["running_mode"] = ("monoprocessor",)
parameters["normalize"] = normalise
parameters["trajectory"] = mock_trajectory
vacf = IJob.create("VelocityAutoCorrelationFunction")
parameters["trajectory"] = mock_json
vacf = IJob.create("VelocityAutoCorrelationFunction", trajectory_input="mock")
vacf.run(parameters, status=True)
assert path.exists(temp_name + ".mda")
assert path.isfile(temp_name + ".mda")
Expand Down
9 changes: 5 additions & 4 deletions MDANSE/Tests/UnitTests/test_mock_trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@

mock_json = os.path.join(file_wd, "Data", "mock.json")


@pytest.fixture(scope="module")
def static_trajectory():
"""Returns a trajectory containing a single atom,
Expand All @@ -70,6 +71,7 @@ def static_trajectory():
traj.set_coordinates(np.array([[1.0, 0.0, 0.0]]))
return traj


@pytest.fixture
def full_trajectory():
"""Returns a trajectory containing muiltiple atoms,
Expand Down Expand Up @@ -156,6 +158,7 @@ def test_modulation_multiple(full_trajectory):
assert np.allclose(conf_init["coordinates"], conf_end["coordinates"])
assert not np.allclose(conf_init["coordinates"], conf_between["coordinates"])


def test_from_json(full_trajectory):
full_trajectory.modulate_structure(
np.array([[1.0, 1.0, 0.0], [0.0, 0.0, 1.0], [0.0, 0.0, 0.0]]),
Expand All @@ -172,7 +175,5 @@ def test_from_json(full_trajectory):
instance = MockTrajectory.from_json(mock_json)
assert full_trajectory._atom_types == instance._atom_types
print(full_trajectory.coordinates(25) - instance.coordinates(25))
assert np.allclose(full_trajectory.coordinates(25),
instance.coordinates(25))
assert not np.allclose(full_trajectory.coordinates(25),
instance.coordinates(22))
assert np.allclose(full_trajectory.coordinates(25), instance.coordinates(25))
assert not np.allclose(full_trajectory.coordinates(25), instance.coordinates(22))

0 comments on commit e804586

Please sign in to comment.