Skip to content

Commit 4bb56e0

Browse files
committed
Add App module and RunSpec-based executor
- Introduce app module with App enum and command adapters - Add RunSpec to describe image, args and mounts for runs - Refactor executor to consume RunSpec and pass through to containers - Extend Docker and HPC paths to use RunSpec - Implement runners for Score, Rosetta, PyRosetta, RFdiffusion, ProteinMPNN, ProteinMPNN Script, LigandMPNN, and Picap
1 parent d0e542d commit 4bb56e0

File tree

13 files changed

+211
-195
lines changed

13 files changed

+211
-195
lines changed

src/app.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use std::collections::HashMap;
2+
3+
use clap::ValueEnum;
4+
5+
mod ligandmpnn;
6+
mod picap;
7+
mod proteinmpnn;
8+
mod proteinmpnn_script;
9+
mod pyrosetta;
10+
mod rfdiffusion;
11+
mod rosetta;
12+
mod score;
13+
14+
#[derive(ValueEnum, Clone, Copy, Debug, strum::Display)]
15+
#[clap(rename_all = "lowercase")]
16+
#[strum(serialize_all = "lowercase")] // "kebab-case"
17+
pub enum App {
18+
/// Run the Rosetta score command
19+
Score,
20+
21+
/// Run the Rosetta protocol
22+
Rosetta,
23+
24+
/// Start python in env where PyRosetta is installed and execute script
25+
#[value(aliases = ["PyRosetta"])]
26+
PyRosetta,
27+
28+
/// Run the RFdiffusion command https://github.com/RosettaCommons/RFdiffusion
29+
#[value(aliases = ["Rfdiffusion"])]
30+
Rfdiffusion,
31+
32+
/// Run the ProteinMPNN command https://github.com/dauparas/ProteinMPNN
33+
#[value(aliases = ["ProteinMPNN"])]
34+
Proteinmpnn,
35+
36+
/// Run the ProteinMPNN Script command https://github.com/dauparas/ProteinMPNN
37+
#[value(aliases = ["Proteinmpnn-script", "ProteinMPNN-Script"])]
38+
ProteinmpnnScript,
39+
40+
/// Run the LigandMPNN command https://github.com/dauparas/LigandMPNN
41+
#[value(aliases = ["LigandMPNN"])]
42+
Ligandmpnn,
43+
44+
/// Run the PiCAP/CAPSIF2 command https://github.com/Graylab/picap
45+
#[value(aliases = ["PiCAP", "CAPSIF2"])]
46+
Picap,
47+
}
48+
49+
pub struct Image(pub String);
50+
51+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
52+
pub enum MountRole {
53+
WorkingDir,
54+
Scratch,
55+
}
56+
57+
pub struct RunSpec {
58+
pub image: Image,
59+
pub args: Vec<String>,
60+
//pub scratch: Option<PathBuf>,
61+
pub mounts: HashMap<MountRole, String>,
62+
}
63+
64+
impl RunSpec {
65+
pub fn new(image: impl Into<String>, args: Vec<String>) -> Self {
66+
Self {
67+
image: Image(image.into()),
68+
args,
69+
mounts: HashMap::new(),
70+
}
71+
}
72+
pub fn scratch(mut self, p: impl Into<String>) -> Self {
73+
self.mounts.insert(MountRole::Scratch, p.into());
74+
self
75+
}
76+
pub fn working_dir(mut self, p: impl Into<String>) -> Self {
77+
self.mounts.insert(MountRole::WorkingDir, p.into());
78+
self
79+
}
80+
}
81+
82+
impl App {
83+
pub fn run_spec(self, app_args: Vec<String>) -> RunSpec {
84+
match self {
85+
App::Score => score::score(app_args),
86+
App::Rosetta => rosetta::rosetta(app_args),
87+
App::PyRosetta => pyrosetta::pyrosetta(app_args),
88+
App::Rfdiffusion => rfdiffusion::rfdiffusion(app_args),
89+
App::Proteinmpnn => proteinmpnn::proteinmpnn(app_args),
90+
App::ProteinmpnnScript => proteinmpnn_script::proteinmpnn_script(app_args),
91+
App::Ligandmpnn => ligandmpnn::ligandmpnn(app_args),
92+
App::Picap => picap::picap(app_args),
93+
}
94+
}
95+
}

