Protein-Ligand Binding Free Energy Benchmarks via alchemiscale
User Instructions
To get started with alchemiscale
, follow the steps below.
Use of the alchemiscale
instance at https://api.alchemiscale.org
will require a unique user identity+key; please reach out to @David Dotson if you need to use this instance and he will issue you these credentials. Please include in your request the organization(s) you will be submitting calculations for.
- 1 Installation
- 2 Creating an AlchemicalNetwork
- 3 Submitting your AlchemicalNetwork to alchemiscale
- 4 Creating and actioning Tasks
- 4.1 About Tasks
- 5 Getting the status of your Tasks
- 5.1 Scope
- 5.2 AlchemicalNetwork
- 5.3 Transformation
- 6 Pulling and assembling results
- 7 Dealing with errors
- 8 Re-running errored Tasks
Installation
Create a conda
environment on your workstation:
conda env create openforcefield/alchemiscale-client
You can also use mamba
instead of conda
above if you prefer a faster solver and have it installed, e.g. via mambaforge.
If this doesn’t work, clone alchemiscale
from Github, and install from there:
git clone https://github.com/openforcefield/alchemiscale.git
cd alchemiscale
git checkout v0.1.4-1
conda env create -f devtools/conda-envs/alchemiscale-client.yml
Once installed, activate the environment:
conda activate alchemiscale-client
You may wish to install other packages into this environment, such as jupyterlab
.
Installing on ARM-based Macs
If installing on an ARM-based Mac (M1, M2, etc.), you may need to use Rosetta. You can do this with the following steps:
Creating an AlchemicalNetwork
To create an AlchemicalNetwork
, review this notebook and apply the same approach to your systems of interest: Preparing AlchemicalNetworks.ipynb
Note that there are currently two Protocol
s you can use:
openfe.protocols.openmm_rfe.RelativeHybridTopologyProtocol
perses.protocols.nonequilibrium_cycling.NonEquilibriumCyclingProtocol
Try each one out with default options for a start. Below are notes on settings you may find more optimal for each, however.
RelativeHybridTopologyProtocol usage notes
@Irfan Alibay notes that this protocol can get timing down to about ~4h per edge on Tyk2 on an NVIDIA 4070 TI with the following settings; we recommend these for production use with alchemiscale.:
NonEquilibriumCyclingProtocol usage notes
For production use of this protocol, we recommend the default settings:
On the use of HMR and hydrogen mass settings
By default the two protocols use hydrogen mass repartitioning (HMR) in order to achieve time steps of up to 4 fs. We have noticed that the choice of value (4.0 amu vs 3.0 amu) for mass repartitioning can impact simulation stability. We recommend in all cases to use 3.0 amu.
For now (gufe v0.7.2) the default is incorrectly set to 4.0 amu so we recommend users to set the following:
Submitting your AlchemicalNetwork
to alchemiscale
Once you’ve defined an AlchemicalNetwork
, you can submit it to the alchemiscale
instance at https://api.alchemiscale.org
. Create an AlchemiscaleClient
instance with that URL and your user identity+key:
Choosing a Scope
Choose a Scope
to submit your network to. A Scope
is an org
-campaign
-project
triple, and your user will have permissions to work within some of these. You can list your accessible Scope
s with:
If you are an OpenFF user, you will likely see the Scope
<Scope('openff-*-*')>
among this list. This means that you can submit your network to any Scope
matching that pattern, such as openff-my_special_campaign-tyk2_testing_1
. A Scope
without any wildcards ('*'
), or a specific Scope
, such as this is needed for submission. Create one with, e.g.:
Within a Scope
, components of an AlchemicalNetwork
are deduplicated against other components already present, allowing you to e.g. submit new AlchemicalNetwork
s sharing Transformation
s with previous ones and benefit from existing calculation results. If you prefer to have an AlchemicalNetwork
not share any components with previously-submitted AlchemicalNetwork
s, then submit it into a different Scope
, such as openff-my_special_campaign-tyk2_testing_2
as in the example above.
Submitting and retrieving a network
Submit your network:
This will return a ScopedKey
uniquely identifying your AlchemicalNetwork
. A ScopedKey
is a combination of network.key
and the Scope
we submitted it to, e.g.:
You can pull the full network back down (even in another Python session) with:
You can always produce a ScopedKey
from its string representation with ScopedKey.from-str(<scoped-key-str>)
, allowing for copy-paste from one session to another.
You can list all your accessible AlchemicalNetwork
s on the alchemiscale
instance with:
and you can use these with get_network
above to pull them down as desired.
Creating and actioning Task
s
Submitting an AlchemicalNetwork
defines it on the alchemiscale
server, but it does not define where to allocate effort in evaluating the Transformation
s in the network. To do this, we need to create and action Task
s on the Transformation
s we are most interested in.
For this example, we’ll loop through every Transformation
in our AlchemicalNetwork
, and create+action 3 Task
s for each:
A Task
is associated with a Transformation
on creation, and actioning the Task
marks it for execution for our AlchemicalNetwork
we submitted earlier. If we submit another AlchemicalNetwork
including some of the same Transformation
s later to the same Scope
, we could get the Task
s for each Transformation
and only create new Task
s if necessary, actioning the existing ones to that AlchemicalNetwork
as well:
The more AlchemicalNetwork
s a Task
is actioned to, the higher its chances of being picked up by a compute service. In this way, actioning is an indicator of demand for a given Task
and its corresponding Transformation
.
About Task
s
Alchemiscale Task
s can be considered a single independent “repeat” of an alchemical transformation, or a ProtocolDAG as defined in gufe
. What this exactly means will be subtly different depending on the type of alchemical protocol employed.
In the case of the RelativeHybridTopologyProtocol
(i.e. for HREX, and SAMS), this effectively means that each Task
carries out all the computation required to obtain a single estimate of the free energy (in practice one would want to do several repeats to get an idea of the sampling error).
In the case of the NonEquilibriumCyclingProtocol
, a Task
instead encompasses a non-equilibrium cycle and will return a single work
estimate. The work
values of multiple Task
s can then be gathered to obtain a free energy estimate, and more Task
s will improve the convergence of the estimate.
Getting the status of your Task
s
As you await results for your actioned Task
s, it’s often desirable to check their to ensure they are running or completing at the rate you expect. You can quickly obtain statuses for all Task
s associated with various levels, including:
Scope
AlchemicalNetwork
Transformation
Scope
For example, to get the status counts for all Task
s within a particular Scope
, you could do:
For a specific Scope
, this will give status counts of all Task
s within that exact Scope
, assuming your user has permissions on it (see asc.list_scopes()
for your accessible Scope
space). For a non-specific Scope
(like my_org-my_campaign-*
above, this will give the aggregate status counts across the Scope
space visible to your user under the given Scope
.
Calling asc.get_scope_status()
without arguments will default to the highest non-specific Scope
of *-*-*
.
To get the specific statuses of all Task
s in a given Scope
, use the query_tasks
method in combination with get_tasks_status
:
AlchemicalNetwork
You can get the status counts of all Task
s associated with Transformation
s within a given AlchemicalNetwork
with:
Note that this will show status counts for all such Task
s, whether or not they have been actioned on the given AlchemicalNetwork
.
To get the specific statuses of all Task
s for a given AlchemicalNetwork
, use the get_network_tasks
method in combination with get_tasks_status
:
Transformation
To get the status counts of all Task
s associated with only a given Transformation
, use:
To get the specific statuses of all Task
s for a given Transformation
, use the get_transformation_tasks
method in combination with get_tasks_status
:
Pulling and assembling results
A Protocol
is attached to each Transformation
, and that Protocol
defines how each Task
is computed. It also defines how the results of each Task
(called a ProtocolDAGResult
) are combined to give an estimate of the free energy difference for that Transformation
.
We can check the status of a Transformation
with:
If there are complete Task
s, we can pull in all successful ProtocolDAGResult
s for the Transformation
and combine them into a ProtocolResult
corresponding to that Transformation
's Protocol
with:
This object features a get_estimate
and get_uncertainty
method, giving the best available estimate of the free energy difference and its uncertainty.
To pull the ProtocolDAGResult
s and not combine them into a ProtocolResult
object, you can give return_protocoldagresults=True
to this method. Any number of ProtocolDAGResult
s can then be manually combined into a single ProtocolResult
with:
This can be useful for subsampling the available ProtocolDAGResult
s and building estimates from these subsamples, such as for an analysis of convergence for the NonEquilibriumCyclingProtocol
.
If you wish to pull results for only a single Task
, you can do so with:
You can then iteratively create+action new Task
s on your desired Transformation
s based on their current estimate and uncertainty, allocating effort where it will be most beneficial.
Dealing with errors
If you observe many errored Task
s from running asc.get_transformation_status
, you can introspect the traceback raised by the Task
on execution. For a given Transformation
, you can pull down all failed results and print their exceptions and tracebacks with:
This may give you clues as to what is going wrong with your Transformation
s. A failure may be a symptom of the environments the compute services are running with; it could also indicate some fundamental problems with the Transformation
s you are attempting to execute, and in this case trying to reproduce the error locally and experimenting with possible solutions is appropriate. You may want to try different Protocol
settings, different Mapping
s, or try to adjust the components in your ChemicalSystem
s.
For a given Transformation
, you can execute it locally with:
Note that for some Protocol
s, your local machine may need to meet certain requirements:
perses.protocols.nonequilibrium_cycling.NonEquilibriumCyclingProtocol
: OpenEye Toolkit license, NVIDIA GPU ifsettings.platform == 'CUDA'
Re-running error
ed Task
s
If you believe an error
ed Task
is due to a random failure (such as landing on a flaky compute host, or due to inherent stochasticity in the protocol itself), or due to a systematic failure that has been resolved (such as a misconfigured compute environment, now remediated), you can choose to set that Task
s status back to waiting
. This will make it eligible for being claimed and executed again, perhaps succefully.
Given a set of Task
s you wish to set back to waiting
, you can do:
Only Task
s with status error
or running
can be set back to waiting
; it is not possible to set Task
s with status complete
, invalid
, or deleted
back to waiting
.
If you’re feeling confident, you could set all error
ed Task
s on a given AlchemicalNetwork
with: