Marcello-Sega/pytim

View on GitHub
pytim/patches.py

Summary

Maintainability
A
3 hrs
Test Coverage
# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding: utf-8 -*-
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
from __future__ import print_function


def patchNumpy():
    # this try/except block patches numpy and provides _validate_lengths
    # to skimage<=1.14.1
    import numpy
    try:
        numpy.lib.arraypad._validate_lengths
    except AttributeError:
        def patch_validate_lengths(ar, crop_width):
            return numpy.lib.arraypad._as_pairs(crop_width, ar.ndim, as_index=True)
        numpy.lib.arraypad._validate_lengths = patch_validate_lengths


def patchTrajectory(trajectory, interface):
    """ Patch the MDAnalysis trajectory class

        this patch makes the layer assignement being automatically
        called whenever a new frame is loaded.
    """
    try:
        trajectory.interface
        trajectory.interface = interface

    except AttributeError:
        trajectory.interface = interface
        trajectory.interface._frame = trajectory.frame
        trajectory.original_read_next_timestep = trajectory._read_next_timestep

        trajectory.original_read_frame_with_aux = trajectory._read_frame_with_aux

        class PatchedTrajectory(trajectory.__class__):
            def _read_next_timestep(self, ts=None):
                tmp = self.original_read_next_timestep(ts=ts)
                if self.interface.autoassign is True:
                    self.interface._assign_layers()
                    self.interface._frame = self.frame
                return tmp

            def _read_frame_with_aux(self, frame):
                if frame != self.frame:
                    tmp = self.original_read_frame_with_aux(frame)
                    if self.interface.autoassign is True:
                        if self.interface._frame != self.frame:
                            self.interface._assign_layers()
                            self.interface._frame = self.frame
                    return tmp
                return self.ts

        oldname = trajectory.__class__.__name__
        oldmodule = trajectory.__class__.__module__

        PatchedTrajectory.__name__ = oldname
        PatchedTrajectory.__module__ = oldmodule
        trajectory.__class__ = PatchedTrajectory


def patchOpenMM(simulation, interface):
    #       return _openmm.CompoundIntegrator_step(self, steps)
    """ Patch the Openmm Simulation class

    """
    from simtk.unit import angstrom as openmm_AA
    try:
        simulation.interface
    except AttributeError:
        simulation.interface = interface
        simulation.original_step = simulation.step

        class PatchedOpenMMSimulation(simulation.__class__):
            def step(self, steps):
                tmp = self.original_step(steps)
                pos = self.context.getState(getPositions=True).getPositions(
                    asNumpy=True).value_in_unit(openmm_AA)
                self.interface.universe.atoms.positions = pos
                if self.interface.autoassign is True:
                    self.interface._assign_layers()
                return tmp

        oldname = simulation.__class__.__name__
        oldmodule = simulation.__class__.__module__

        PatchedOpenMMSimulation.__name__ = oldname
        PatchedOpenMMSimulation.__module__ = oldmodule
        simulation.__class__ = PatchedOpenMMSimulation


def patchMDTRAJ_ReplacementTables():
    try:
        import mdtraj
        if not (mdtraj.formats.pdb.PDBTrajectoryFile._atomNameReplacements == {}):
            print('Warning: mdtraj has not been patched correctly. The trajectory must be loaded *after* importing pytim: some atom names might have been replaced')

        @staticmethod
        def _NoReplacementTables():
            mdtraj.formats.pdb.PDBTrajectoryFile._atomNameReplacements = {}

        mdtraj.formats.pdb.PDBTrajectoryFile._loadNameReplacementTables = _NoReplacementTables
    except ImportError:
        pass


def patchMDTRAJ(trajectory, universe):
    """ Patch the mdtraj Trajectory class

        automates the data exchange between MDAnalysis and mdtraj classes

        Example:

        >>> import mdtraj
        >>> import pytim
        >>> from pytim.datafiles import WATER_GRO, WATER_XTC
        >>> t = mdtraj.load_xtc(WATER_XTC,top=WATER_GRO)
        >>> inter = pytim.ITIM(t)


    """

    try:
        trajectory.universe
    except AttributeError:
        trajectory.universe = universe

        class PatchedMdtrajTrajectory(trajectory.__class__):
            def __getitem__(self, key):
                slice_ = self.slice(key)
                patchMDTRAJ(slice_, universe)

                if isinstance(key, int):
                    # mdtraj uses nm as distance unit, we need to convert to
                    # Angstrom for MDAnalysis
                    slice_.universe.atoms.positions = slice_.xyz[0] * 10.0
                    dimensions = slice_.universe.dimensions[:]
                    dimensions[0:3] = slice_.unitcell_lengths[0:3] * 10.0
                    slice_.universe.dimensions = dimensions
                    if slice_.universe.trajectory.interface.autoassign is True:
                        slice_.universe.trajectory.interface._assign_layers()
                return slice_

        oldname = trajectory.__class__.__name__
        oldmodule = trajectory.__class__.__module__

        PatchedMdtrajTrajectory.__name__ = oldname
        PatchedMdtrajTrajectory.__module__ = oldmodule
        trajectory.__class__ = PatchedMdtrajTrajectory