Skip to content

Commit

Permalink
Merge branch 'main' into ligandnet-to-alchnet
Browse files Browse the repository at this point in the history
  • Loading branch information
dwhswenson authored Aug 1, 2023
2 parents 047b7f9 + e10293f commit 19ae779
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 57 deletions.
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ API docs

api/components
api/protocols
api/transformation
api/settings

12 changes: 12 additions & 0 deletions docs/api/transformation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
GUFE Transformation API
-----------------------

Alchemical network edges
========================

.. autoclass:: gufe.transformations.Transformation
:members:

.. autoclass:: gufe.transformations.NonTransformation
:members:
:show-inheritance:
7 changes: 6 additions & 1 deletion gufe/components/proteincomponent.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
1: BondType.SINGLE,
2: BondType.DOUBLE,
3: BondType.TRIPLE,
app.Single: BondType.SINGLE,
app.Double: BondType.DOUBLE,
app.Triple: BondType.TRIPLE,
app.Aromatic: BondType.AROMATIC,
None: BondType.UNSPECIFIED,
}
_BONDORDERS_RDKIT_TO_OPENMM = {
Expand Down Expand Up @@ -361,7 +365,8 @@ def chainkey(m):
a1 = atom_lookup[bond.GetBeginAtomIdx()]
a2 = atom_lookup[bond.GetEndAtomIdx()]
top.addBond(a1, a2,
order=_BONDORDERS_RDKIT_TO_OPENMM[bond.GetBondType()])
order=_BONDORDERS_RDKIT_TO_OPENMM.get(
bond.GetBondType(), None))

return top

Expand Down
103 changes: 47 additions & 56 deletions gufe/transformations/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,7 @@
class Transformation(GufeTokenizable):
"""An edge of an alchemical network.
Connects two :class:`.ChemicalSystem`\ s, with directionality.
Attributes
----------
stateA : ChemicalSystem
The starting :class:`.ChemicalSystem` for the transformation.
stateB : ChemicalSystem
The ending :class:`.ChemicalSystem` for the transformation.
protocol : Protocol
The protocol used to perform the transformation.
Includes all details needed to perform required
simulations/calculations and encodes the alchemical pathway used.
May also correspond to an experimental result.
mapping : Optional[Dict[str, ComponentMapping]]
Mapping of e.g. atoms between the `stateA` and `stateB`
:class:`.ChemicalSystem`\ s.
name : Optional[str]
Optional identifier for the transformation; set this to a unique value
if adding multiple, otherwise identical transformations to the same
:class:`.AlchemicalNetwork` to avoid deduplication
Connects two :class:`ChemicalSystem` objects, with directionality.
"""