src/app/ligandmpnn.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn ligandmpnn(mut app_args: Vec<String>) -> RunSpec {
4+
app_args.splice(
5+
0..0,
6+
[
7+
"--out_folder=/w".into(),
8+
"--checkpoint_protein_mpnn".into(),
9+
"/app/ligandmpnn/model_params/proteinmpnn_v_48_020.pt".into(),
10+
],
11+
);
12+
RunSpec::new("rosettacommons/ligandmpnn", app_args).working_dir("/w")
13+
}

src/app/picap.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn picap(mut app_args: Vec<String>) -> RunSpec {
4+
app_args.splice(
5+
0..0,
6+
[
7+
"--out_folder=/w".into(),
8+
"--checkpoint_protein_mpnn".into(),
9+
"/app/ligandmpnn/model_params/proteinmpnn_v_48_020.pt".into(),
10+
],
11+
);
12+
RunSpec::new("rosettacommons/picap", app_args).working_dir("/w")
13+
}

src/app/proteinmpnn.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn proteinmpnn(mut app_args: Vec<String>) -> RunSpec {
4+
app_args.splice(0..0, ["--out_folder=/w".into()]);
5+
RunSpec::new("rosettacommons/proteinmpnn", app_args).working_dir("/w")
6+
}

src/app/proteinmpnn_script.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn proteinmpnn_script(mut app_args: Vec<String>) -> RunSpec {
4+
assert!(
5+
app_args.is_empty() || app_args[0].starts_with("-"),
6+
"ProteinmpnnScript arguments must include a script name as first argument"
7+
);
8+
9+
let have_input_path_option = ![
10+
"helper_scripts/make_bias_AA.py",
11+
"helper_scripts/make_pssm_input_dict.py",
12+
]
13+
.contains(&app_args[0].as_str());
14+
15+
if have_input_path_option {
16+
app_args.splice(1..1, ["--input_path=/w".into()]);
17+
}
18+
app_args.splice(1..1, ["--output_path=/w".into()]);
19+
app_args[0].insert_str(0, "/app/proteinmpnn/helper_scripts/");
20+
21+
RunSpec::new("rosettacommons/proteinmpnn", app_args).working_dir("/w")
22+
}

src/app/pyrosetta.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn pyrosetta(mut app_args: Vec<String>) -> RunSpec {
4+
app_args.insert(0, "python".into());
5+
RunSpec::new("rosettacommons/rosetta:serial", app_args).working_dir("/w")
6+
}

src/app/rfdiffusion.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn rfdiffusion(mut app_args: Vec<String>) -> RunSpec {
4+
app_args.splice(
5+
0..0,
6+
[
7+
"inference.output_prefix=/w/".into(),
8+
"inference.model_directory_path=/app/RFdiffusion/models".into(),
9+
],
10+
);
11+
RunSpec::new("rosettacommons/rfdiffusion", app_args)
12+
.scratch("/app/RFdiffusion/schedules")
13+
.working_dir("/w")
14+
}

src/app/rosetta.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn rosetta(app_args: Vec<String>) -> RunSpec {
4+
RunSpec::new("rosettacommons/rosetta:serial", app_args).working_dir("/w")
5+
}

src/app/score.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use crate::app::RunSpec;
2+
3+
pub fn score(mut app_args: Vec<String>) -> RunSpec {
4+
app_args.insert(0, "score".into());
5+
RunSpec::new("rosettacommons/rosetta:serial", app_args).working_dir("/w")
6+
}

0 commit comments

Comments
 (0)