schrodinger.application.desmond.packages.traj module

Molecular dynamics trajectory handling module Define common APIs for various trajectory formats. Basic trajectory handling algorithms are also implemented here.

Copyright Schrodinger, LLC. All rights reserved.

class schrodinger.application.desmond.packages.traj.Fmt(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: enum.Enum

Trajectory format enum

AUTO = 0
DTR = 1
XTC = 2
schrodinger.application.desmond.packages.traj.get_fmt(fname, format=Fmt.AUTO)

Returns the format based on the given trajectory file name (fname) and the format specification (format). If the format specification is definite (i.e., not Fmt.AUTO), this function will trivially return the value of format, otherwise it will check the fname’s value, determining the format, and return the result.

Parameters
  • fname (str) – Trajectory file name

  • format (Fmt) – Trajectory format specification

:rtype : Fmt :return: The format of the given trajectory fname

schrodinger.application.desmond.packages.traj.get_trajectory_extname(format=Fmt.AUTO, ref_fname=None)
class schrodinger.application.desmond.packages.traj.Source(reader, name='sometraj')

Bases: object

CACHE_LIMIT_BYTES = 1000000000.0
__init__(reader, name='sometraj')

reader specifies where to retrieve a trajectory frame when it’s needed but currently NOT in the memory (in other words, it’s not cached by this source). A reader could potentially be a file reader, a string reader, a socket reader, a database dealer, etc., as long as it satisfies the duck-typing requirements (see below). And interestingly, the probably simplest reader is another trajectory (i.e., a list of Frame objects) in memory.

Duck typing for readers.

  • Random access reader[index] should return the index-th frame. Here index is zero-based, of Python style (i.e., -1 means the last frame, etc.).

  • len support len(reader) should return the total number of frames.

If a reader doesn’t support the duck typing as specified above, a subclass can be created to bypass the typing requirements. See DtrSource below as an example.

property name
retrieve_frame(index)

Retrieves the index-th frame from the source. index is zero-based. This method assumes the source allows random access to frames.

Raise

IndexError if index is out of range, or IOError if the trajectory reader is closed.

can_cache_more_frames(cachable_frames_margin: int = 5) bool

Returns whether more frames can be cached.

Parameters

cachable_frames_margin – The margin of frames to consider when checking if more frames can be cached.

The motivating use case for cachable_frames_margin is to ensure that there is enough space in memory for caching not just the immediate next frame but also some additional frames. This is useful when frames are being used in a batch and additional caching is required, the margin provides flexibility.

:return True if more frames can be cached, False otherwise.

clear_cache()
used_space()
nframes()

Returns the total number of frames in this trajectory source.

close()

Closes down the trajectory reader. A couple of points to note:

  1. Once this method is called, this Source object can only retrieve frames that are internally cached. Attempting to retrieve uncached frames will incur an IOError. Normally we do NOT know which frames are cached, so to be safe this method should be called only when we are done with the trajectory.

  2. Normally, only some Frame objects reference a Source object, if all the Frame objects are garbaged, the Source object will be garbaged automatically, and there is no need to call this close method separately.

class schrodinger.application.desmond.packages.traj.DtrSource(reader, name='sometraj')

Bases: schrodinger.application.desmond.packages.traj.Source

nframes()

Returns the total number of frames in this trajectory source.

class schrodinger.application.desmond.packages.traj.XtcSource(*args, **kwargs)

Bases: schrodinger.application.desmond.packages.traj.Source

__init__(*args, **kwargs)

reader specifies where to retrieve a trajectory frame when it’s needed but currently NOT in the memory (in other words, it’s not cached by this source). A reader could potentially be a file reader, a string reader, a socket reader, a database dealer, etc., as long as it satisfies the duck-typing requirements (see below). And interestingly, the probably simplest reader is another trajectory (i.e., a list of Frame objects) in memory.

Duck typing for readers.

  • Random access reader[index] should return the index-th frame. Here index is zero-based, of Python style (i.e., -1 means the last frame, etc.).

  • len support len(reader) should return the total number of frames.

If a reader doesn’t support the duck typing as specified above, a subclass can be created to bypass the typing requirements. See DtrSource below as an example.

nframes()

Returns the total number of frames in this trajectory source.

class schrodinger.application.desmond.packages.traj.Frame(source: Optional[schrodinger.application.desmond.packages.traj.Source], index: Optional[int])

Bases: object

This class, as its name suggests, represents a single trajectory frame. So far, we allow a frame to be mutated in the following ways:

  • Assign a new chemical time

  • Reduce to a subset of particles

  • Coordinates of all particles are translated

We call changes generally as decorations. They might not make into the frame data, or at least not immediately. Why? This avoids making multiple expensive copies of the data.

__init__(source: Optional[schrodinger.application.desmond.packages.traj.Source], index: Optional[int])
Parameters
  • source – The object to retrieve the actual frame data from. It can be None, which means this Frame object itself contains all the frame data.

  • index – The index in source to retrieve the frame data. It can be None, which means this Frame object itself contains all the frame data.

source()
copy()

Return a copy of this Frame object. The atom position and atom velocity arrays, as well as lambda value, lambda position, and lambda velocity arrays will be copied.

property natoms
property nactive: int
property is_gcmc

Return whether the frame is from a gcmc simulation

FrameAttributeType

alias of Union[numpy.ndarray, numpy.float32]

AtomIndexType

alias of Union[int, collections.abc.Iterable]

FrameAttributeLambdaType

alias of Callable[[schrodinger.application.desmond.packages.msys.molfile._molfile.Frame], Union[numpy.ndarray, numpy.float32, int]]

pos(i: Optional[Union[int, collections.abc.Iterable]] = None) numpy.ndarray

Return the position vector(s).

i can be any of the following types:

  • None: Return the whole position-vector array;

  • int: i should be a GID, and this function return position vector of the particle i.

  • Iterable: i should be a “list” of GIDs, and this function returns a NEW numpy array of position-vectors of the specified particles.

vel(i: Optional[Union[int, collections.abc.Iterable]] = None) numpy.ndarray

Return the velocity vector(s). This method may throw if this frame doesn’t have velocity data.

See the method pos method for more details on param i.

lambdas(i: Optional[Union[int, collections.abc.Iterable]] = None) Union[numpy.ndarray, numpy.float32]

Return the lambda value(s) (weight(s)) for an specific state or all states. This method may throw if this frame doesn’t have lambda data.

See the method pos method for more details on param i.

lambda_pos(i: Optional[Union[int, collections.abc.Iterable]] = None) Union[numpy.ndarray, numpy.float32]

Return the lambda position(s) for an specific state or all states. This method may throw if this frame doesn’t have lambda pos data.

See the method pos method for more details on param i.

lambda_vel(i: Optional[Union[int, collections.abc.Iterable]] = None) Union[numpy.ndarray, numpy.float32]

Return the lambda velocity/velocities for an specific state or all states. This method may throw if this frame doesn’t have lambda vel data.

See the method pos method for more details on param i.

property nlambdas: int

Return the number of lambda states (sum of all states/sites in lambda dynamics simulation).

hijackPos(impos)

Tentatively replace the internal position array of this Frame object with an external numpy array impos. We can call the external array “imposter”. After calling this method, the pos method will return values from the imposter until the imposter is removed (by calling hijackPos(None)). The imposter should be a Nx3 numpy array, where N can be of any size. Note the impacts on other methods of this class:

  • pos Use impos.

  • copy The entire impos array will be copied into the copy of

    this Frame object.

  • reduce Still function in the same way, but note that the impos

    array will not be changed by these methods.

  • moveby The same as reduce

  • write Still function in the same way, note that it’s the internal

    position array, not impos, that will be written out.

Parameters

impos (None, or numpy.ndarray of size Nx3, where N is arbitray number) – The position array to tentatively replac the internal position array in this Frame object. If the value is None, we remove the “imposter” and recover the internal position array.

property time
property box
transpose_box()

Transpose the simulation box.

property orig_index
reduce(indices, copy=True)

Keep only the atoms specified by indices, the other atoms will be deleted from this frame. The caller needs to ensure the indices order matches with the msys model of the reduced system.

Parameters

copy – If true, this function will make a copy of this frame and reduce atoms in this copy, and finally return the copy.

moveby(x, y, z)

Translate all positions by the given x, y, and z.

write(writer)

Write out this frame using the given writer.

class schrodinger.application.desmond.packages.traj.MaeFrameReader(mae_fnames: List[str], cms_model: Cms, frame_template: schrodinger.application.desmond.packages.traj.Frame)

Bases: object

This class reads a number of MAE files into a sequence of “bare-metal” frame objects. See docstring of MaeSource below for more detail.

__init__(mae_fnames: List[str], cms_model: Cms, frame_template: schrodinger.application.desmond.packages.traj.Frame)
__len__()
class schrodinger.application.desmond.packages.traj.MaestroFrame(source: Optional[schrodinger.application.desmond.packages.traj.Source], index: Optional[int])

Bases: schrodinger.application.desmond.packages.traj.Frame

This class is added to keep the self._object as weakref so that if any client is keeping the list of Frame objects, underlying self._object gets deleted whenever the corresponding frame object is deleted from cache. Named as MaestroFrame as this class is only consumed by Maestro.

“View position” refers to properties of the frame, such as the frame’s position vector and box matrix. These attributes may be updated when the frame is used in Maestro.

view_position_updated keeps track of whether the frame’s view position has been updated.

__init__(source: Optional[schrodinger.application.desmond.packages.traj.Source], index: Optional[int])
Parameters
  • source – The object to retrieve the actual frame data from. It can be None, which means this Frame object itself contains all the frame data.

  • index – The index in source to retrieve the frame data. It can be None, which means this Frame object itself contains all the frame data.

property view_position_updated

Returns whether the view position of the frame is updated or not.

load_frame_to_memory()

Ensures that the frame is added to cache

can_cache_more_frames(cachable_frames_margin: int = 5) bool

Returns whether more frames can be cached.

Parameters

cachable_frames_margin – The margin of frames to consider when checking if more frames can be cached.

:return True if more frames can be cached, False otherwise.

class schrodinger.application.desmond.packages.traj.MaeSource(mae_fnames: List[str], cms_model: Cms, frame_template: schrodinger.application.desmond.packages.traj.Frame)

Bases: schrodinger.application.desmond.packages.traj.Source

This is to reverse-convert a list of MAE (or CMS) files into a single trajectory file. The molecular structure in each MAE file will become a single frame in the trajectory. If an MAE file contains multiple CTs, only the first one will be used.

CAVEATS: This kind of conversions always have some caveats, which in this particular case are the following:

  1. Velocities are not always present in either the trajectory frame template or the MAE file. In either case, the velocities will not be saved into the resultant frame.

  2. Since we generally don’t a priori know the exact force field to be used, it’s difficult/impossible to predict about the pseudoatoms. So if they exist in the trajectory frame, their positions will not be set. This is normally not a problem for MD simulations the pseudoatoms’ positions are normally determined on the fly in MD simulations.

  3. The time of each frame is arbitrarily set to the index of the frame.

  4. This will not work properly for GCMC systems where the number of active atoms in the frame template happens to differ from that of the structures in the MAE files.

__init__(mae_fnames: List[str], cms_model: Cms, frame_template: schrodinger.application.desmond.packages.traj.Frame)

reader specifies where to retrieve a trajectory frame when it’s needed but currently NOT in the memory (in other words, it’s not cached by this source). A reader could potentially be a file reader, a string reader, a socket reader, a database dealer, etc., as long as it satisfies the duck-typing requirements (see below). And interestingly, the probably simplest reader is another trajectory (i.e., a list of Frame objects) in memory.

Duck typing for readers.

  • Random access reader[index] should return the index-th frame. Here index is zero-based, of Python style (i.e., -1 means the last frame, etc.).

  • len support len(reader) should return the total number of frames.

If a reader doesn’t support the duck typing as specified above, a subclass can be created to bypass the typing requirements. See DtrSource below as an example.

schrodinger.application.desmond.packages.traj.read_traj(inp, format=Fmt.AUTO, return_iter=False, frame_class=<class 'schrodinger.application.desmond.packages.traj.Frame'>)

Lazy load trajectory.

Parameters
  • inp (str or pathlib.Path) – Input trajectory’s file name

  • format (Fmt) – Trajectory file format

  • return_iter – If True, return an iterator, otherwise return a list of Frame.

  • frame_class (type[Frame]) – The class to use to create frame objects.

schrodinger.application.desmond.packages.traj.write_traj(tr, fname, format=Fmt.AUTO)
Parameters
  • fname (str) – Output file name

  • format (Fmt) – Trajectory file format

schrodinger.application.desmond.packages.traj.create_frame_from_coords(xyz: numpy.ndarray, box: numpy.ndarray, time: float, vel: Optional[numpy.ndarray] = None, lambdas: Optional[List[float]] = None, nactive: Optional[int] = None) schrodinger.application.desmond.packages.traj.Frame

Create a Frame object from XYZ coords, box array and simulation time.

Parameters
  • xyz – numpy array with Nx3 shape, with coordinate of all particles in the frame

  • box – numpy array, size 9 (3x3, row majored matrix)

  • time – simulation time in picoseconds

  • vel – numpy array with Nx3 shape, with velocity vectors for all particles. Should be the same shape as xyz variable.

  • lambdas – values of lambda particles used in constant-pH and lambda dynamics workflows

  • nactive – set number of active particles (for GCMC trajectories only)

Returns

Frame object

schrodinger.application.desmond.packages.traj.merge(*arg)

Merge a list of trajectories. If there is any overlapped frames among these trajectories, the ones from the latter trajectory (higher index in the arg list) will be kept.

schrodinger.application.desmond.packages.traj.concat(first_time, delta_time, *args)

Concatenate a list of trajectories or iterators and reassign the chemical time for each frame. Results are yielded.

Parameters
  • first_time (float) – Chemical time of the first frame.

  • delta_time (float) – The chemical time interval between two successive frames.

  • args – trajectories as iterables

schrodinger.application.desmond.packages.traj.extract_subsystem(tr, gids)

Extract the subsystem as specified by the gids for each frame in the given trajectory tr, and return a new trajectory for the subsystem. The original trajectory is not mutated in any way by this function. Inactive atoms in GCMC trajectory cannot be extracted.

Parameters
  • tr (list of Frame) – Original trajectory

  • gids (list of int) – A list of gids that specifies the subsystem.

Return type

list

Returns

A new trajectory for the subsystem

schrodinger.application.desmond.packages.traj.is_empty_trajectory(trj_name: str) bool

Determine whether the specified trajectory is empty (in filesystem sense, ie relevant files exist, and are of size zero). Note that trajectory readers will fail to open a trajectory which is empty in this sense.

Parameters

trj_name – path to the trajectory