def __init__(
Expand Down Expand Up @@ -63,31 +43,42 @@ def __repr__(self):
f"stateB={self.stateB}, protocol={self.protocol})"

@property
def stateA(self):
"""The starting `ChemicalSystem` for the transformation."""
def stateA(self) -> ChemicalSystem:
"""The starting :class:`ChemicalSystem` for the transformation."""
return self._stateA

@property
def stateB(self):
"""The ending `ChemicalSystem` for the transformation."""
def stateB(self) -> ChemicalSystem:
"""The ending :class:`ChemicalSystem` for the transformation."""
return self._stateB

@property
def protocol(self):
"""The protocol for sampling the transformation to derive free energy
differences between `stateA` and `stateB` `ChemicalSystem`s.
def protocol(self) -> Protocol:
"""The protocol used to perform the transformation.
This protocol derives free energy differences between ``stateA`` and
``stateB`` ``ChemicalSystem`` objects. It includes all details needed to
perform required simulations/calculations and encodes the alchemical
pathway used. May also correspond to an experimental result.
"""
return self._protocol

@property
def mapping(self):
"""The mapping between atoms in `stateA` to `stateB`"""
def mapping(self) -> Optional[dict[str, ComponentMapping]]:
"""
Mapping of e.g. atoms between ``stateA`` and ``stateB``.
"""
return self._mapping

@property
def name(self):
"""User-specified for the transformation; used as part of its hash."""
def name(self) -> Optional[str]:
"""
Optional identifier for the transformation; used as part of its hash.
Set this to a unique value if adding multiple, otherwise identical
transformations to the same :class:`AlchemicalNetwork` to avoid
deduplication.
"""
return self._name

def _to_dict(self) -> dict:
Expand All @@ -109,7 +100,9 @@ def create(
extends: Optional[ProtocolDAGResult] = None,
name: Optional[str] = None,
) -> ProtocolDAG:
"""Returns a `ProtocolDAG` executing this `Transformation.protocol`."""
"""
Returns a ``ProtocolDAG`` executing this ``Transformation.protocol``.
"""
return self.protocol.create(
stateA=self.stateA,
stateB=self.stateB,
Expand All @@ -122,17 +115,20 @@ def create(
def gather(
self, protocol_dag_results: Iterable[ProtocolDAGResult]
) -> ProtocolResult:
"""Gather multiple `ProtocolDAGResult`s into a single `ProtocolResult`.
"""
Gather multiple ``ProtocolDAGResult`` into a single ``ProtocolResult``.
Parameters
----------
protocol_dag_results : Iterable[ProtocolDAGResult]
The `ProtocolDAGResult`s to assemble aggregate quantities from.
The ``ProtocolDAGResult`` objects to assemble aggregate quantities
from.
Returns
-------
ProtocolResult
Aggregated results from many `ProtocolDAGResult`s from a given `Protocol`.
Aggregated results from many ``ProtocolDAGResult`` objects, all from
a given ``Protocol``.
"""
return self.protocol.gather(protocol_dag_results=protocol_dag_results)
Expand All @@ -141,7 +137,7 @@ def dump(self, file):
"""Dump this Transformation to a JSON file.
Note that this is not space-efficient: for example, any
``Component`` which is used in both ``ChemicalSystem``s will be
``Component`` which is used in both ``ChemicalSystem`` objects will be
represented twice in the JSON output.
Parameters
Expand Down Expand Up @@ -173,25 +169,13 @@ class NonTransformation(Transformation):
"""A non-alchemical edge of an alchemical network.
A "transformation" that performs no transformation at all.
Technically a self-loop, or an edge with the same `ChemicalSystem` at
Technically a self-loop, or an edge with the same ``ChemicalSystem`` at
either end.
Functionally used for applying a dynamics protocol to a `ChemicalSystem`
Functionally used for applying a dynamics protocol to a ``ChemicalSystem``
that performs no alchemical transformation at all. This allows e.g.
equilibrium MD to be performed on a `ChemicalSystem` as desired alongside
alchemical protocols between it and and other `ChemicalSystem`s.
Attributes
----------
system : ChemicalSystem
protocol : Protocol
The protocol used to perform the dynamics. Includes all details needed
to perform required simulations/calculations.
name : Optional[str]
Optional identifier for the nontransformation; set this to a unique
value if adding multiple, otherwise identical transformations to the
same `AlchemicalNetwork` to avoid deduplication
equilibrium MD to be performed on a ``ChemicalSystem`` as desired alongside
alchemical protocols between it and and other ``ChemicalSystem`` objects.
"""

def __init__(
Expand All @@ -214,12 +198,17 @@ def stateB(self):
return self._system

@property
def system(self):
def system(self) -> ChemicalSystem:
return self._system

@property
def protocol(self):
"""The protocol for sampling dynamics of the `ChemicalSystem`."""
"""
The protocol for sampling dynamics of the `ChemicalSystem`.
Includes all details needed to perform required
simulations/calculations.
"""
return self._protocol

def _to_dict(self) -> dict:
Expand All @@ -239,7 +228,9 @@ def create(
extends: Optional[ProtocolDAGResult] = None,
name: Optional[str] = None,
) -> ProtocolDAG:
"""Returns a `ProtocolDAG` executing this `Transformation.protocol`."""
"""
Returns a ``ProtocolDAG`` executing this ``Transformation.protocol``.
"""
return self.protocol.create(
stateA=self.system,
stateB=self.system,
Expand Down

0 comments on commit 19ae779

Please sign in to comment.