rowan-python 2.1.6__py3-none-any.whl → 2.1.8__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.
@@ -844,7 +844,7 @@ async def _single_conformers(
844
844
  raise NoConformersError("This molecule has no conformers")
845
845
 
846
846
  sorted_data = sorted(
847
- zip(data["energies"], data["conformer_uuids"]),
847
+ zip(data["energies"], data["conformer_uuids"], strict=True),
848
848
  key=lambda x: x[0],
849
849
  )
850
850
 
rowan/workflow.py CHANGED
@@ -1,14 +1,20 @@
1
+ import logging
1
2
  import time
2
3
  from datetime import datetime
4
+ from pathlib import Path
3
5
  from typing import Any, Literal, Self, TypeAlias
4
6
 
5
7
  import stjames
6
8
  from pydantic import BaseModel, Field
7
9
  from rdkit import Chem
10
+ from stjames.optimization.freezing_string_method import FSMSettings
8
11
 
9
12
  from .protein import Protein
10
13
  from .utils import api_client
11
14
 
15
+ logger = logging.getLogger(__name__)
16
+ logger.setLevel(logging.INFO)
17
+
12
18
  RdkitMol: TypeAlias = Chem.rdchem.Mol | Chem.rdchem.RWMol
13
19
  StJamesMolecule: TypeAlias = stjames.Molecule
14
20
 
@@ -215,6 +221,25 @@ class Workflow(BaseModel):
215
221
  response = client.delete(f"/workflow/{self.uuid}/delete_workflow_data")
216
222
  response.raise_for_status()
217
223
 
224
+ def download_msa_files(self, msa_format: stjames.MSAFormat, path: Path | None = None) -> None:
225
+ if self.workflow_type != "msa":
226
+ raise ValueError("This workflow is not an MSA workflow.")
227
+
228
+ if path is None:
229
+ path = Path.cwd()
230
+
231
+ if not path.exists():
232
+ path.mkdir(parents=True, exist_ok=True)
233
+
234
+ with api_client() as client:
235
+ response = client.get(
236
+ f"/workflow/{self.uuid}/get_msa_files", params={"msa_format": msa_format.value}
237
+ )
238
+ response.raise_for_status()
239
+
240
+ with open(path / f"{self.name}-msa.tar.gz", "wb") as f:
241
+ f.write(response.content)
242
+
218
243
 
219
244
  def submit_workflow(
220
245
  workflow_type: stjames.WORKFLOW_NAME,
@@ -271,6 +296,75 @@ def submit_workflow(
271
296
  return Workflow(**response.json())
272
297
 
273
298
 
299
+ def batch_submit_workflow(
300
+ workflow_type: stjames.WORKFLOW_NAME,
301
+ workflow_data: dict[str, Any] | None = None,
302
+ initial_molecules: list[dict[str, Any] | StJamesMolecule | RdkitMol] | None = None,
303
+ initial_smileses: list[str] | None = None,
304
+ names: list[str] | None = None,
305
+ folder_uuid: str | None = None,
306
+ max_credits: int | None = None,
307
+ ) -> list[Workflow]:
308
+ """
309
+ Submits a batch of workflows to the API. Each workflow will be submitted with the
310
+ same workflow type, workflow data, and folder UUID, but with different initial molecules and/or
311
+ SMILES strings.
312
+
313
+ :param workflow_type: The type of workflow to submit.
314
+ :param workflow_data: A dictionary containing the data required to run the workflow.
315
+ :param initial_molecules: A list of molecule objects to use as the initial molecules in the
316
+ workflows.
317
+ At least one of a molecule or SMILES must be provided.
318
+ :param initial_smileses: A list of SMILES strings to use as the initial molecules in the
319
+ workflows.
320
+ At least one of a molecule or SMILES must be provided.
321
+ :param names: A list of names to give to the workflows.
322
+ :param folder_uuid: The UUID of the folder to store the workflow in.
323
+ :param max_credits: The maximum number of credits to use for the workflow. This applies per
324
+ workflow, not for the batch.
325
+ :return: A list of Workflow objects representing the submitted workflows.
326
+ :raises ValueError: If neither `initial_smiles` nor a valid `initial_molecule` is provided.
327
+ :raises HTTPError: If the API request fails.
328
+ """
329
+ if workflow_type not in stjames.WORKFLOW_MAPPING:
330
+ raise ValueError(
331
+ "Invalid workflow type. Must be one of:\n " + "\n ".join(stjames.WORKFLOW_MAPPING)
332
+ )
333
+
334
+ if initial_molecules and initial_smileses:
335
+ raise ValueError(
336
+ "You must provide either `initial_molecules` or `initial_smileses`, but not both."
337
+ )
338
+
339
+ if names:
340
+ if initial_molecules and len(names) != len(initial_molecules):
341
+ logger.warning(
342
+ "The number of names is not the same as the number of initial "
343
+ "molecules. Generic names of the form 'Batch Workflow {i}' "
344
+ "will be used."
345
+ )
346
+ if initial_smileses and len(names) != len(initial_smileses):
347
+ logger.warning(
348
+ "The number of names is not the same as the number of initial SMILES."
349
+ "Generic names of the form 'Batch Workflow {i}' will be used."
350
+ )
351
+
352
+ data = {
353
+ "names": names,
354
+ "folder_uuid": folder_uuid,
355
+ "workflow_type": workflow_type,
356
+ "workflow_data": workflow_data,
357
+ "max_credits": max_credits,
358
+ "initial_molecules": initial_molecules,
359
+ "initial_smileses": initial_smileses,
360
+ }
361
+
362
+ with api_client() as client:
363
+ response = client.post("/workflow/batch_submit", json=data)
364
+ response.raise_for_status()
365
+ return [Workflow(**workflow_data) for workflow_data in response.json()]
366
+
367
+
274
368
  def retrieve_workflow(uuid: str) -> Workflow:
275
369
  """
276
370
  Retrieves a workflow from the API.
@@ -285,16 +379,21 @@ def retrieve_workflow(uuid: str) -> Workflow:
285
379
  return Workflow(**response.json())
286
380
 
287
381
 
288
- def retrieve_calculation_molecules(uuid: str) -> list[dict[str, Any]]:
382
+ def retrieve_calculation_molecules(
383
+ uuid: str, return_frequencies: bool = False
384
+ ) -> list[dict[str, Any]]:
289
385
  """
290
386
  Retrieves a list of molecules from a calculation.
291
387
 
292
388
  :param uuid: The UUID of the calculation to retrieve molecules from.
389
+ :param return_frequencies: Whether to return the frequencies of the molecules.
293
390
  :return: A list of dictionaries representing the molecules in the calculation.
294
391
  :raises HTTPError: If the API request fails.
295
392
  """
296
393
  with api_client() as client:
297
- response = client.get(f"/calculation/{uuid}/molecules")
394
+ response = client.get(
395
+ f"/calculation/{uuid}/molecules", params={"return_frequencies": return_frequencies}
396
+ )
298
397
  response.raise_for_status()
299
398
  return response.json()
300
399
 
@@ -352,9 +451,10 @@ def list_workflows(
352
451
  def submit_basic_calculation_workflow(
353
452
  initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol,
354
453
  method: stjames.Method | str = "uma_m_omol",
454
+ basis_set: stjames.BasisSet | str | None = None,
355
455
  tasks: list[str] | None = None,
356
456
  mode: str = "auto",
357
- engine: str = "omol25",
457
+ engine: str | None = None,
358
458
  name: str = "Basic Calculation Workflow",
359
459
  folder_uuid: str | None = None,
360
460
  max_credits: int | None = None,
@@ -364,7 +464,7 @@ def submit_basic_calculation_workflow(
364
464
 
365
465
  :param initial_molecule: The molecule to perform the calculation on.
366
466
  :param method: The method to use for the calculation.
367
- See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
467
+ :param basis_set: The basis_set to use (if any).
368
468
  for options.
369
469
  :param tasks: A list of tasks to perform for the calculation.
370
470
  :param mode: The mode to run the calculation in. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
@@ -391,10 +491,11 @@ def submit_basic_calculation_workflow(
391
491
  initial_molecule=initial_molecule,
392
492
  settings=stjames.Settings(
393
493
  method=method,
494
+ basis_set=basis_set,
394
495
  tasks=tasks,
395
496
  mode=mode,
396
497
  ),
397
- engine=engine,
498
+ engine=engine or method.default_engine(),
398
499
  )
399
500
 
400
501
  data = {
@@ -543,8 +644,10 @@ def submit_solubility_workflow(
543
644
 
544
645
 
545
646
  def submit_pka_workflow(
546
- initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol,
647
+ initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol | str,
547
648
  pka_range: tuple[int, int] = (2, 12),
649
+ method: Literal["aimnet2_wagen2024", "chemprop_nevolianis2025"] = "aimnet2_wagen2024",
650
+ solvent: str = "water",
548
651
  deprotonate_elements: list[int] | None = None,
549
652
  protonate_elements: list[int] | None = None,
550
653
  mode: str = "careful",
@@ -556,7 +659,10 @@ def submit_pka_workflow(
556
659
  Submits a pKa workflow to the API.
557
660
 
558
661
  :param initial_molecule: The molecule to calculate the pKa of.
662
+ Valid input types include `stjames.Molecule`, RDKit molecule, and SMILES.
559
663
  :param pka_range: The range of pKa values to calculate.
664
+ :param method: The algorithm used to compute pKa values.
665
+ :param solvent: The solvent in which pKa values will be computed.
560
666
  :param deprotonate_elements: The elements to deprotonate. Given by atomic number.
561
667
  :param protonate_elements: The elements to protonate. Given by atomic number.
562
668
  :param mode: The mode to run the calculation in. See
@@ -568,20 +674,30 @@ def submit_pka_workflow(
568
674
  :return: A Workflow object representing the submitted workflow.
569
675
  :raises requests.HTTPError: if the request to the API fails.
570
676
  """
571
- if isinstance(initial_molecule, StJamesMolecule):
572
- initial_molecule = initial_molecule.model_dump()
677
+ initial_smiles: str = ""
678
+ initial_stjames_mol: StJamesMolecule | None = None
679
+
680
+ if isinstance(initial_molecule, dict):
681
+ initial_stjames_mol = StJamesMolecule.model_validate(initial_molecule)
682
+ elif isinstance(initial_molecule, StJamesMolecule):
683
+ initial_stjames_mol = initial_molecule
573
684
  elif isinstance(initial_molecule, RdkitMol):
574
- initial_molecule = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
685
+ initial_stjames_mol = StJamesMolecule.from_rdkit(initial_molecule, cid=0)
686
+ elif isinstance(initial_molecule, str):
687
+ initial_smiles = initial_molecule
575
688
 
576
689
  protonate_elements = protonate_elements or [7]
577
690
  deprotonate_elements = deprotonate_elements or [7, 8, 16]
578
691
 
579
692
  workflow = stjames.pKaWorkflow(
580
- initial_molecule=initial_molecule,
693
+ initial_molecule=initial_stjames_mol,
694
+ initial_smiles=initial_smiles,
581
695
  pka_range=pka_range,
582
696
  deprotonate_elements=deprotonate_elements,
583
697
  protonate_elements=protonate_elements,
584
698
  mode=mode,
699
+ solvent=solvent,
700
+ microscopic_pka_method=method,
585
701
  )
586
702
 
587
703
  data = {
@@ -589,7 +705,8 @@ def submit_pka_workflow(
589
705
  "folder_uuid": folder_uuid,
590
706
  "workflow_type": "pka",
591
707
  "workflow_data": workflow.model_dump(),
592
- "initial_molecule": initial_molecule,
708
+ "initial_molecule": initial_stjames_mol.model_dump() if initial_stjames_mol else None,
709
+ "initial_smiles": initial_smiles,
593
710
  "max_credits": max_credits,
594
711
  }
595
712
 
@@ -792,7 +909,7 @@ def submit_descriptors_workflow(
792
909
  def submit_scan_workflow(
793
910
  initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol,
794
911
  scan_settings: stjames.ScanSettings | dict[str, Any] | None = None,
795
- calculation_engine: str = "omol25",
912
+ calculation_engine: str | None = None,
796
913
  calculation_method: stjames.Method | str = "uma_m_omol",
797
914
  wavefront_propagation: bool = True,
798
915
  name: str = "Scan Workflow",
@@ -835,7 +952,7 @@ def submit_scan_workflow(
835
952
  initial_molecule=initial_molecule,
836
953
  scan_settings=scan_settings,
837
954
  calc_settings=calc_settings,
838
- calc_engine=calculation_engine,
955
+ calc_engine=calculation_engine or calculation_method.default_engine(),
839
956
  wavefront_propagation=wavefront_propagation,
840
957
  )
841
958
 
@@ -911,7 +1028,6 @@ def submit_macropka_workflow(
911
1028
  def submit_irc_workflow(
912
1029
  initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol | None = None,
913
1030
  method: stjames.Method | str = "uma_m_omol",
914
- engine: str = "omol25",
915
1031
  preopt: bool = True,
916
1032
  step_size: float = 0.05,
917
1033
  max_irc_steps: int = 30,
@@ -926,7 +1042,6 @@ def submit_irc_workflow(
926
1042
  :param method: The computational method to use for the IRC calculation.
927
1043
  See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
928
1044
  for options.
929
- :param engine: The computational engine to use for the calculation. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
930
1045
  :param preopt: Whether to perform a pre-optimization of the molecule.
931
1046
  :param step_size: The step size to use for the IRC calculation.
932
1047
  :param max_irc_steps: The maximum number of IRC steps to perform.
@@ -953,12 +1068,12 @@ def submit_irc_workflow(
953
1068
  corrections=[],
954
1069
  mode="auto",
955
1070
  ),
956
- engine=engine,
957
1071
  preopt=preopt,
958
1072
  step_size=step_size,
959
1073
  max_irc_steps=max_irc_steps,
960
1074
  mode="manual",
961
1075
  )
1076
+
962
1077
  data = {
963
1078
  "name": name,
964
1079
  "folder_uuid": folder_uuid,
@@ -1034,6 +1149,9 @@ def submit_docking_workflow(
1034
1149
  protein: str | Protein,
1035
1150
  pocket: list[list[float]],
1036
1151
  initial_molecule: dict[str, Any] | StJamesMolecule | RdkitMol | None = None,
1152
+ executable: str = "vina",
1153
+ scoring_function: str = "vinardo",
1154
+ exhaustiveness: float = 8,
1037
1155
  do_csearch: bool = False,
1038
1156
  do_optimization: bool = False,
1039
1157
  do_pose_refinement: bool = False,
@@ -1044,15 +1162,18 @@ def submit_docking_workflow(
1044
1162
  """
1045
1163
  Submits a Docking workflow to the API.
1046
1164
 
1047
- :param protein: The protein to dock. Can be fed as a uuid or a Protein object.
1165
+ :param protein: The protein to dock. Can be input as a uuid or a Protein object.
1048
1166
  :param initial_molecule: The initial molecule to be docked
1167
+ :param executable: Which docking implementation to use.
1168
+ :param scoring_function: Which docking scoring function to use.
1169
+ :param exhaustiveness: Which exhaustiveness to employ.
1049
1170
  :param do_csearch: Whether to perform a conformational search on the ligand.
1050
1171
  :param do_optimization: Whether to perform an optimization on the ligand.
1051
1172
  :param do_pose_refinement: Whether or not to optimize output poses.
1052
1173
  :param name: The name of the workflow.
1053
1174
  :param folder_uuid: The UUID of the folder to place the workflow in.
1054
1175
  :param max_credits: The maximum number of credits to use for the workflow.
1055
- :return: A Workflow object representing the submitted IRC workflow.
1176
+ :return: A Workflow object representing the submitted docking workflow.
1056
1177
  :raises requests.HTTPError: if the request to the API fails.
1057
1178
  """
1058
1179
 
@@ -1064,6 +1185,12 @@ def submit_docking_workflow(
1064
1185
  if isinstance(protein, Protein):
1065
1186
  protein = protein.uuid
1066
1187
 
1188
+ docking_settings = {
1189
+ "executable": executable,
1190
+ "exhaustiveness": exhaustiveness,
1191
+ "scoring_function": scoring_function,
1192
+ }
1193
+
1067
1194
  workflow = stjames.DockingWorkflow(
1068
1195
  initial_molecule=initial_molecule,
1069
1196
  target_uuid=protein,
@@ -1071,6 +1198,7 @@ def submit_docking_workflow(
1071
1198
  do_csearch=do_csearch,
1072
1199
  do_optimization=do_optimization,
1073
1200
  do_pose_refinement=do_pose_refinement,
1201
+ docking_settings=docking_settings,
1074
1202
  )
1075
1203
 
1076
1204
  data = {
@@ -1229,3 +1357,185 @@ def submit_strain_workflow(
1229
1357
  response = client.post("/workflow", json=data)
1230
1358
  response.raise_for_status()
1231
1359
  return Workflow(**response.json())
1360
+
1361
+
1362
+ def submit_double_ended_ts_search_workflow(
1363
+ reactant: dict[str, Any] | StJamesMolecule,
1364
+ product: dict[str, Any] | StJamesMolecule,
1365
+ calculation_settings: stjames.Settings | dict[str, Any] | None = None,
1366
+ search_settings: FSMSettings | dict[str, Any] | None = None,
1367
+ optimize_inputs: bool = False,
1368
+ optimize_ts: bool = True,
1369
+ name: str = "Double-Ended TS Search Workflow",
1370
+ folder_uuid: str | None = None,
1371
+ max_credits: int | None = None,
1372
+ ) -> Workflow:
1373
+ """
1374
+ Submits a double-ended transition state search workflow to the API.
1375
+
1376
+ :param reactant: reactant Molecule.
1377
+ :param product: product Molecule.
1378
+ :param calculation_settings: Settings to use for calculations.
1379
+ :param search_settings: settings to use for the transition state search.
1380
+ :param optimize_inputs: Whether to optimize the reactant and product before the search.
1381
+ :param optimize_ts: Whether to optimize the found transition state.
1382
+ :param name: name of the workflow.
1383
+ :param folder_uuid: The UUID of the folder to place the workflow in.
1384
+ :param max_credits: The maximum number of credits to use for the workflow.
1385
+ :return: Workflow object representing the submitted workflow.
1386
+ """
1387
+ workflow = stjames.DoubleEndedTSSearchWorkflow(
1388
+ reactant=reactant,
1389
+ product=product,
1390
+ calculation_settings=calculation_settings,
1391
+ search_settings=search_settings,
1392
+ optimize_inputs=optimize_inputs,
1393
+ optimize_ts=optimize_ts,
1394
+ )
1395
+ data = {
1396
+ "name": name,
1397
+ "folder_uuid": folder_uuid,
1398
+ "workflow_type": "double_ended_ts_search",
1399
+ "workflow_data": workflow.model_dump(),
1400
+ "initial_molecule": reactant if isinstance(reactant, dict) else reactant.model_dump(),
1401
+ "max_credits": max_credits,
1402
+ }
1403
+
1404
+ with api_client() as client:
1405
+ response = client.post("/workflow", json=data)
1406
+ response.raise_for_status()
1407
+ return Workflow(**response.json())
1408
+
1409
+
1410
+ def submit_pose_analysis_md_workflow(
1411
+ protein: str | Protein,
1412
+ initial_smiles: str,
1413
+ num_trajectories: int = 1,
1414
+ simulation_time_ns: int = 10,
1415
+ ligand_residue_name: str = "LIG",
1416
+ name: str = "Pose-Analysis MD Workflow",
1417
+ folder_uuid: str | None = None,
1418
+ max_credits: int | None = None,
1419
+ ) -> Workflow:
1420
+ """
1421
+ Submits a pose-analysis MD workflow to the API.
1422
+
1423
+ :param protein: The *holo* protein on which MD will be run.
1424
+ Can be input as a uuid or a Protein object.
1425
+ :param initial_smiles: The SMILES for the ligand.
1426
+ :param num_trajectories: The number of trajectories to run.
1427
+ :param simulation_time_ns: How long to run the simulation for, in nanoseconds.
1428
+ :param ligand_residue_name: The name of the residue corresponding to the ligand.
1429
+ :param name: The name of the workflow.
1430
+ :param folder_uuid: The UUID of the folder to place the workflow in.
1431
+ :param max_credits: The maximum number of credits to use for the workflow.
1432
+ :return: A Workflow object representing the submitted workflow.
1433
+ :raises requests.HTTPError: if the request to the API fails.
1434
+ """
1435
+
1436
+ if isinstance(protein, Protein):
1437
+ protein = protein.uuid
1438
+
1439
+ workflow = stjames.PoseAnalysisMolecularDynamicsWorkflow(
1440
+ protein_uuid=protein,
1441
+ initial_smiles=initial_smiles,
1442
+ num_trajectories=num_trajectories,
1443
+ simulation_time_ns=simulation_time_ns,
1444
+ ligand_residue_name=ligand_residue_name,
1445
+ )
1446
+
1447
+ data = {
1448
+ "name": name,
1449
+ "folder_uuid": folder_uuid,
1450
+ "workflow_type": "pose_analysis_md",
1451
+ "workflow_data": workflow.model_dump(serialize_as_any=True),
1452
+ "initial_smiles": initial_smiles,
1453
+ "max_credits": max_credits,
1454
+ }
1455
+
1456
+ with api_client() as client:
1457
+ response = client.post("/workflow", json=data)
1458
+ response.raise_for_status()
1459
+ return Workflow(**response.json())
1460
+
1461
+
1462
+ def submit_batch_docking_workflow(
1463
+ smiles_list: list[str],
1464
+ protein: str | Protein,
1465
+ pocket: list[list[float]],
1466
+ executable: str = "qvina2",
1467
+ scoring_function: str = "vina",
1468
+ exhaustiveness: float = 8,
1469
+ name: str = "Batch Docking Workflow",
1470
+ folder_uuid: str | None = None,
1471
+ max_credits: int | None = None,
1472
+ ) -> Workflow:
1473
+ """
1474
+ Submits a batch docking workflow to the API.
1475
+
1476
+ :param smiles_list: The SMILES strings to dock.
1477
+ :param protein: The protein to dock. Can be input as a uuid or a Protein object.
1478
+ :param executable: Which docking implementation to use.
1479
+ :param scoring_function: Which docking scoring function to use.
1480
+ :param exhaustiveness: Which exhaustiveness to employ.
1481
+ :param name: The name of the workflow.
1482
+ :param folder_uuid: The UUID of the folder to place the workflow in.
1483
+ :param max_credits: The maximum number of credits to use for the workflow.
1484
+ :return: A Workflow object representing the submitted batch docking workflow.
1485
+ :raises requests.HTTPError: if the request to the API fails.
1486
+ """
1487
+
1488
+ docking_settings = {
1489
+ "executable": executable,
1490
+ "exhaustiveness": exhaustiveness,
1491
+ "scoring_function": scoring_function,
1492
+ }
1493
+
1494
+ workflow = stjames.BatchDockingWorkflow(
1495
+ initial_smiles_list=smiles_list,
1496
+ target=protein,
1497
+ pocket=pocket,
1498
+ docking_settings=docking_settings,
1499
+ )
1500
+
1501
+ data = {
1502
+ "name": name,
1503
+ "folder_uuid": folder_uuid,
1504
+ "workflow_type": "batch_docking",
1505
+ "workflow_data": workflow.model_dump(serialize_as_any=True),
1506
+ "max_credits": max_credits,
1507
+ }
1508
+
1509
+ with api_client() as client:
1510
+ response = client.post("/workflow", json=data)
1511
+ response.raise_for_status()
1512
+ return Workflow(**response.json())
1513
+
1514
+
1515
+ def submit_msa_workflow(
1516
+ initial_protein_sequences: list[stjames.ProteinSequence | str],
1517
+ output_formats: list[stjames.MSAFormat],
1518
+ name: str = "MSA Workflow",
1519
+ folder_uuid: str | None = None,
1520
+ max_credits: int | None = None,
1521
+ ) -> Workflow:
1522
+ """
1523
+ Submits an MSA workflow to the API.
1524
+ """
1525
+ workflow = stjames.MSAWorkflow(
1526
+ initial_protein_sequences=initial_protein_sequences,
1527
+ output_formats=output_formats,
1528
+ )
1529
+
1530
+ data = {
1531
+ "name": name,
1532
+ "folder_uuid": folder_uuid,
1533
+ "workflow_type": "msa",
1534
+ "workflow_data": workflow.model_dump(serialize_as_any=True),
1535
+ "max_credits": max_credits,
1536
+ }
1537
+
1538
+ with api_client() as client:
1539
+ response = client.post("/workflow", json=data)
1540
+ response.raise_for_status()
1541
+ return Workflow(**response.json())
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rowan-python
3
- Version: 2.1.6
3
+ Version: 2.1.8
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
7
7
  Author-email: Corin Wagen <corin@rowansci.com>
8
8
  License-File: LICENSE
9
- Requires-Python: >=3.9
9
+ Requires-Python: >=3.11
10
10
  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.109
14
+ Requires-Dist: stjames>=0.0.125
15
15
  Description-Content-Type: text/markdown
16
16
 
17
17
  # Rowan Python Library
@@ -6,10 +6,10 @@ rowan/protein.py,sha256=bMemvLZua_pnTrYOxHFZ4jFlRH9KgpYvtjj5M2__28k,8026
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=EGcqPv2K-CCt8t_FSVAGTaI7QCM4BJdY--kN4PHvhOo,46749
9
+ rowan/workflow.py,sha256=tPvFXYC9O8Qr_9HVGDzYTgW-3MrFcDLGqbGDzlOq5tI,58562
10
10
  rowan/rowan_rdkit/__init__.py,sha256=EATX2VRzywzKxqkpCUMTf7RNQLkWsfi5VcCNDW6EIiw,503
11
- rowan/rowan_rdkit/chem_utils.py,sha256=i7-EmAcmvHYtc9NiZblLY_k2DoQKofAZo5KT2qtkUCI,34775
12
- rowan_python-2.1.6.dist-info/METADATA,sha256=rNw5EUh2Dz3xfBKUtFHtIPykxSVegqydghdhhq-q3XI,1599
13
- rowan_python-2.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- rowan_python-2.1.6.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
15
- rowan_python-2.1.6.dist-info/RECORD,,
11
+ rowan/rowan_rdkit/chem_utils.py,sha256=sKCzul2e0ldVYTBImhTwso7ddNgPKmvS-OmvCEjVJH0,34788
12
+ rowan_python-2.1.8.dist-info/METADATA,sha256=H4imf_mPDAVYyT8l7AYJsC947qE2yfu0labnvuhDdX4,1600
13
+ rowan_python-2.1.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ rowan_python-2.1.8.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
15
+ rowan_python-2.1.8.dist-info/RECORD,,