rowan-python 2.1.12__py3-none-any.whl → 2.1.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rowan/workflow.py CHANGED
@@ -22,7 +22,7 @@ StJamesMolecule: TypeAlias = stjames.Molecule
22
22
  class Workflow(BaseModel):
23
23
  """A Rowan workflow.
24
24
 
25
- Dont instantiate this class directly. Instead use one of the submit workflow functions.
25
+ Don't instantiate this class directly. Instead use one of the submit workflow functions.
26
26
  Workflow data is not loaded by default to avoid unnecessary downloads that could impact
27
27
  performance. Call `load_data()` to fetch and attach the workflow data to this `Workflow` object.
28
28
 
@@ -312,11 +312,13 @@ def submit_workflow(
312
312
  if initial_smiles is not None:
313
313
  data["initial_smiles"] = initial_smiles
314
314
  elif isinstance(initial_molecule, StJamesMolecule):
315
- data["initial_molecule"] = initial_molecule.model_dump()
315
+ data["initial_molecule"] = initial_molecule.model_dump(mode="json")
316
316
  elif isinstance(initial_molecule, dict):
317
317
  data["initial_molecule"] = initial_molecule
318
318
  elif isinstance(initial_molecule, RdkitMol):
319
- data["initial_molecule"] = StJamesMolecule.from_rdkit(initial_molecule, cid=0).model_dump()
319
+ data["initial_molecule"] = StJamesMolecule.from_rdkit(initial_molecule, cid=0).model_dump(
320
+ mode="json"
321
+ )
320
322
  else:
321
323
  raise ValueError("You must provide either `initial_smiles` or a valid `initial_molecule`.")
322
324
 
@@ -538,7 +540,7 @@ def submit_basic_calculation_workflow(
538
540
  tasks = ["optimize"]
539
541
 
540
542
  if isinstance(initial_molecule, StJamesMolecule):
541
- initial_molecule = initial_molecule.model_dump()
543
+ initial_molecule = initial_molecule.model_dump(mode="json")
542
544
  elif isinstance(initial_molecule, RdkitMol):
543
545
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
544
546
 
@@ -560,7 +562,7 @@ def submit_basic_calculation_workflow(
560
562
  "name": name,
561
563
  "folder_uuid": folder_uuid,
562
564
  "workflow_type": "basic_calculation",
563
- "workflow_data": workflow.model_dump(),
565
+ "workflow_data": workflow.model_dump(mode="json"),
564
566
  "initial_molecule": initial_molecule,
565
567
  "max_credits": max_credits,
566
568
  }
@@ -573,7 +575,7 @@ def submit_basic_calculation_workflow(
573
575
 
574
576
  def submit_conformer_search_workflow(
575
577
  initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol,
576
- conf_gen_mode: str = "rapid",
578
+ conf_gen_settings: stjames.ConformerGenSettings,
577
579
  final_method: stjames.Method | str = "aimnet2_wb97md3",
578
580
  solvent: str | None = None,
579
581
  transition_state: bool = False,
@@ -585,9 +587,7 @@ def submit_conformer_search_workflow(
585
587
  Submits a conformer search workflow to the API.
586
588
 
587
589
  :param initial_molecule: The molecule to perform the conformer search on.
588
- :param conf_gen_mode: The mode to use for conformer generation. See
589
- [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
590
- for options.
590
+ :param conf_gen_settings: settings for conformer generation
591
591
  :param final_method: The method to use for the final optimization.
592
592
  See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
593
593
  for options.
@@ -601,7 +601,7 @@ def submit_conformer_search_workflow(
601
601
  :raises requests.HTTPError: if the request to the API fails.
602
602
  """
603
603
  if isinstance(initial_molecule, StJamesMolecule):
604
- initial_molecule = initial_molecule.model_dump()
604
+ initial_molecule = initial_molecule.model_dump(mode="json")
605
605
  elif isinstance(initial_molecule, RdkitMol):
606
606
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
607
607
 
