Repository navigation
add task-based execution tutorials #322
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
Open
atravitz
wants to merge
27
commits into
main
Choose a base branch
from
feat/add_worker_based_execution
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
d32b02e
add worker-based execution example notebook
atravitz d46a091
add example
atravitz c6b32a8
rename
atravitz 8df01c5
copy over rbfe CLI as a starting point
atravitz 5a09a1c
update gitignore
atravitz 83567c6
add todo
atravitz 7702492
fix comment
atravitz a626a79
Add more explanation
hannahbaumann fb2d996
Merge branch 'main' into feat/add_worker_based_execution
hannahbaumann 7d246ab
More tutorial updates
hannahbaumann 14883b6
More tutorial updates
hannahbaumann 4ee1457
Merge branch 'feat/add_worker_based_execution' of github.com:OpenFree…
hannahbaumann 1397db0
More changes
hannahbaumann d7a5f6b
Update environment.yaml
hannahbaumann f45a782
Address review comments
hannahbaumann c1d0512
Merge branch 'feat/add_worker_based_execution' of github.com:OpenFree…
hannahbaumann 95a621f
Merge branch 'main' into feat/add_worker_based_execution
hannahbaumann 18a74dd
address review comments
hannahbaumann e968a6c
Add CLI tutorial
hannahbaumann 708a0d5
some more changes
hannahbaumann ff78737
small change
hannahbaumann 6ba026f
Merge branch 'main' into feat/add_worker_based_execution
atravitz 13d56c8
fix typo in filename
atravitz c79096e
update gitignore
atravitz c779ea4
update output dir name
atravitz 3af15ef
add max_tries tips
atravitz 1d6bef7
Update execution/task_based_execution_cli.md
hannahbaumann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
execution/alchemicalNetwork_mcl1_small/alchemicalNetwork_mcl1_small.json
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,298 @@ | ||
| # Task-Based Execution with the OpenFE CLI | ||
|
|
||
| When using `openfe quickrun`, you orchestrate the campaign. You choose which | ||
| `Transformation` to run and when to run it. | ||
|
|
||
| With task-based execution, **openfe** handles that orchestration for you. You provide | ||
| an entire `AlchemicalNetwork`, **openfe** breaks it into dependent tasks, and one or | ||
| more `Worker`s claim tasks as soon as they are ready to run. | ||
|
|
||
| A **task** is a single `ProtocolUnit`, for example the setup, simulation, or | ||
| analysis step of one repeat of one `Transformation`. | ||
|
|
||
| Three resources make up a task-based campaign: | ||
|
|
||
| - the **Warehouse** stores the campaign data needed for execution, including the | ||
| `AlchemicalNetwork`, tasks, and results; | ||
| - the **TaskStatusDB** tracks task status and dependencies; | ||
| - calls to ``run-task`` (equivalent to the ``Worker.execute_unit()`` in the Python API) claim available tasks, execute them, and store the results. | ||
|
|
||
| This tutorial walks through a task-based campaign using the OpenFE command-line | ||
| interface. For the equivalent workflow using the Python API, see the | ||
| [Task-Based Execution with the Python API tutorial](...). | ||
|
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. note for one of us to add a link |
||
|
|
||
| > **Note:** To run this tutorial, clone the OpenFE ExampleNotebooks repository | ||
| > and run these commands from the tutorial directory. The example input files | ||
| > used below are included in the repository. | ||
|
|
||
| ## 1. Start from an `AlchemicalNetwork` | ||
|
|
||
| The input to a task-based campaign is an `AlchemicalNetwork`. | ||
|
|
||
| Here we use a small MCL-1 network with pre-charged ligands and two edges, | ||
| `ligand_1 → ligand_2` and `ligand_2 → ligand_3`. Each edge has a complex and a | ||
| solvent leg, giving four `Transformation`s. | ||
|
|
||
| For this example, each `Transformation` has one repeat, and each repeat of the | ||
| hybrid-topology protocol consists of setup, simulation, and analysis units. | ||
| The campaign therefore contains 12 tasks in total. | ||
|
|
||
| If you are setting up your own campaign with `openfe plan-rbfe-network` or | ||
| `openfe plan-rhfe-network`, use `--networks-only` to generate an | ||
| `AlchemicalNetwork` for task-based execution. For example: | ||
|
|
||
| ```bash | ||
| >>> openfe plan-rbfe-network -M ligands.sdf -p protein.pdb --networks-only -o alchemicalNetwork_mcl1_small --n-protocol-repeats=1 | ||
| ``` | ||
|
|
||
| This creates an `AlchemicalNetwork` JSON file that can be used as input to | ||
| `openfe setup-task-campaign`. | ||
|
|
||
| > **Note:** Unlike `quickrun` execution, task-based execution creates a separate set of tasks for each repeat, | ||
| > so different repeats can be executed in parallel by different workers. | ||
| > For production calculations, we recommend keeping the default of `--n-protocol-repeats=3`. | ||
| > To keep this tutorial small, however, we use a single repeat. | ||
|
|
||
| ## 2. Set up the campaign | ||
|
|
||
| Use `openfe setup-task-campaign` to create the resources needed for task-based | ||
| execution. By default, the `TaskStatusDB` and `Warehouse` will be created using the input file basename, | ||
| but you can pass in the `--name` parameter to define the identifier for the `Warehouse` and `TaskStatusDB` file names. | ||
|
|
||
| ```bash | ||
| >>> openfe setup-task-campaign --alchemical-network alchemicalNetwork_mcl1_small/alchemicalNetwork_mcl1_small.json --name mcl1 | ||
| ``` | ||
|
|
||
| You should see a `Warehouse` (`warehouse_tyk2/`) in the form of a directory and a `TaskStatusDB` (`tasks_tyk2.db`) file as output. | ||
|
|
||
| ```text | ||
| warehouse_mcl1/ | ||
| tasks_mcl1.db | ||
| ``` | ||
|
|
||
| The `Warehouse` contains the campaign data and results, while the | ||
| `TaskStatusDB` contains the orchestration state of the campaign. | ||
|
|
||
| > **Warning:** The `Warehouse` has a specific directory structure and should not | ||
| > be edited manually. | ||
|
|
||
| At this point, the `Warehouse` contains the information needed to describe and | ||
| execute the campaign: | ||
|
|
||
| ```text | ||
| warehouse_mcl1/ | ||
| ├── protocol_dags/ | ||
| ├── results/ | ||
| ├── setup/ | ||
| ├── shared/ | ||
| └── tasks/ | ||
| ``` | ||
|
|
||
| The `setup`, `tasks`, and `protocol_dags` stores are populated when the campaign | ||
| is created. `results` and `shared` are populated during execution. | ||
|
|
||
| > **Note:** If you're migrating from `quickrun`-based execution, the `Warehouse` directory contains the information that would | ||
| > otherwise be stored across a directory of `transformation.json` files, organized in a different structure for | ||
| > task-based execution. | ||
|
|
||
| ## 3. Inspect task status | ||
|
|
||
| The `TaskStatusDB` is the source of truth for the execution state of the | ||
| campaign. | ||
|
|
||
| You can inspect it at any time with: | ||
|
|
||
| ```bash | ||
| >>> openfe status --task-db tasks_mcl1.db | ||
| ``` | ||
|
|
||
| For this network, there are initially: | ||
|
|
||
| ```text | ||
| ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━┓ | ||
| ┃ taskid ┃ status ┃ last_modified ┃ tries ┃ max_tries ┃ | ||
| ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━┩ | ||
| │ HybridTopologySetupUnit-31fdc6a... │ AVAILABLE │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologySetupUnit-15899f7... │ AVAILABLE │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologySetupUnit-9212216... │ AVAILABLE │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologySetupUnit-d5d714f... │ AVAILABLE │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologyMultiStateSimulationUnit-415456a... │ BLOCKED │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologyMultiStateSimulationUnit-23aea7d... │ BLOCKED │ NaT │ 0 │ 1 │ | ||
| │ ... │ ... │ ... │ ... │ ... │ | ||
| │ HybridTopologyMultiStateAnalysisUnit-9354cb2... │ BLOCKED │ NaT │ 0 │ 1 │ | ||
| └─────────────────────────────────────────────────────────────────────────┴───────────┴───────────────┴───────┴───────────┘ | ||
| ``` | ||
|
|
||
| Initially, the four setup tasks are `AVAILABLE`. The simulation and analysis | ||
| tasks are `BLOCKED` because their dependencies have not completed yet. | ||
| The `tries` column records how many times a task has been attempted, while | ||
| `max_tries` gives the maximum number of attempts allowed. | ||
|
|
||
| To display only the number of tasks in each state, use: | ||
|
|
||
| ```bash | ||
| >>> openfe status --task-db tasks_mcl1.db --summary | ||
| ``` | ||
|
|
||
| ```text | ||
| ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ | ||
| ┃ status ┃ n_tasks ┃ | ||
| ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ | ||
| │ BLOCKED │ 8 │ | ||
| │ AVAILABLE │ 4 │ | ||
| │ IN_PROGRESS │ 0 │ | ||
| │ COMPLETED │ 0 │ | ||
| │ TOO_MANY_RETRIES │ 0 │ | ||
| │ ERROR │ 0 │ | ||
| └──────────────────┴─────────┘ | ||
| ``` | ||
|
|
||
| As execution proceeds, tasks move through states such as `AVAILABLE`, | ||
| `IN_PROGRESS`, and `COMPLETED`. Failed tasks are retried up to `max_tries`, then marked `TOO_MANY_RETRIES`. | ||
|
|
||
| ## 4. Execute one task | ||
|
|
||
| A worker uses the `Warehouse` and the `TaskStatusDB` to execute tasks from the campaign. | ||
| To execute one available task, run: | ||
|
|
||
| ```bash | ||
| >>> openfe run-task --warehouse warehouse_mcl1/ --task-db tasks_mcl1.db --scratch scratch/ | ||
| ``` | ||
|
|
||
| You do not choose which specific task is executed. `openfe run-task` claims an | ||
| `AVAILABLE` task from the `TaskStatusDB`, retrieves the corresponding | ||
| `ProtocolUnit` and any required upstream data from the `Warehouse`, and executes | ||
| it. | ||
|
|
||
| Now, you will see that a `scratch/` directory has been created locally, which is needed for quick read/write | ||
| operations during execution. Use the `--scratch` argument to specify where to create this directory; | ||
| by default, it will be created in the current directory and named `scratch/`. | ||
|
|
||
| You'll now see that one task has been completed, and a new task has been unblocked: | ||
|
|
||
| ```bash | ||
| >>> openfe status --task-db tasks_mcl1.db | ||
| ``` | ||
|
|
||
| ```text | ||
| ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━┓ | ||
| ┃ taskid ┃ status ┃ last_modified ┃ tries ┃ max_tries ┃ | ||
| ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━┩ | ||
| │ HybridTopologySetupUnit-31fdc6a... │ COMPLETED │ 2026-10-06 13:10:00 │ 1 │ 1 │ | ||
| │ HybridTopologySetupUnit-15899f7... │ AVAILABLE │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologySetupUnit-9212216... │ AVAILABLE │ NaT │ 0 │ 1 │ | ||
| │ HybridTopologyMultiStateSimulationUnit-415456a... │ AVAILABLE │ 2026-10-06 13:10:00 │ 0 │ 1 │ | ||
| │ HybridTopologyMultiStateSimulationUnit-23aea7d... │ BLOCKED │ NaT │ 0 │ 1 │ | ||
| │ ... │ ... │ ... │ ... │ ... │ | ||
| │ HybridTopologyMultiStateAnalysisUnit-9354cb2... │ BLOCKED │ NaT │ 0 │ 1 │ | ||
| └──────────────────────────────────────────────────────┴───────────┴─────────────────────┴───────┴───────────┘ | ||
| ``` | ||
|
|
||
| One setup task is now `COMPLETED`, and the simulation task that depended on it is now `AVAILABLE`. | ||
| The remaining downstream tasks stay `BLOCKED` until their dependencies are satisfied. | ||
|
|
||
| **Tip**: You can use ``openfe update-task-db`` command to update the `max_tries` column for all valid rows of the TaskDB. Note that rows that are marked ``COMPLETED`` or whose ``tries`` are greater than the provided value will not be updated. | ||
|
|
||
| ```bash | ||
| >>> openfe update-task-db --task-db tasks_mcl1.db --max-tries 2 | ||
| ``` | ||
|
|
||
| ```text | ||
| ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━┓ | ||
| ┃ taskid ┃ status ┃ last_modified ┃ tries ┃ max_tries ┃ | ||
| ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━┩ | ||
| │ HybridTopologySetupUnit-31fdc6a... │ COMPLETED │ 2026-10-06 13:10:00 │ 1 │ 1 │ | ||
| │ HybridTopologySetupUnit-15899f7... │ AVAILABLE │ NaT │ 0 │ 2 │ | ||
| │ HybridTopologySetupUnit-9212216... │ AVAILABLE │ NaT │ 0 │ 2 │ | ||
| │ HybridTopologyMultiStateSimulationUnit-415456a... │ AVAILABLE │ 2026-10-06 13:10:00 │ 0 │ 2 │ | ||
| │ HybridTopologyMultiStateSimulationUnit-23aea7d... │ BLOCKED │ NaT │ 0 │ 2 │ | ||
| │ ... │ ... │ ... │ ... │ ... │ | ||
| │ HybridTopologyMultiStateAnalysisUnit-9354cb2... │ BLOCKED │ NaT │ 0 │ 2 │ | ||
| └──────────────────────────────────────────────────────┴───────────┴─────────────────────┴───────┴───────────┘ | ||
| ``` | ||
|
|
||
|
|
||
| ## 5. Run the rest of the campaign | ||
|
|
||
| Running `openfe run-task` once executes one task. A worker can repeatedly | ||
| execute tasks by calling it in a loop. | ||
|
|
||
| For example, a simple SLURM worker script could contain: | ||
|
|
||
| ```bash | ||
| #!/bin/bash | ||
|
|
||
| #SBATCH --job-name="openfe-worker" | ||
| #SBATCH --gres=gpu:1 | ||
| #SBATCH --mem-per-cpu=2G | ||
|
|
||
| # Activate the environment containing OpenFE | ||
| conda activate openfe_env | ||
|
|
||
| # continue submitting run-task in serial until the wall time is hit | ||
| # you may submit this *script* multiple times to have workers execute tasks in parallel | ||
|
|
||
| while true; do | ||
| openfe run-task --warehouse warehouse_mcl1/ --task-db tasks_mcl1.db --scratch scratch/ | ||
| done | ||
| ``` | ||
|
|
||
| In production, several independent workers can run in separate jobs on an HPC | ||
| system, all operating on the same campaign to execute tasks in parallel. | ||
| For example, using a SLURM job array: | ||
|
|
||
| ```bash | ||
| >>> sbatch --array=1-4 run_tasks.sh | ||
| ``` | ||
|
|
||
|
|
||
| All workers use the same `Warehouse` and `TaskStatusDB`. The task database | ||
| coordinates which tasks are available for each worker to claim. | ||
|
|
||
| ## 6. Gather results | ||
|
|
||
| Running the complete simulations would take too long for this tutorial, so for | ||
| this section we use a completed `Warehouse` from the same example network. | ||
|
|
||
| Download and extract the completed Warehouse: | ||
|
|
||
| ```bash | ||
| >>> curl -fLO https://zenodo.org/records/23072369/files/warehouse_mcl1_small.gz | ||
| >>> tar -xzf warehouse_mcl1_small.gz | ||
| ``` | ||
|
|
||
| This creates the warehouse_mcl1_small/ directory containing the results of the | ||
| completed campaign. | ||
|
|
||
| The `Warehouse` contains the `ProtocolUnitResult`s produced during execution. | ||
|
|
||
| Because task-based execution is currently under development, there is not yet a direct command to output the results. | ||
| To enable complete workflows in the meantime, we provide the `openfe to-legacy-json` command to | ||
| convert these results into the JSON format accepted by the existing | ||
| `openfe gather` command: | ||
|
|
||
| ```bash | ||
| >>> openfe to-legacy-json warehouse_mcl1_small/ -o mcl1_result_jsons | ||
| ``` | ||
|
|
||
| The resulting directory can then be passed to `openfe gather` (and `openfe gather-septop`, `openfe gather-abfe`). | ||
|
|
||
| ```bash | ||
| >>> openfe gather mcl1_result_jsons/ --report=raw | ||
| ``` | ||
|
|
||
| For an RBFE campaign, `--report=raw` shows the individual complex and solvent | ||
| leg results. Other `openfe gather` report types can be used to obtain | ||
| edge-level relative free energies or network-level estimates. | ||
|
|
||
| ## Summary | ||
|
|
||
| In this tutorial, we: | ||
|
|
||
| - created a task-based campaign from an `AlchemicalNetwork` with | ||
| `openfe setup-task-campaign`; | ||
| - inspected task state with `openfe status`; | ||
| - used `openfe run-task` to claim and execute available tasks; | ||
| - saw how completing a task makes downstream tasks available; | ||
| - showed how multiple workers can execute tasks from the same campaign; | ||
| - gathered results produced by a completed campaign. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is copy/pasted from the quickrun cli instructions. maybe we should move https://github.com/OpenFreeEnergy/openfe/blob/151108ebda6d0571ca4ea338b996eb193d7b82c8/docs/guide/execution/task_based_execution.rst#L7-L8 from the User Guide into here instead? That way the CLI and API docs live together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied things over from the user guide, for the intro I copied over the intro from the API tutorial, and then I used claude to structure this more tutorial like (headings,...). Please let me know what you think!