by Corin Wagen · Dec 10, 2025

Desembarco de los tercios en Terceira (Azores) en 1583, Niccolò Granello
Many tasks in computational chemistry require running a lot of calculations. While submitting calculations one-at-a-time can be done through Rowan's web interface, submitting and analyzing thousands of workflows by hand quickly becomes tedious. Rowan's free Python API is designed to make it easy to submit, monitor, and analyze large numbers of workflows.
In this blog post, I'll demonstrate how to use Rowan's API to compute thousands of solubility calculations in just a few hours.
Running lots of calculations requires lots of molecules. For this tutorial, I chose the "decoy" subset of the MT1 DUDEZ set as a representative set of a few thousand drug-like small molecules. Here's the first 10 lines of decoys.name.smi:
CCOc1ccc(CNc2ccc(OC)cc2)cc1 ZINC000000516872
O=C1CCc2c(OCc3cc(=O)n4ccccc4n3)cccc21 ZINC000010198221
COc1ccc(CNc2cccnc2)cc1Br ZINC000037187080
Cc1nc(-c2cccc(NCc3ccccc3Cl)c2)n[nH]1 ZINC000037781618
COC(=O)c1cc(CSc2cnccn2)c(C)o1 ZINC000074790767
CN(Cc1cccc(OCC(F)(F)F)c1)c1cnn(C)c1 ZINC000081089862
COC(=O)c1cccc(N(C)Cc2ccsc2)n1 ZINC000092827273
COC(=O)c1cccc(N(C)CC2CCCC2)n1 ZINC000094151518
c1cc(NCc2cccc3[nH]ccc23)cc(-c2nc[nH]n2)c1 ZINC000095431145
O=C(OCc1cccnc1)[C@@H]1C[C@@H]1c1ccc(F)cc1 ZINC000096999692
To submit these calculations, we must first parse the above DUDEZ file and extract the SMILES strings. We can then use Rowan's batch_submit_workflow function to submit all the jobs:
import rowan
rowan.api_key = "rowan-sk-your-secret-key-here"
# load data
smiles_list = []
name_list = []
with open("decoys.name.smi") as f:
for line in f:
smiles, name = line.strip().split(" ")
smiles_list.append(smiles)
name_list.append(name)
workflows = rowan.batch_submit_workflow(
"solubility",
workflow_data={},
initial_smileses=smiles_list,
names=name_list,
folder_uuid="09faaa68-f91b-44e9-a711-533042fbedc4",
)
Here, we've provided the UUID of the folder where we want these workflows to go. This helps us stay organized and will make it easier to gather the results later. In this case I created the folder manually through the web interface, but folders can also be created through Rowan's create_folder API function.
If we want to submit a different workflow, we could do so by changing "solubility" to the name of a different workflow. Additional customization can be done through the workflow_data argument; it's always recommended to try a test calculation before submitting thousands of calculations to ensure that the settings are parsed and applied as expected.
Running the above script will submit 2150 solubility workflows to Rowan, but the workflows won't all run right away! The status of the submitted workflows can be monitored through a simple script like this:
import rowan
rowan.api_key = "rowan-sk-your-secret-key-here"
c = {k: 0 for k in (0, 1, 2, 3, 4, 5, 6)}
page_num = 0
while ws := rowan.list_workflows(
parent_uuid="09faaa68-f91b-44e9-a711-533042fbedc4",
size=100,
page=page_num,
):
for w in ws:
c[w.status] += 1
page_num += 1
print(c)
This script retrieves workflows in batches of 100 and uses a dictionary to keep track of how many rows have each status code. Here's what each status code means:
| Status | Name | Description |
|---|---|---|
| 0 | QUEUED | Job created and queued (user is below max_concurrency). |
| 1 | RUNNING | Job is currently running. |
| 2 | COMPLETED_OK | Job finished successfully. |
| 3 | FAILED | Job finished with an error. |
| 4 | STOPPED | Job was stopped externally (e.g., timeout/cancellation). |
| 5 | AWAITING_QUEUE | User exceeded allowed max_concurrency; job is waiting for a slot. |
| 6 | DRAFT | Job not yet submitted. |
More workflows will run simultaneously (spending credits faster) if your account's maximum concurrency is increased. You can increase your maximum concurrency on your account page (up to the limit of your subscription tier).
When I ran these scripts, it took me just over two hours (8157 s) to run all 2150 workflows: all jobs completed successfully, and the workflows took 49 seconds each on average.
Once all workflows have completed, it's easy to use Rowan's API to download the results. As before, we use the list_workflows function to get all the workflows from a given folder; here, I've wrapped this into a generator so that I can use tqdm to monitor how long the download is taking.
import rowan
from tqdm import tqdm
rowan.api_key = "rowan-sk-your-secret-key-here"
def iter_workflows(parent_uuid: str, size: int = 100):
page_num = 0
while ws := rowan.list_workflows(
parent_uuid=parent_uuid,
size=size,
page=page_num,
):
yield from ws
page_num += 1
with open("mt1_solubility.csv", "w") as f:
for w in tqdm(iter_workflows("09faaa68-f91b-44e9-a711-533042fbedc4")):
try:
w.fetch_latest(in_place=True)
smiles = w.data["initial_smiles"]
solubility = w.data["solubilities"]["O"]["solubilities"][0]
f.write(f"{smiles}, {solubility:.3f}\n")
except Exception as e:
print(f"Skipping {w.uuid}: {e}")
The above script simply writes all the solubility values to a .csv file alongside the input SMILES strings. For more complex workflows, parsing the data might be more involved; we've put together example scripts for various workflow types on GitHub.
These scripts provide a minimal demonstration of how Rowan's API can be used to run thousands of jobs per day without requiring any special handling. Sophisticated software engineers can doubtless write more complex submission and analysis code; feel free to look through our API documentation and reach out! We're always happy to talk to customers looking to run computational chemistry workloads at scale.