@@ -629,8 +629,7 @@ def submit_conformer_search_workflow(
629
629
  workflow = stjames.ConformerSearchWorkflow(
630
630
  initial_molecule=initial_molecule,
631
631
  multistage_opt_settings=msos,
632
- conf_gen_mode=conf_gen_mode,
633
- mso_mode="manual",
632
+ conf_gen_settings=conf_gen_settings,
634
633
  solvent=solvent,
635
634
  transition_state=transition_state,
636
635
  )
@@ -639,7 +638,7 @@ def submit_conformer_search_workflow(
639
638
  "name": name,
640
639
  "folder_uuid": folder_uuid,
641
640
  "workflow_type": "conformer_search",
642
- "workflow_data": workflow.model_dump(),
641
+ "workflow_data": workflow.model_dump(mode="json"),
643
642
  "initial_molecule": initial_molecule,
644
643
  "max_credits": max_credits,
645
644
  }
@@ -690,7 +689,7 @@ def submit_solubility_workflow(
690
689
  "name": name,
691
690
  "folder_uuid": folder_uuid,
692
691
  "workflow_type": "solubility",
693
- "workflow_data": workflow.model_dump(),
692
+ "workflow_data": workflow.model_dump(mode="json"),
694
693
  "initial_smiles": initial_smiles,
695
694
  "max_credits": max_credits,
696
695
  }
@@ -762,8 +761,10 @@ def submit_pka_workflow(
762
761
  "name": name,
763
762
  "folder_uuid": folder_uuid,
764
763
  "workflow_type": "pka",
765
- "workflow_data": workflow.model_dump(),
766
- "initial_molecule": initial_stjames_mol.model_dump() if initial_stjames_mol else None,
764
+ "workflow_data": workflow.model_dump(mode="json"),
765
+ "initial_molecule": initial_stjames_mol.model_dump(mode="json")
766
+ if initial_stjames_mol
767
+ else None,
767
768
  "initial_smiles": initial_smiles,
768
769
  "max_credits": max_credits,
769
770
  }
@@ -799,7 +800,7 @@ def submit_redox_potential_workflow(
799
800
  :raises requests.HTTPError: if the request to the API fails.
800
801
  """
801
802
  if isinstance(initial_molecule, StJamesMolecule):
802
- initial_molecule = initial_molecule.model_dump()
803
+ initial_molecule = initial_molecule.model_dump(mode="json")
803
804
  elif isinstance(initial_molecule, RdkitMol):
804
805
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
805
806
 
@@ -814,7 +815,7 @@ def submit_redox_potential_workflow(
814
815
  "name": name,
815
816
  "folder_uuid": folder_uuid,
816
817
  "workflow_type": "redox_potential",
817
- "workflow_data": workflow.model_dump(),
818
+ "workflow_data": workflow.model_dump(mode="json"),
818
819
  "initial_molecule": initial_molecule,
819
820
  "max_credits": max_credits,
820
821
  }
@@ -848,7 +849,7 @@ def submit_fukui_workflow(
848
849
  :raises requests.HTTPError: if the request to the API fails.
849
850
  """
850
851
  if isinstance(initial_molecule, StJamesMolecule):
851
- initial_molecule = initial_molecule.model_dump()
852
+ initial_molecule = initial_molecule.model_dump(mode="json")
852
853
  elif isinstance(initial_molecule, RdkitMol):
853
854
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
854
855
 
@@ -862,9 +863,9 @@ def submit_fukui_workflow(
862
863
  )
863
864
 
864
865
  workflow_data = {
865
- "opt_settings": optimization_settings.model_dump(),
866
+ "opt_settings": optimization_settings.model_dump(mode="json"),
866
867
  "opt_engine": stjames.Method(optimization_method).default_engine(),
867
- "fukui_settings": fukui_settings.model_dump(),
868
+ "fukui_settings": fukui_settings.model_dump(mode="json"),
868
869
  "fukui_engine": stjames.Method(fukui_method).default_engine(),
869
870
  }
870
871
 
@@ -904,7 +905,7 @@ def submit_tautomer_search_workflow(
904
905
  :raises requests.HTTPError: if the request to the API fails.
905
906
  """
906
907
  if isinstance(initial_molecule, StJamesMolecule):
907
- initial_molecule = initial_molecule.model_dump()
908
+ initial_molecule = initial_molecule.model_dump(mode="json")
908
909
  elif isinstance(initial_molecule, RdkitMol):
909
910
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
910
911
 
@@ -917,7 +918,7 @@ def submit_tautomer_search_workflow(
917
918
  "name": name,
918
919
  "folder_uuid": folder_uuid,
919
920
  "workflow_type": "tautomers",
920
- "workflow_data": workflow.model_dump(),
921
+ "workflow_data": workflow.model_dump(mode="json"),
921
922
  "initial_molecule": initial_molecule,
922
923
  "max_credits": max_credits,
923
924
  }
@@ -945,7 +946,7 @@ def submit_descriptors_workflow(
945
946
  :raises requests.HTTPError: if the request to the API fails.
946
947
  """
947
948
  if isinstance(initial_molecule, StJamesMolecule):
948
- initial_molecule = initial_molecule.model_dump()
949
+ initial_molecule = initial_molecule.model_dump(mode="json")
949
950
  elif isinstance(initial_molecule, RdkitMol):
950
951
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
951
952
 
@@ -991,7 +992,7 @@ def submit_scan_workflow(
991
992
  :raises requests.HTTPError: if the request to the API fails.
992
993
  """
993
994
  if isinstance(initial_molecule, StJamesMolecule):
994
- initial_molecule = initial_molecule.model_dump()
995
+ initial_molecule = initial_molecule.model_dump(mode="json")
995
996
  elif isinstance(initial_molecule, RdkitMol):
996
997
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
997
998
 
@@ -1018,7 +1019,7 @@ def submit_scan_workflow(
1018
1019
  "name": name,
1019
1020
  "folder_uuid": folder_uuid,
1020
1021
  "workflow_type": "scan",
1021
- "workflow_data": workflow.model_dump(),
1022
+ "workflow_data": workflow.model_dump(mode="json"),
1022
1023
  "initial_molecule": initial_molecule,
1023
1024
  "max_credits": max_credits,
1024
1025
  }
@@ -1072,7 +1073,7 @@ def submit_macropka_workflow(
1072
1073
  "name": name,
1073
1074
  "folder_uuid": folder_uuid,
1074
1075
  "workflow_type": "macropka",
1075
- "workflow_data": workflow.model_dump(),
1076
+ "workflow_data": workflow.model_dump(mode="json"),
1076
1077
  "initial_smiles": initial_smiles,
1077
1078
  "max_credits": max_credits,
1078
1079
  }
@@ -1111,7 +1112,7 @@ def submit_irc_workflow(
1111
1112
  """
1112
1113
 
1113
1114
  if isinstance(initial_molecule, StJamesMolecule):
1114
- initial_molecule = initial_molecule.model_dump()
1115
+ initial_molecule = initial_molecule.model_dump(mode="json")
1115
1116
  elif isinstance(initial_molecule, RdkitMol):
1116
1117
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
1117
1118
 
@@ -1136,7 +1137,7 @@ def submit_irc_workflow(
1136
1137
  "name": name,
1137
1138
  "folder_uuid": folder_uuid,
1138
1139
  "workflow_type": "irc",
1139
- "workflow_data": workflow.model_dump(),
1140
+ "workflow_data": workflow.model_dump(mode="json"),
1140
1141
  "initial_molecule": initial_molecule,
1141
1142
  "max_credits": max_credits,
1142
1143
  }
@@ -1193,7 +1194,7 @@ def submit_protein_cofolding_workflow(
1193
1194
  "name": name,
1194
1195
  "folder_uuid": folder_uuid,
1195
1196
  "workflow_type": "protein_cofolding",
1196
- "workflow_data": workflow.model_dump(),
1197
+ "workflow_data": workflow.model_dump(mode="json"),
1197
1198
  "max_credits": max_credits,
1198
1199
  }
1199
1200
 
@@ -1206,7 +1207,7 @@ def submit_protein_cofolding_workflow(
1206
1207
  def submit_docking_workflow(
1207
1208
  protein: str | Protein,
1208
1209
  pocket: list[list[float]],
1209
- initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol | None = None,
1210
+ initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol,
1210
1211
  executable: str = "vina",
1211
1212
  scoring_function: str = "vinardo",
1212
1213
  exhaustiveness: float = 8,
@@ -1236,7 +1237,7 @@ def submit_docking_workflow(
1236
1237
  """
1237
1238
 
1238
1239
  if isinstance(initial_molecule, StJamesMolecule):
1239
- initial_molecule = initial_molecule.model_dump()
1240
+ initial_molecule = initial_molecule.model_dump(mode="json")
1240
1241
  elif isinstance(initial_molecule, RdkitMol):
1241
1242
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
1242
1243
 
@@ -1251,7 +1252,7 @@ def submit_docking_workflow(
1251
1252
 
1252
1253
  workflow = stjames.DockingWorkflow(
1253
1254
  initial_molecule=initial_molecule,
1254
- target_uuid=protein,
1255
+ protein=protein,
1255
1256
  pocket=pocket,
1256
1257
  do_csearch=do_csearch,
1257
1258
  do_optimization=do_optimization,
@@ -1263,7 +1264,7 @@ def submit_docking_workflow(
1263
1264
  "name": name,
1264
1265
  "folder_uuid": folder_uuid,
1265
1266
  "workflow_type": "docking",
1266
- "workflow_data": workflow.model_dump(),
1267
+ "workflow_data": workflow.model_dump(mode="json"),
1267
1268
  "initial_molecule": initial_molecule,
1268
1269
  "max_credits": max_credits,
1269
1270
  }
@@ -1300,7 +1301,7 @@ def submit_ion_mobility_workflow(
1300
1301
  :raises requests.HTTPError: if the request to the API fails.
1301
1302
  """
1302
1303
  if isinstance(initial_molecule, StJamesMolecule):
1303
- initial_molecule = initial_molecule.model_dump()
1304
+ initial_molecule = initial_molecule.model_dump(mode="json")
1304
1305
  elif isinstance(initial_molecule, RdkitMol):
1305
1306
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
1306
1307
 
@@ -1316,7 +1317,7 @@ def submit_ion_mobility_workflow(
1316
1317
  "name": name,
1317
1318
  "folder_uuid": folder_uuid,
1318
1319
  "workflow_type": "ion_mobility",
1319
- "workflow_data": workflow.model_dump(),
1320
+ "workflow_data": workflow.model_dump(mode="json"),
1320
1321
  "initial_molecule": initial_molecule,
1321
1322
  "max_credits": max_credits,
1322
1323
  }
@@ -1350,7 +1351,7 @@ def submit_nmr_workflow(
1350
1351
  :raises requests.HTTPError: if the request to the API fails.
1351
1352
  """
1352
1353
  if isinstance(initial_molecule, StJamesMolecule):
1353
- initial_molecule = initial_molecule.model_dump()
1354
+ initial_molecule = initial_molecule.model_dump(mode="json")
1354
1355
  elif isinstance(initial_molecule, RdkitMol):
1355
1356
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
1356
1357
 
@@ -1368,7 +1369,7 @@ def submit_nmr_workflow(
1368
1369
  "name": name,
1369
1370
  "folder_uuid": folder_uuid,
1370
1371
  "workflow_type": "nmr",
1371
- "workflow_data": workflow.model_dump(serialize_as_any=True),
1372
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1372
1373
  "initial_molecule": initial_molecule,
1373
1374
  "max_credits": max_credits,
1374
1375
  }
@@ -1396,7 +1397,7 @@ def submit_strain_workflow(
1396
1397
  :raises requests.HTTPError: if the request to the API fails.
1397
1398
  """
1398
1399
  if isinstance(initial_molecule, StJamesMolecule):
1399
- initial_molecule = initial_molecule.model_dump()
1400
+ initial_molecule = initial_molecule.model_dump(mode="json")
1400
1401
  elif isinstance(initial_molecule, RdkitMol):
1401
1402
  initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
1402
1403
 
@@ -1406,7 +1407,7 @@ def submit_strain_workflow(
1406
1407
  "name": name,
1407
1408
  "folder_uuid": folder_uuid,
1408
1409
  "workflow_type": "strain",
1409
- "workflow_data": workflow.model_dump(serialize_as_any=True),
1410
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1410
1411
  "initial_molecule": initial_molecule,
1411
1412
  "max_credits": max_credits,
1412
1413
  }
@@ -1454,8 +1455,10 @@ def submit_double_ended_ts_search_workflow(
1454
1455
  "name": name,
1455
1456
  "folder_uuid": folder_uuid,
1456
1457
  "workflow_type": "double_ended_ts_search",
1457
- "workflow_data": workflow.model_dump(),
1458
- "initial_molecule": reactant if isinstance(reactant, dict) else reactant.model_dump(),
1458
+ "workflow_data": workflow.model_dump(mode="json"),
1459
+ "initial_molecule": reactant
1460
+ if isinstance(reactant, dict)
1461
+ else reactant.model_dump(mode="json"),
1459
1462
  "max_credits": max_credits,
1460
1463
  }
1461
1464
 
@@ -1469,8 +1472,20 @@ def submit_pose_analysis_md_workflow(
1469
1472
  protein: str | Protein,
1470
1473
  initial_smiles: str,
1471
1474
  num_trajectories: int = 1,
1472
- simulation_time_ns: int = 10,
1475
+ equilibration_time_ns: float = 1,
1476
+ simulation_time_ns: float = 10,
1477
+ temperature: float = 300,
1478
+ pressure_atm: float = 1.0,
1479
+ langevin_timescale_ps: float = 1.0,
1480
+ timestep_fs: float = 2,
1481
+ constrain_hydrogens: bool = True,
1482
+ nonbonded_cutoff: float = 8.0,
1483
+ ionic_strength_M: float = 0.10,
1484
+ water_buffer: float = 6.0,
1473
1485
  ligand_residue_name: str = "LIG",
1486
+ protein_restraint_cutoff: float | None = None,
1487
+ protein_restraint_constant: float = 100,
1488
+ save_solvent: bool = False,
1474
1489
  name: str = "Pose-Analysis MD Workflow",
1475
1490
  folder_uuid: str | None = None,
1476
1491
  max_credits: int | None = None,
@@ -1479,11 +1494,23 @@ def submit_pose_analysis_md_workflow(
1479
1494
  Submits a pose-analysis MD workflow to the API.
1480
1495
 
1481
1496
  :param protein: The *holo* protein on which MD will be run.
1482
- Can be input as a uuid or a Protein object.
1497
+ Can be input as a UUID or a Protein object.
1483
1498
  :param initial_smiles: The SMILES for the ligand.
1484
1499
  :param num_trajectories: The number of trajectories to run.
1485
- :param simulation_time_ns: How long to run the simulation for, in nanoseconds.
1500
+ :param equilibration_time_ns: how long to equilibrate trajectories for, in ns
1501
+ :param simulation_time_ns: how long to run trajectories for, in ns
1502
+ :param temperature: temperature, in K
1503
+ :param pressure_atm: pressure, in atm
1504
+ :param langevin_timescale_ps: timescale for the Langevin integrator, in ps⁻¹
1505
+ :param timestep_fs: timestep, in femtoseconds
1486
1506
  :param ligand_residue_name: The name of the residue corresponding to the ligand.
1507
+ :param constrain_hydrogens: whether or not to use SHAKE to freeze bonds to hydrogen
1508
+ :param nonbonded_cutoff: nonbonded cutoff for particle-mesh Ewald, in Å
1509
+ :param ionic_strength_M: ionic strength of the solution, in M (molar)
1510
+ :param water_buffer: amount of water to add around the protein, in Å
1511
+ :param protein_restraint_cutoff: cutoff past which alpha-carbons will be constrained, in Å
1512
+ :param protein_restraint_constant: force constant for backbone restraints, in kcal/mol/Ų
1513
+ :param save_solvent: whether to save solvent molecules
1487
1514
  :param name: The name of the workflow.
1488
1515
  :param folder_uuid: The UUID of the folder to place the workflow in.
1489
1516
  :param max_credits: The maximum number of credits to use for the workflow.
@@ -1495,18 +1522,30 @@ def submit_pose_analysis_md_workflow(
1495
1522
  protein = protein.uuid
1496
1523
 
1497
1524
  workflow = stjames.PoseAnalysisMolecularDynamicsWorkflow(
1498
- protein_uuid=protein,
1525
+ protein=protein,
1499
1526
  initial_smiles=initial_smiles,
1500
1527
  num_trajectories=num_trajectories,
1528
+ equilibration_time_ns=equilibration_time_ns,
1501
1529
  simulation_time_ns=simulation_time_ns,
1530
+ temperature=temperature,
1531
+ pressure_atm=pressure_atm,
1532
+ langevin_timescale_ps=langevin_timescale_ps,
1533
+ timestep_fs=timestep_fs,
1502
1534
  ligand_residue_name=ligand_residue_name,
1535
+ constrain_hydrogens=constrain_hydrogens,
1536
+ nonbonded_cutoff=nonbonded_cutoff,
1537
+ ionic_strength_M=ionic_strength_M,
1538
+ water_buffer=water_buffer,
1539
+ protein_restraint_cutoff=protein_restraint_cutoff,
1540
+ protein_restraint_constant=protein_restraint_constant,
1541
+ save_solvent=save_solvent,
1503
1542
  )
1504
1543
 
1505
1544
  data = {
1506
1545
  "name": name,
1507
1546
  "folder_uuid": folder_uuid,
1508
1547
  "workflow_type": "pose_analysis_md",
1509
- "workflow_data": workflow.model_dump(serialize_as_any=True),
1548
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1510
1549
  "initial_smiles": initial_smiles,
1511
1550
  "max_credits": max_credits,
1512
1551
  }
@@ -1552,6 +1591,7 @@ def submit_batch_docking_workflow(
1552
1591
  workflow = stjames.BatchDockingWorkflow(
1553
1592
  initial_smiles_list=smiles_list,
1554
1593
  target=protein,
1594
+ protein=protein,
1555
1595
  pocket=pocket,
1556
1596
  docking_settings=docking_settings,
1557
1597
  )
@@ -1560,7 +1600,7 @@ def submit_batch_docking_workflow(
1560
1600
  "name": name,
1561
1601
  "folder_uuid": folder_uuid,
1562
1602
  "workflow_type": "batch_docking",
1563
- "workflow_data": workflow.model_dump(serialize_as_any=True),
1603
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1564
1604
  "max_credits": max_credits,
1565
1605
  }
1566
1606
 
@@ -1598,7 +1638,7 @@ def submit_msa_workflow(
1598
1638
  "name": name,
1599
1639
  "folder_uuid": folder_uuid,
1600
1640
  "workflow_type": "msa",
1601
- "workflow_data": workflow.model_dump(serialize_as_any=True),
1641
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1602
1642
  "max_credits": max_credits,
1603
1643
  }
1604
1644
 
@@ -1631,7 +1671,7 @@ def submit_admet_workflow(
1631
1671
  "name": name,
1632
1672
  "folder_uuid": folder_uuid,
1633
1673
  "workflow_type": "admet",
1634
- "workflow_data": workflow.model_dump(),
1674
+ "workflow_data": workflow.model_dump(mode="json"),
1635
1675
  "initial_smiles": initial_smiles,
1636
1676
  "max_credits": max_credits,
1637
1677
  }
@@ -1643,7 +1683,8 @@ def submit_admet_workflow(
1643
1683
 
1644
1684
 
1645
1685
  def submit_membrane_permeability_workflow(
1646
- initial_smiles: str,
1686
+ initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol | str,
1687
+ method: Literal["gnn-mtl", "pypermm"] = "gnn-mtl",
1647
1688
  name: str = "ADMET Workflow",
1648
1689
  folder_uuid: str | None = None,
1649
1690
  max_credits: int | None = None,
@@ -1651,7 +1692,8 @@ def submit_membrane_permeability_workflow(
1651
1692
  """
1652
1693
  Submits a membrane permeability workflow to the API.
1653
1694
 
1654
- :param initial_smiles: The molecule used in the workflow.
1695
+ :param initial_molecule: The molecule used in the workflow.
1696
+ :param method: The method used to compute membrane permeability.
1655
1697
  :param name: The name of the workflow.
1656
1698
  :param folder_uuid: The UUID of the folder to store the workflow in.
1657
1699
  :param max_credits: The maximum number of credits to use for the workflow.
@@ -1659,14 +1701,182 @@ def submit_membrane_permeability_workflow(
1659
1701
  :raises requests.HTTPError: if the request to the API fails.
1660
1702
  """
1661
1703
 
1662
- workflow = stjames.MembranePermeabilityWorkflow(initial_smiles=initial_smiles)
1704
+ data: dict[str, Any] = {
1705
+ "name": name,
1706
+ "folder_uuid": folder_uuid,
1707
+ "workflow_type": "membrane_permeability",
1708
+ "max_credits": max_credits,
1709
+ }
1710
+
1711
+ match method:
1712
+ case "gnn-mtl":
1713
+ assert isinstance(initial_molecule, str)
1714
+ workflow = stjames.MembranePermeabilityWorkflow(
1715
+ initial_smiles=initial_molecule,
1716
+ membrane_permeability_method="chemprop_ohlsson2025",
1717
+ )
1718
+
1719
+ data["initial_smiles"] = initial_molecule
1720
+
1721
+ case "pypermm":
1722
+ if isinstance(initial_molecule, str):
1723
+ raise ValueError("Cannot specify molecule as SMILES for PyPermm")
1724
+ elif isinstance(initial_molecule, StJamesMolecule):
1725
+ initial_molecule = initial_molecule.model_dump(mode="json")
1726
+ elif isinstance(initial_molecule, RdkitMol):
1727
+ initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0).model_dump(
1728
+ mode="json"
1729
+ )
1730
+
1731
+ workflow = stjames.MembranePermeabilityWorkflow(
1732
+ initial_molecule=initial_molecule,
1733
+ membrane_permeability_method="pypermm",
1734
+ )
1735
+
1736
+ data["initial_molecule"] = initial_molecule
1737
+
1738
+ case _:
1739
+ raise ValueError(f"Unexpected {method=}")
1740
+
1741
+ data["workflow_data"] = workflow.model_dump(mode="json")
1742
+
1743
+ with api_client() as client:
1744
+ response = client.post("/workflow", json=data)
1745
+ response.raise_for_status()
1746
+ return Workflow(**response.json())
1747
+
1748
+
1749
+ def submit_analogue_docking_workflow(
1750
+ analogues: list[str],
1751
+ initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol,
1752
+ protein: str | Protein,
1753
+ executable: str = "vina",
1754
+ scoring_function: str = "vinardo",
1755
+ exhaustiveness: float = 8,
1756
+ name: str = "Analogue Docking Workflow",
1757
+ folder_uuid: str | None = None,
1758
+ max_credits: int | None = None,
1759
+ ) -> Workflow:
1760
+ """
1761
+ Submits an analogue docking workflow to the API.
1762
+
1763
+ :param smiles_list: The SMILES strings to dock.
1764
+ :param initial_molecule: The template to which to align molecules to.
1765
+ :param protein: The protein to dock. Can be input as a uuid or a Protein object.
1766
+ :param executable: Which docking implementation to use.
1767
+ :param scoring_function: Which docking scoring function to use.
1768
+ :param exhaustiveness: Which exhaustiveness to employ.
1769
+ :param name: The name of the workflow.
1770
+ :param folder_uuid: The UUID of the folder to place the workflow in.
1771
+ :param max_credits: The maximum number of credits to use for the workflow.
1772
+ :return: A Workflow object representing the submitted batch docking workflow.
1773
+ :raises requests.HTTPError: if the request to the API fails.
1774
+ """
1775
+
1776
+ docking_settings = {
1777
+ "executable": executable,
1778
+ "exhaustiveness": exhaustiveness,
1779
+ "scoring_function": scoring_function,
1780
+ }
1781
+
1782
+ if isinstance(initial_molecule, StJamesMolecule):
1783
+ initial_molecule = initial_molecule.model_dump(mode="json")
1784
+ elif isinstance(initial_molecule, RdkitMol):
1785
+ initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0).model_dump(
1786
+ mode="json"
1787
+ )
1788
+
1789
+ if isinstance(protein, Protein):
1790
+ protein = protein.uuid
1791
+
1792
+ workflow = stjames.AnalogueDockingWorkflow(
1793
+ analogues=analogues,
1794
+ initial_molecule=initial_molecule,
1795
+ protein=protein,
1796
+ docking_settings=docking_settings,
1797
+ )
1798
+
1799
+ data = {
1800
+ "name": name,
1801
+ "folder_uuid": folder_uuid,
1802
+ "initial_molecule": initial_molecule,
1803
+ "workflow_type": "analogue_docking",
1804
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1805
+ "max_credits": max_credits,
1806
+ }
1807
+
1808
+ with api_client() as client:
1809
+ response = client.post("/workflow", json=data)
1810
+ response.raise_for_status()
1811
+ return Workflow(**response.json())
1812
+
1813
+
1814
+ def submit_protein_md_workflow(
1815
+ protein: str | Protein,
1816
+ num_trajectories: int = 1,
1817
+ equilibration_time_ns: float = 1,
1818
+ simulation_time_ns: float = 10,
1819
+ temperature: float = 300,
1820
+ pressure_atm: float = 1.0,
1821
+ langevin_timescale_ps: float = 1.0,
1822
+ timestep_fs: float = 2,
1823
+ constrain_hydrogens: bool = True,
1824
+ nonbonded_cutoff: float = 8.0,
1825
+ ionic_strength_M: float = 0.10,
1826
+ water_buffer: float = 6.0,
1827
+ save_solvent: bool = False,
1828
+ name: str = "Protein MD Workflow",
1829
+ folder_uuid: str | None = None,
1830
+ max_credits: int | None = None,
1831
+ ) -> Workflow:
1832
+ """
1833
+ Submits a pose-analysis MD workflow to the API.
1834
+
1835
+ :param protein: The *holo* protein on which MD will be run.
1836
+ Can be input as a UUID or a Protein object.
1837
+ :param num_trajectories: The number of trajectories to run.
1838
+ :param equilibration_time_ns: how long to equilibrate trajectories for, in ns
1839
+ :param simulation_time_ns: how long to run trajectories for, in ns
1840
+ :param temperature: temperature, in K
1841
+ :param pressure_atm: pressure, in atm
1842
+ :param langevin_timescale_ps: timescale for the Langevin integrator, in ps⁻¹
1843
+ :param timestep_fs: timestep, in femtoseconds
1844
+ :param constrain_hydrogens: whether or not to use SHAKE to freeze bonds to hydrogen
1845
+ :param nonbonded_cutoff: nonbonded cutoff for particle-mesh Ewald, in Å
1846
+ :param ionic_strength_M: ionic strength of the solution, in M (molar)
1847
+ :param water_buffer: amount of water to add around the protein, in Å
1848
+ :param save_solvent: whether solvent should be saed
1849
+ :param name: The name of the workflow.
1850
+ :param folder_uuid: The UUID of the folder to place the workflow in.
1851
+ :param max_credits: The maximum number of credits to use for the workflow.
1852
+ :return: A Workflow object representing the submitted workflow.
1853
+ :raises requests.HTTPError: if the request to the API fails.
1854
+ """
1855
+
1856
+ if isinstance(protein, Protein):
1857
+ protein = protein.uuid
1858
+
1859
+ workflow = stjames.ProteinMolecularDynamicsWorkflow(
1860
+ protein=protein,
1861
+ num_trajectories=num_trajectories,
1862
+ equilibration_time_ns=equilibration_time_ns,
1863
+ simulation_time_ns=simulation_time_ns,
1864
+ temperature=temperature,
1865
+ pressure_atm=pressure_atm,
1866
+ langevin_timescale_ps=langevin_timescale_ps,
1867
+ timestep_fs=timestep_fs,
1868
+ constrain_hydrogens=constrain_hydrogens,
1869
+ nonbonded_cutoff=nonbonded_cutoff,
1870
+ ionic_strength_M=ionic_strength_M,
1871
+ water_buffer=water_buffer,
1872
+ save_solvent=save_solvent,
1873
+ )
1663
1874
 
1664
1875
  data = {
1665
1876
  "name": name,
1666
1877
  "folder_uuid": folder_uuid,
1667
- "workflow_type": "membrane_permeability",
1668
- "workflow_data": workflow.model_dump(),
1669
- "initial_smiles": initial_smiles,
1878
+ "workflow_type": "protein_md",
1879
+ "workflow_data": workflow.model_dump(serialize_as_any=True, mode="json"),
1670
1880
  "max_credits": max_credits,
1671
1881
  }
1672
1882
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rowan-python
3
- Version: 2.1.12
3
+ Version: 2.1.14
4
4
  Summary: Rowan Python Library
5
5
  Project-URL: Homepage, https://github.com/rowansci/rowan-client
6
6
  Project-URL: Bug Tracker, https://github.com/rowansci/rowan-client/issues
@@ -11,7 +11,7 @@ Requires-Dist: httpx
11
11
  Requires-Dist: nest-asyncio
12
12
  Requires-Dist: rdkit
13
13
  Requires-Dist: setuptools
14
- Requires-Dist: stjames>=0.0.137
14
+ Requires-Dist: stjames>=0.0.144
15
15
  Description-Content-Type: text/markdown
16
16
 
17
17
  # Rowan Python Library
@@ -6,10 +6,10 @@ rowan/protein.py,sha256=mFSVCr-08bSikXBUtJtSWzjKcVAuBmTeRckn7JUHYSE,8810
6
6
  rowan/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  rowan/user.py,sha256=Dl--NPUPATKCs2VmILsW8HnLiunG0Lxr0n6mKuHm21U,3891
8
8
  rowan/utils.py,sha256=64II-cPOe_SFJK302Bm8hP62d_3_CgnTVYCbn3zKT7U,3334
9
- rowan/workflow.py,sha256=Y9H1qXCjTd-E-LehtlbpEp5l7a0__TKE7nYqY5XwUI8,63669
9
+ rowan/workflow.py,sha256=QQWHTZ_O3PF2WbegYLPIKiszOEYj1frPKbI8U-B1muc,72419
10
10
  rowan/rowan_rdkit/__init__.py,sha256=EATX2VRzywzKxqkpCUMTf7RNQLkWsfi5VcCNDW6EIiw,503
11
11
  rowan/rowan_rdkit/chem_utils.py,sha256=sKCzul2e0ldVYTBImhTwso7ddNgPKmvS-OmvCEjVJH0,34788
12
- rowan_python-2.1.12.dist-info/METADATA,sha256=IdwxdzM7GqpuqU9lF9_69NKeGldpBq-FOW00C4tZaqg,1601
13
- rowan_python-2.1.12.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
- rowan_python-2.1.12.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
15
- rowan_python-2.1.12.dist-info/RECORD,,
12
+ rowan_python-2.1.14.dist-info/METADATA,sha256=GdXzsTQIY2SSuTUgVnerp8Cib41LCL2koTc1VuPvP5w,1601
13
+ rowan_python-2.1.14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ rowan_python-2.1.14.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
15
+ rowan_python-2.1.14.dist-info/RECORD,,