-
Notifications
You must be signed in to change notification settings - Fork 824
Refactor Transformations from closure into class #2859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
05f2ddd
92a9653
9fc5071
6b7c45b
ae51c5b
a542792
1729ee6
26950b2
5aa8d2b
1c5bbdb
b09bef6
235e8a9
4447869
5ef7d3f
f6331d3
1ebcc33
c412104
3b1c470
6e87625
11f3644
7c857f6
58f6e4e
26dab2f
648c9b0
3f083ae
9ae7f83
26f68bc
ae8a2a2
499efc1
2793ba2
acb4488
1080678
0655275
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,38 +22,107 @@ | |||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| """\ | ||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||
| Trajectory transformations --- :mod:`MDAnalysis.transformations` | ||||||||||||||||||||||||||||||||||||||||||||||||
| ================================================================ | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| The transformations submodule contains a collection of functions to modify the | ||||||||||||||||||||||||||||||||||||||||||||||||
| trajectory. Coordinate transformations, such as PBC corrections and molecule fitting | ||||||||||||||||||||||||||||||||||||||||||||||||
| are often required for some analyses and visualization, and the functions in this | ||||||||||||||||||||||||||||||||||||||||||||||||
| module allow transformations to be applied on-the-fly. | ||||||||||||||||||||||||||||||||||||||||||||||||
| These transformation functions can be called by the user for any given | ||||||||||||||||||||||||||||||||||||||||||||||||
| timestep of the trajectory, added as a workflow using :meth:`add_transformations` | ||||||||||||||||||||||||||||||||||||||||||||||||
| of the :mod:`~MDAnalysis.coordinates.base` module, or upon Universe creation using | ||||||||||||||||||||||||||||||||||||||||||||||||
| The transformations submodule contains a collection of function-like classes to | ||||||||||||||||||||||||||||||||||||||||||||||||
| modify the trajectory. | ||||||||||||||||||||||||||||||||||||||||||||||||
| Coordinate transformations, such as PBC corrections and molecule fitting | ||||||||||||||||||||||||||||||||||||||||||||||||
| are often required for some analyses and visualization, and the functions in | ||||||||||||||||||||||||||||||||||||||||||||||||
| this module allow transformations to be applied on-the-fly. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| A typical transformation class looks like this (note that we keep its name | ||||||||||||||||||||||||||||||||||||||||||||||||
| lowercase because we will treat it as a function, thanks to the ``__call__`` | ||||||||||||||||||||||||||||||||||||||||||||||||
| method): | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| .. code-blocks:: python | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| class transformation(object): | ||||||||||||||||||||||||||||||||||||||||||||||||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, *args, **kwargs): | ||||||||||||||||||||||||||||||||||||||||||||||||
| # do some things | ||||||||||||||||||||||||||||||||||||||||||||||||
| # save needed args as attributes. | ||||||||||||||||||||||||||||||||||||||||||||||||
| self.needed_var = args[0] | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a little abstract, a trivial example would be better |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| def __call__(self, ts): | ||||||||||||||||||||||||||||||||||||||||||||||||
| # apply changes to the Timestep, | ||||||||||||||||||||||||||||||||||||||||||||||||
| # or modify an AtomGroup and return Timestep | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return ts | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You showed the abstract class. Now show a concrete example to address @richardjgowers comment. For instance
Suggested change
I currently can't get nglview to work in my notebook so you'll need to check that this actually works... or come up with another example. EDIT: forgot to increment EDIT 2: yes, it's pretty dumb that the phi angle just keeps incrementing, no matter what you do with the trajectory. Perhaps better to do something like EDIT 3: changed it to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! it works. And I think it makes sense to just rotate by a fixed angle. (for visualization perhaps)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the snippet. |
||||||||||||||||||||||||||||||||||||||||||||||||
| As a concrete example we will write a transformation that rotates a group of | ||||||||||||||||||||||||||||||||||||||||||||||||
| atoms around the z-axis through the center of geometry by a fixed increment | ||||||||||||||||||||||||||||||||||||||||||||||||
| for every time step. We will use | ||||||||||||||||||||||||||||||||||||||||||||||||
| :meth:`MDAnalysis.core.groups.AtomGroup.rotateby` | ||||||||||||||||||||||||||||||||||||||||||||||||
| and simply increment the rotation angle every time the | ||||||||||||||||||||||||||||||||||||||||||||||||
| transformation is called :: | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| class spin_atoms(object): | ||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, atoms, dphi): | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Rotate atoms by dphi degrees for every ts around the z axis | ||||||||||||||||||||||||||||||||||||||||||||||||
| self.atoms = atoms | ||||||||||||||||||||||||||||||||||||||||||||||||
| self.dphi = dphi | ||||||||||||||||||||||||||||||||||||||||||||||||
| self.axis = np.array([0, 0, 1]) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| def __call__(self, ts): | ||||||||||||||||||||||||||||||||||||||||||||||||
| phi = self.dphi * ts.frame | ||||||||||||||||||||||||||||||||||||||||||||||||
| self.atoms.rotateby(phi, self.axis) | ||||||||||||||||||||||||||||||||||||||||||||||||
| return ts | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| This transformation can be used as :: | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| u = mda.Universe(PSF, DCD) | ||||||||||||||||||||||||||||||||||||||||||||||||
| u.trajectory.add_transformations(spin_atoms(u.select_atoms("protein"), 1.0)) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Also see :mod:`MDAnalysis.transformations.translate` for a simple example. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| These transformation functions can be called by the user for any given timestep | ||||||||||||||||||||||||||||||||||||||||||||||||
| of the trajectory, added as a workflow using :meth:`add_transformations` | ||||||||||||||||||||||||||||||||||||||||||||||||
| of the :mod:`~MDAnalysis.coordinates.base`, or upon Universe creation using | ||||||||||||||||||||||||||||||||||||||||||||||||
| the keyword argument `transformations`. Note that in the two latter cases, the | ||||||||||||||||||||||||||||||||||||||||||||||||
| workflow cannot be changed after being defined. | ||||||||||||||||||||||||||||||||||||||||||||||||
| workflow cannot be changed after being defined. for example: | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| .. code-block:: python | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| In addition to the specific arguments that each transformation can take, they also | ||||||||||||||||||||||||||||||||||||||||||||||||
| contain a wrapped function that takes a `Timestep` object as argument. | ||||||||||||||||||||||||||||||||||||||||||||||||
| So, a transformation can be roughly defined as follows: | ||||||||||||||||||||||||||||||||||||||||||||||||
| u = mda.Universe(GRO, XTC) | ||||||||||||||||||||||||||||||||||||||||||||||||
| trans = transformation(args) | ||||||||||||||||||||||||||||||||||||||||||||||||
| u.trajectory.add_transformations(trans) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # it is equivalent to applying this transforamtion to each Timestep by | ||||||||||||||||||||||||||||||||||||||||||||||||
| ts = u.trajectory[0] | ||||||||||||||||||||||||||||||||||||||||||||||||
| ts_trans = trans(ts) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Transformations can also be created as a closure/nested function. | ||||||||||||||||||||||||||||||||||||||||||||||||
| In addition to the specific arguments that each transformation can take, they | ||||||||||||||||||||||||||||||||||||||||||||||||
| also contain a wrapped function that takes a `Timestep` object as argument. | ||||||||||||||||||||||||||||||||||||||||||||||||
| So, a closure-style transformation can be roughly defined as follows: | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| .. code-block:: python | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| def transformations(*args,**kwargs): | ||||||||||||||||||||||||||||||||||||||||||||||||
| def transformation(*args,**kwargs): | ||||||||||||||||||||||||||||||||||||||||||||||||
| # do some things | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| def wrapped(ts): | ||||||||||||||||||||||||||||||||||||||||||||||||
| # apply changes to the Timestep object | ||||||||||||||||||||||||||||||||||||||||||||||||
| # apply changes to the Timestep, | ||||||||||||||||||||||||||||||||||||||||||||||||
| # or modify an AtomGroup and return Timestep | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return ts | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return wrapped | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| See `MDAnalysis.transformations.translate` for a simple example. | ||||||||||||||||||||||||||||||||||||||||||||||||
| .. Note:: | ||||||||||||||||||||||||||||||||||||||||||||||||
| Although functions (closures) work as transformations, they are not used in | ||||||||||||||||||||||||||||||||||||||||||||||||
| in MDAnalysis from release 2.0.0 onwards because they cannot be reliably | ||||||||||||||||||||||||||||||||||||||||||||||||
| serialized and thus a :class:`Universe` with such transformations cannot be | ||||||||||||||||||||||||||||||||||||||||||||||||
| used with common parallelization schemes (e.g., ones based on | ||||||||||||||||||||||||||||||||||||||||||||||||
| :mod:`multiprocessing`). | ||||||||||||||||||||||||||||||||||||||||||||||||
| For detailed descriptions about how to write a closure-style transformation, | ||||||||||||||||||||||||||||||||||||||||||||||||
| please refer to MDAnalysis 1.x documentation. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| .. versionchanged:: 2.0.0 | ||||||||||||||||||||||||||||||||||||||||||||||||
| Transformations should now be created as classes with a :meth:`__call__` | ||||||||||||||||||||||||||||||||||||||||||||||||
| method instead of being written as a function/closure. | ||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| from .translate import translate, center_in_box | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.