azulene-opal 0.4.3
A CLI and Python library to interact with Azulene Opal
Requires Python: >=3.8

<a name="quickstart"></a>
## Opal Quick Start Guide: 

- [Opal Quick Start Guide](#quickstart)
- [Azulene-Opal](#Azulene-Opal)
- [Opal Job Types](#job-types)


This guide walks you through a **complete working example** of using Opal to submit and monitor an `Absolute Binding Free Energy` job using a protein and ligand file.

You will learn how to:

a. Install `azulene-opal` from PyPI  
b. Log in via the CLI  
c. Place your protein + ligand files in the correct location  
d. Submit an `absolute_binding` job (including automatic file upload)  
e. Check job status and retrieve results  

---

## Create and activate a virtual environment (optional)

### For conda
```bash
conda create -n opal-env python=3.11 -y
conda activate opal-env
```

### For Python
```bash
# Create a virtual environment
python -m venv opal-env

# Activate the environment on Windows
opal-env\Scripts\activate

# Activate the environment on macOS / Linux
source opal-env/bin/activate
```

---

## a. Install `azulene-opal` from PyPI

```bash
pip install azulene-opal
```

Confirm installation:

```bash
python -m opal.main --help
```

---

## b. Log in using the CLI

Run:

```bash
python -m opal.main login
```

The CLI will securely prompt you:

```
Your email: example@gmail.com
Your password: **********
```

After this, Opal stores your auth tokens locally so you don’t need to log in again.

---

## c. Place your protein and ligand files

For this example, we place the files in a folder named `examples`:

```
examples/
  t4_lysozyme.pdb
  toluene.sdf
```

The file paths will be:

* `examples/t4_lysozyme.pdb`
* `examples/toluene.sdf`

The CLI will automatically detect these as **local files**, upload them to Opal, and replace the paths with storage URLs.

---

## d. Submit an `absolute_binding` job

The job type is:

```
absolute_binding
```

The required parameters are:

```json
{
  "pdb_file": "",
  "ligand_sdf_file": ""
}
```

### **Example 1: Using the sample files**

**Using CLI**
```bash
# Submit an absolute_binding job (CMD)
python -m opal.main jobs submit --job-type absolute_binding --input-data "{\"pdb_file\": \"./examples/data/t4_lysozyme.pdb\", \"ligand_sdf_file\": \"./examples/data/toluene.sdf\"}"

# Submit an absolute_binding job (Git Bash / WSL / Linux / macOS)
python -m opal.main jobs submit --job-type absolute_binding --input-data '{"pdb_file": "./examples/data/t4_lysozyme.pdb", "ligand_sdf_file": "./examples/data/toluene.sdf"}'

# Submit an absolute_binding job (Powershell)
python -m opal.main jobs submit --job-type absolute_binding --input-data '{\"pdb_file\": \"./examples/data/t4_lysozyme.pdb\", \"ligand_sdf_file\": \"./examples/data/toluene.sdf\"}'

```

**Using Python**
```bash
from opal import jobs

result = jobs.submit(
    job_type="absolute_binding",
    input_data={
        "pdb_file": "./examples/data/t4_lysozyme.pdb",
        "ligand_sdf_file": "./examples/data/toluene.sdf"
    }
)

print(result)
```

You should see something like:

```
📤 Uploading local files...
✅ Job submitted successfully
{
  "job_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "submitted",
  "message": "Job submitted successfully"
}
```

### **Example 2: Absolute Binding Free Energy (Ligand Already in PDB)**

This example runs an absolute_binding job using:
- A protein PDB file
- A ligand inside the PDB file
- A SMILES string for the ligand
- Shortened equilibration & production lengths
- Only 1 protocol repeat

**Python Example**

```bash
from opal import auth, jobs

# 1. Log in (Only if you haven't logged in)
auth.login(email="your@email.com", password="yourpassword")

# 2. Submit the job
input_data = {
    "pdb_file": "./examples/data/fkb_model_0_2.pdb",
    "ligand_smiles": "CS(=O)C",
    "protocol_repeats": 1,
    "ligand_in_pdb_file": True,
    "complex_prod_length": 0.1,
    "solvent_prod_length": 0.1,
    "complex_equil_length": 0.02,
    "solvent_equil_length": 0.02
}

result = jobs.submit(
    job_type="absolute_binding",
    input_data=input_data
)

print(result)
```


**CLI Example**

Login with:
```bash
python -m opal.main login 
```

Then
```bash
python -m opal.main jobs submit \
  --job-type absolute_binding \
  --input-data "{
      \"pdb_file\": \"./examples/data/fkb_model_0_2.pdb\",
      \"ligand_smiles\": \"CS(=O)C\",
      \"protocol_repeats\": 1,
      \"ligand_in_pdb_file\": true,
      \"complex_prod_length\": 0.1,
      \"solvent_prod_length\": 0.1,
      \"complex_equil_length\": 0.02,
      \"solvent_equil_length\": 0.02
  }"
```


### **Example 3: Using your own files**

```bash
python -m opal.main jobs submit \
  --job-type absolute_binding \
  --input-data '{"pdb_file": "path/to/your_protein.pdb", "ligand_sdf_file": "path/to/your_ligand.sdf"}'
```

Replace the paths with your actual file locations.

---

## e. Submit an `Absolute Aqueous Solvation Free Energy` job

The job type is:

```text
aqueous_solvation
````

The required parameters are:

```json
{
  "smiles": ""
}
```

### **Example: Using a simple SMILES (`CCO`)**

**Using CLI**

```bash
# Submit an aqueous_solvation job (CMD)
python -m opal.main jobs submit --job-type aqueous_solvation --input-data "{\"smiles\": \"CCO\"}"

# Submit an aqueous_solvation job (Git Bash / WSL / Linux / macOS)
python -m opal.main jobs submit --job-type aqueous_solvation --input-data '{"smiles": "CCO"}'

# Submit an aqueous_solvation job (Powershell)
python -m opal.main jobs submit --job-type aqueous_solvation --input-data '{\"smiles\": \"CCO\"}'
```

**Using Python**

```python
from opal import jobs

result = jobs.submit(
    job_type="aqueous_solvation",
    input_data={
        "smiles": "CCO"
    }
)

print(result)
```

You should see something like:

```text
✅ Job submitted successfully
{
  "job_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "submitted",
  "message": "Job submitted successfully"
}
```


## f. Other useful commands

### **1. List your jobs**

Last 5 jobs (default):

```bash
python -m opal.main jobs get-jobs
```

All jobs:

```bash
python -m opal.main jobs get-jobs --all
```

Filter by job type and status:

```bash
python -m opal.main jobs get-jobs \
  --job-type absolute_binding \
  --status completed
```

Filter by date:

```bash
python -m opal.main jobs get-jobs \
  --start-date 2025-12-01T00:00:00Z \
  --end-date   2025-12-05T00:00:00Z
```

---

### **2. Check a specific job**

```bash
python -m opal.main jobs get --job-id YOUR_JOB_ID
```

This returns:

* job status
* input data
* results (if completed)
* timestamps
* any error messages

---

### **3. Poll running jobs**

```bash
python -m opal.main jobs check-running-jobs
```

Use this to check on running jobs.

---

### **4. Cancel a job**

```bash
python -m opal.main jobs cancel --job-id YOUR_JOB_ID
```

Only works if the job is still running.

---

<a name="Azulene-Opal"></a>
# Azulene-Opal


This guide shows how to:

1. Log in
2. Submit a job
3. Inspect and filter jobs
4. Get / cancel a specific job
5. Poll running jobs
6. Check service health & job types
7. Submit a batch of jobs

Each section has **Python** and **CLI** examples.

---

## How to download OPAL CLI

```shellscript
pip install azulene-opal
```

## 0. Imports (Python)

```python
from opal import auth, jobs
```

---

## 1. Log in

### Python

```python
from opal import auth

res = auth.login(email="test@example.com", password="pass123")
print(res)  # {"ok": True, "message": "Logged in successfully!"}
```

### CLI

```bash
# Recommended: let the CLI prompt you (password hidden)
python -m opal.main login
# Your email:    test@example.com
# Your password: *****
```

You stay logged in via locally stored tokens until you explicitly log out.

---

## 2. Check who you are

### Python

```python
from opal import auth

res = auth.whoami()
print(res)
# {
#   "ok": True,
#   "user": { ... full user object ... },
#   "slim": {
#       "email": "...",
#       "role": "...",
#       "approved": True,
#       ...
#   }
# }
```

### CLI

```bash
python -m opal.main whoami
```

If your account isn’t approved yet, the API will tell you and block job access.

---

## 3. Submit a single job

Example job type: `generate_conformers` with a SMILES and number of conformers.

### Python

```python
from opal import jobs

res = jobs.submit(
    job_type="generate_conformers",
    input_data={"smiles": "CCO", "num_conformers": 5},  # dict
)
print(res)
# {"ok": True, "data": {"job_id": "...", "status": "submitted", ...}}
```

(You *can* also pass a JSON string instead of a dict if you want.)

### CLI

```bash
python -m opal.main jobs submit \
  --job-type generate_conformers \
  --input-data '{"smiles": "CCO", "num_conformers": 5}'
```

Each call submits **one** job.

---

## 4. List and filter jobs

By default, the server returns **the last 5 jobs** for the current user.
You can ask for all jobs, limit, or filter by job_type, status, or date range.

### Python

```python
from opal import jobs

# Last 5 jobs (default)
print(jobs.get_jobs())

# All jobs
print(jobs.get_jobs(all_jobs=True))

# Last 10 jobs
print(jobs.get_jobs(limit=10))

# Filter by job_type and status
print(
    jobs.get_jobs(
        job_type="generate_conformers",
        status="completed",
    )
)

# Filter by created_at date range (ISO timestamps)
print(
    jobs.get_jobs(
        start_date="2025-12-01T00:00:00Z",
        end_date="2025-12-05T00:00:00Z",
    )
)
```

Each call returns something like:

```python
{"ok": True, "data": [ { "id": "...", "job_type": "...", ... }, ... ]}
```

### CLI

```bash
# Last 5 jobs
python -m opal.main jobs get-jobs

# All jobs
python -m opal.main jobs get-jobs --all

# Last 10 jobs
python -m opal.main jobs get-jobs --limit 10

# Filter by job_type + status
python -m opal.main jobs get-jobs \
  --job-type generate_conformers \
  --status completed

# Filter by date range
python -m opal.main jobs get-jobs \
  --start-date 2025-12-01T00:00:00Z \
  --end-date   2025-12-05T00:00:00Z
```

---

## 5. Get a specific job

Once you have a `job_id`, you can fetch that job’s details.

### Python

```python
from opal import jobs

res = jobs.get(job_id="YOUR_JOB_ID")
print(res)
# {"ok": True, "data": { "id": "...", "status": "...", "input_data": {...}, "results": {...}, ... }}
```

### CLI

```bash
python -m opal.main jobs get --job-id YOUR_JOB_ID
```

---

## 6. Cancel a job

If a job is still running, you can cancel it.

### Python

```python
from opal import jobs

res = jobs.cancel(job_id="YOUR_JOB_ID")
print(res)
# {"ok": True, "data": {...}}
```

### CLI

```bash
python -m opal.main jobs cancel --job-id YOUR_JOB_ID
```

---

## 7. Poll running jobs

This endpoint checks any currently running jobs and update their statuses.

### Python

```python
from opal import jobs

res = jobs.check_running_jobs()
print(res)
# {"ok": True, "data": {...}}  # depends on your backend payload
```

### CLI

```bash
python -m opal.main jobs check-running-jobs
```


---

## 8. Health check

Check that the Opal backend is reachable.

### Python

```python
from opal import jobs

res = jobs.check_health()
print(res)
# {"ok": True, "data": {...}}  on success
```

### CLI

```bash
python -m opal.main jobs check-health
```

---

## 9. Discover available job types

List job types supported by the current backend.

### Python

```python
from opal import jobs

res = jobs.get_job_types()
print(res)
# {"ok": True, "data": ["generate_conformers", "absolute_solvation_energy_aqueous", ...]}
```

### CLI

```bash
python -m opal.main jobs get-job-types
```

The CLI version prints a prettier, less noisy summary.

---

## 10. Submit a batch of jobs (same job_type, many inputs)

You can submit **multiple jobs at once** for a single `job_type`.
Each entry in the list becomes a **separate job** under the hood.

### Python

```python
from opal import jobs

small_input_list = [
    {"smiles": "CCO",   "num_conformers": 5},
    {"smiles": "CCCO",  "num_conformers": 3},
    {"smiles": "CCcndO","num_conformers": 2},
]

res = jobs.submit_batch_jobs(
    job_type="generate_conformers",
    input_data=small_input_list,
)
print(res)
# {
#   "ok": True,
#   "results": [
#       {
#         "index": 0,
#         "input": {...},
#         "response": {
#             "ok": True,
#             "data": {
#                 "job_id": "...",
#                 "status": "submitted",
#                 "message": "Job submitted successfully",
#                 ...
#             }
#         }
#       },
#       ...
#   ]
# }
```

### CLI

Same thing from the command line, using a JSON list:

```bash
python -m opal.main jobs submit-batch-jobs \
  --job-type generate_conformers \
  --input-data '[{"smiles": "CCO", "num_conformers": 5}, {"smiles": "CCCO", "num_conformers": 3}, {"smiles": "CCcndO", "num_conformers": 2}]'
```

The CLI will print a summary like:

* Total jobs
* Number of successes / failures
* Per-job `job_id` and status

---

## 11. Log out

When you’re done, you can clear the local tokens.

### Python

```python
from opal import auth

res = auth.logout()
print(res)  # {"ok": True}
```

### CLI

```bash
python -m opal.main logout
```

---

## TL;DR minimal workflows

### Python minimal workflow

```python
from opal import auth, jobs

# 1) Log in
auth.login(email="test@example.com", password="pass123")

# 2) Submit a job
submit_res = jobs.submit(
    job_type="generate_conformers",
    input_data={"smiles": "CCO", "num_conformers": 5},
)
print(submit_res)

# 3) List recent jobs
print(jobs.get_jobs())

# 4) Fetch that job by ID
job_id = submit_res["data"]["job_id"]
print(jobs.get(job_id=job_id))
```

### CLI minimal workflow

```bash
# 1) Log in
python -m opal.main login

# 2) Submit one job
python -m opal.main jobs submit \
  --job-type generate_conformers \
  --input-data '{"smiles": "CCO", "num_conformers": 5}'

# 3) See your last 5 jobs
python -m opal.main jobs get-jobs

# 4) Get a specific job
python -m opal.main jobs get --job-id YOUR_JOB_ID
```

### Help Commands

```bash
python -m opal.main --help

python -m opal.main jobs --help

python -m opal.main jobs submit --help
```


<a name="job-types"></a>
## Opal Job Types: 

This document lists all currently available **Opal job types**, their purpose, required inputs, and example payloads.

You can fetch this list via:

```bash
python -m opal.main jobs get-job-types
```

or in Python:

```python
from opal import jobs
jobs.get_job_types()
```

---

## Overview

| ID                      | Name                                             | Description                                                  |
| ----------------------- | ------------------------------------------------ | ------------------------------------------------------------ |
| `generate_conformers`   | Generate Conformers                              | Generate molecular conformers from SMILES notation           |
| `mp2`                   | MP2 Calculation                                  | Møller–Plesset second-order perturbation theory              |
| `hartree_fock`          | Hartree-Fock Calculation                         | Self-consistent field Hartree–Fock calculation               |
| `ccsd_calculation`      | CCSD Calculation                                 | Coupled Cluster Singles and Doubles                          |
| `xtb_calculation`       | XTB Calculation                                  | Extended tight-binding semi-empirical calculation            |
| `molecular_dynamics`    | Molecular Dynamics                               | Molecular dynamics simulation                                |
| `aqueous_solvation`     | Absolute Aqueous Solvation Free Energy           | Solvation free energy in water                               |
| `relative_fe`           | Relative Free Energy                             | Relative free energy between two molecules in water          |
| `relative_fe_uaa`       | Relative Free Energy for (Unnatural) Amino Acids | Relative FE between two (un)natural amino acid structures    |
| `nonaqueous_solvation`  | Absolute Nonaqueous Solvation Free Energy        | Solvation FE of a solute between two solvents                |
| `reaction_free_energy`  | Aqueous Reaction Free Energy                     | Reaction free energy in aqueous solution                     |
| `deprotonation_fe`      | Deprotonation Free Energy                        | Deprotonation free energy in aqueous solution                |
| `absolute_binding`      | Absolute Binding Free Energy                     | Binding FE of a ligand to a protein in water                 |
| `relative_binding`      | Relative Binding Free Energy                     | Relative binding FE between two ligands                      |
| `relative_binding_uaa`  | Relative Binding FE for (Unnatural) Amino Acids  | Relative binding FE for (un)natural amino acid ligands       |
| `lipid_permeation`      | Lipid Permeation Free Energy                     | FE of permeation through a lipid bilayer                     |
| `pocket_docking`        | Pocket Finding and Ligand Docking                | Pocket finding + docking of a ligand to a protein            |
| `upload_file`           | Upload File                                      | Uploads a file and returns its storage path                  |
| `boltz_prediction`      | Boltz-2 Affinity and Structure Prediction        | Protein–ligand affinity + structure prediction using Boltz-2 |

---

## 1. Generate Conformers (`generate_conformers`)

**Description:** Generate molecular conformers from SMILES notation.

### Input Schema

| Field            | Type   | Required | Default | Description                      |
| ---------------- | ------ | -------- | ------- | -------------------------------- |
| `smiles`         | string | yes      | —       | SMILES of the molecule           |
| `num_conformers` | number | yes      | `5`     | Number of conformers to generate |

### Example Input

```json
{
  "smiles": "CCO",
  "num_conformers": 5
}
```

---

## 2. MP2 Calculation (`mp2`)

**Description:** Møller–Plesset second-order perturbation theory.

### Input Schema

| Field   | Type   | Required | Description                      |
| ------- | ------ | -------- | -------------------------------- |
| `atom`  | string | yes      | Atomic coordinates in XYZ format |
| `basis` | string | yes      | Basis set for the calculation    |

### Example Input

```json
{
  "atom": "H 0 0 0; H 0 0 0.74",
  "basis": "ccpvdz"
}
```

---

## 3. Hartree-Fock Calculation (`hartree_fock`)

**Description:** Self-consistent field Hartree–Fock calculation.

### Input Schema

| Field   | Type   | Required | Description                      |
| ------- | ------ | -------- | -------------------------------- |
| `atom`  | string | yes      | Atomic coordinates in XYZ format |
| `basis` | string | yes      | Basis set for the calculation    |

### Example Input

```json
{
  "atom": "H 0 0 0; F 0 0 1.1",
  "basis": "ccpvdz"
}
```

---

## 4. CCSD Calculation (`ccsd_calculation`)

**Description:** Coupled Cluster Singles and Doubles calculation.

### Input Schema

| Field   | Type   | Required | Description                      |
| ------- | ------ | -------- | -------------------------------- |
| `atom`  | string | yes      | Atomic coordinates in XYZ format |
| `basis` | string | yes      | Basis set for the calculation    |

### Example Input

```json
{
  "atom": "H 0 0 0; H 0 0 0.74",
  "basis": "ccpvdz"
}
```

---

## 5. XTB Calculation (`xtb_calculation`)

**Description:** Extended tight-binding semi-empirical calculation.

### Input Schema

| Field       | Type  | Required | Description                 |
| ----------- | ----- | -------- | --------------------------- |
| `numbers`   | array | yes      | Atomic numbers of the atoms |
| `positions` | array | yes      | 3D coordinates of the atoms |

### Example Input

```json
{
  "numbers": [8, 1, 1],
  "positions": [
    [0, 0, 0],
    [0.96, 0, 0],
    [-0.24, 0.93, 0]
  ]
}
```

---

## 6. Molecular Dynamics (`molecular_dynamics`)

**Description:** Molecular dynamics simulation.

### Input Schema

| Field       | Type  | Required | Description            |
| ----------- | ----- | -------- | ---------------------- |
| `numbers`   | array | yes      | Atomic numbers         |
| `positions` | array | yes      | Initial 3D coordinates |

### Example Input

```json
{
  "numbers": [1, 1],
  "positions": [
    [0, 0, 0],
    [0.74, 0, 0]
  ]
}
```

---

## 7. Absolute Aqueous Solvation Free Energy (`aqueous_solvation`)

**Description:** Absolute solvation free energy of a molecule in water via alchemical transformations.

### Key Input Fields

| Field                  | Type    | Required | Default | Description                                            |
| ---------------------- | ------- | -------- | ------- | ------------------------------------------------------ |
| `smiles`               | string  | yes      | —       | Solute SMILES                                          |
| `protonate`            | boolean | no       | `false` | Protonate at given pH                                  |
| `ph`                   | number  | no       | `7`     | pH for protonation                                     |
| `solvent_equil_length` | number  | no       | `0.08`  | Solvent equilibration length (ns / replica)            |
| `solvent_prod_length`  | number  | no       | `0.4`   | Solvent production length (ns / replica)               |
| `vacuum_equil_length`  | number  | no       | `0.08`  | Vacuum equilibration length (ns / replica)             |
| `vacuum_prod_length`   | number  | no       | `0.4`   | Vacuum production length (ns / replica)                |
| `platform`             | string  | no       | `CUDA`  | OpenMM platform (`CUDA`, `OpenCL`, `CPU`, `Reference`) |
| `protocol_repeats`     | integer | no       | `3`     | # of repeats for uncertainty                           |
| `keep_dirs`            | boolean | no       | `True`  | Keep working directories                               |

### Example Input

```json
{
  "smiles": "CCO"
}
```

---

## 8. Relative Free Energy (`relative_fe`)

**Description:** Relative FE between two molecules in water.

### Key Input Fields

| Field              | Type    | Required | Default | Description                         |
| ------------------ | ------- | -------- | ------- | ----------------------------------- |
| `smiles_a`         | string  | yes      | —       | SMILES of molecule A                |
| `smiles_b`         | string  | yes      | —       | SMILES of molecule B                |
| `protonate`        | boolean | no       | `false` | Protonate at pH                     |
| `ph`               | number  | no       | `7`     | pH value                            |
| `equil_length`     | number  | no       | `0.08`  | Equilibration length (ns / replica) |
| `prod_length`      | number  | no       | `0.4`   | Production length (ns / replica)    |
| `platform`         | string  | no       | `CUDA`  | OpenMM platform                     |
| `protocol_repeats` | integer | no       | `3`     | # of repeats                        |
| `keep_dirs`        | boolean | no       | `True`  | Keep working dirs                   |

### Example Input

```json
{
  "smiles_a": "CCO",
  "smiles_b": "CCC"
}
```

---

## 9. Relative Free Energy for (Unnatural) Amino Acids (`relative_fe_uaa`)

**Description:** Relative FE between two (un)natural amino acid sequences.

### Key Input Fields

| Field              | Type    | Required | Default | Description                                             |
| ------------------ | ------- | -------- | ------- | ------------------------------------------------------- |
| `sequence_a`       | string  | yes      | —       | First peptide sequence (standard codes or UAA notation) |
| `sequence_b`       | string  | yes      | —       | Second peptide sequence                                 |
| `uaa_map`          | object  | no       | —       | Map of placeholders (e.g. `{"x": "pF-Phe"}`)            |
| `protonate`        | boolean | no       | `false` | Protonate at pH                                         |
| `ph`               | number  | no       | `7`     | pH value                                                |
| `equil_length`     | number  | no       | `0.08`  | Equilibration length (ns / replica)                     |
| `prod_length`      | number  | no       | `0.4`   | Production length (ns / replica)                        |
| `platform`         | string  | no       | `CUDA`  | OpenMM platform                                         |
| `protocol_repeats` | integer | no       | `3`     | # of repeats                                            |
| `keep_dirs`        | boolean | no       | `True`  | Keep working dirs                                       |

### Example Input

```json
{
  "sequence_a": "YGH",
  "sequence_b": "<pF-Phe>GH"
}
```

---

## 10. Absolute Nonaqueous Solvation Free Energy (`nonaqueous_solvation`)

**Description:** Solvation FE of a solute between two solvents.

### Key Input Fields

| Field              | Type   | Required | Default | Description                            |
| ------------------ | ------ | -------- | ------- | -------------------------------------- |
| `smiles_solute`    | string | yes      | —       | Solute SMILES                          |
| `smiles_solvent_a` | string | yes      | —       | Solvent A SMILES (`"None"` for vacuum) |
| `smiles_solvent_b` | string | yes      | —       | Solvent B SMILES (`"None"` for vacuum) |
| `equil_length`     | number | no       | `0.08`  | Equilibration length (ns / replica)    |
| `prod_length`      | number | no       | `0.4`   | Production length (ns / replica)       |
| `platform`         | string | no       | `CUDA`  | OpenMM platform                        |

### Example Input

```json
{
  "smiles_solute": "CCO",
  "smiles_solvent_a": "None",
  "smiles_solvent_b": "O"
}
```

---

## 11. Aqueous Reaction Free Energy (`reaction_free_energy`)

**Description:** Reaction free energy in aqueous solution.

### Key Input Fields

| Field                    | Type    | Required | Description                                  |
| ------------------------ | ------- | -------- | -------------------------------------------- |
| `smiles_reactant`        | string  | yes      | Reactants SMILES (comma-separated)           |
| `smiles_product`         | string  | yes      | Products SMILES (comma-separated)            |
| `stoichiometry_reactant` | string  | yes      | Stoichiometry of reactants (comma-separated) |
| `stoichiometry_product`  | string  | yes      | Stoichiometry of products (comma-separated)  |
| `solvent_equil_length`   | number  | no       | Solvent equilibration length                 |
| `solvent_prod_length`    | number  | no       | Solvent production length                    |
| `vacuum_equil_length`    | number  | no       | Vacuum equilibration length                  |
| `vacuum_prod_length`     | number  | no       | Vacuum production length                     |
| `platform`               | string  | no       | OpenMM platform                              |
| `protocol_repeats`       | integer | no       | # of repeats                                 |
| `use_xtb`                | boolean | no       | Use xTB for gas-phase                        |
| `keep_dirs`              | boolean | no       | Keep dirs                                    |

### Example Input

```json
{
  "smiles_reactant": "C(=O)=O,O",
  "smiles_product": "OC(=O)O",
  "stoichiometry_reactant": "1,1",
  "stoichiometry_product": "1",
  "use_xtb": true
}
```

---

## 12. Deprotonation Free Energy (`deprotonation_fe`)

**Description:** Deprotonation free energy in aqueous solution.

### Key Input Fields

| Field                  | Type    | Required | Description                    |
| ---------------------- | ------- | -------- | ------------------------------ |
| `smiles_prot`          | string  | yes      | SMILES of protonated species   |
| `smiles_deprot`        | string  | yes      | SMILES of deprotonated species |
| `solvent_equil_length` | number  | no       | Solvent equilibration          |
| `solvent_prod_length`  | number  | no       | Solvent production             |
| `vacuum_equil_length`  | number  | no       | Vacuum equilibration           |
| `vacuum_prod_length`   | number  | no       | Vacuum production              |
| `platform`             | string  | no       | OpenMM platform                |
| `protocol_repeats`     | integer | no       | # of repeats                   |
| `use_xtb`              | boolean | no       | Use xTB                        |
| `keep_dirs`            | boolean | no       | Keep dirs                      |

### Example Input

```json
{
  "smiles_prot": "C(=O)O",
  "smiles_deprot": "C(=O)[O-]",
  "use_xtb": true
}
```

---

## 13. Absolute Binding Free Energy (`absolute_binding`)

**Description:** Absolute binding FE of a ligand to a protein in water.

### Key Input Fields

| Field                  | Type    | Required | Description                                   |
| ---------------------- | ------- | -------- | --------------------------------------------- |
| `pdb_file`             | file    | yes      | Protein PDB (may optionally contain ligand)   |
| `ligand_sdf_file`      | file    | no       | Ligand SDF file                               |
| `ligand_pdb_file`      | file    | no       | Ligand PDB file                               |
| `ligand_in_pdb_file`   | boolean | no       | Whether ligand is in protein PDB              |
| `ligand_smiles`        | string  | no       | Ligand SMILES (esp. if ligand is only in PDB) |
| `solvent_equil_length` | number  | no       | Ligand solvent equilibration                  |
| `solvent_prod_length`  | number  | no       | Ligand solvent production                     |
| `complex_equil_length` | number  | no       | Complex equilibration                         |
| `complex_prod_length`  | number  | no       | Complex production                            |
| `platform`             | string  | no       | OpenMM platform                               |
| `protocol_repeats`     | integer | no       | # of repeats                                  |
| `keep_dirs`            | boolean | no       | Keep dirs                                     |

### Example Input

```json
{
  "pdb_file": "examples/t4_lysozyme.pdb",
  "ligand_sdf_file": "examples/toluene.sdf"
}
```

---

## 14. Relative Binding Free Energy (`relative_binding`)

**Description:** Relative binding FE between two ligands to the same protein.

### Key Input Fields

| Field                  | Type    | Required | Description                  |
| ---------------------- | ------- | -------- | ---------------------------- |
| `pdb_file`             | file    | yes      | Protein PDB                  |
| `ligand_sdf_file_a`    | file    | no       | First ligand SDF             |
| `ligand_sdf_file_b`    | file    | no       | Second ligand SDF            |
| `ligand_pdb_file_a`    | file    | no       | First ligand PDB             |
| `ligand_pdb_file_b`    | file    | no       | Second ligand PDB            |
| `ligand_in_pdb_file_a` | boolean | no       | First ligand in protein PDB  |
| `ligand_in_pdb_file_b` | boolean | no       | Second ligand in protein PDB |
| `smiles_a`             | string  | no       | SMILES of ligand A           |
| `smiles_b`             | string  | no       | SMILES of ligand B           |
| `protonate`            | boolean | no       | Protonate                    |
| `ph`                   | number  | no       | pH value                     |
| `equil_length`         | number  | no       | Equilibration length         |
| `prod_length`          | number  | no       | Production length            |
| `platform`             | string  | no       | OpenMM platform              |
| `protocol_repeats`     | integer | no       | # of repeats                 |
| `keep_dirs`            | boolean | no       | Keep dirs                    |

### Example Input

```json
{
  "pdb_file": "protein.pdb",
  "ligand_sdf_file_a": "ligandA.sdf",
  "ligand_sdf_file_b": "ligandB.sdf"
}
```

---

## 15. Relative Binding FE for (Unnatural) Amino Acids (`relative_binding_uaa`)

**Description:** Relative binding FE between two (un)natural amino acid ligands.

### Key Input Fields

| Field              | Type    | Required | Description                          |
| ------------------ | ------- | -------- | ------------------------------------ |
| `sequence_a`       | string  | yes      | First peptide sequence               |
| `sequence_b`       | string  | yes      | Second peptide sequence              |
| `pdb_file`         | file    | yes      | PDB file (e.g. from previous job)    |
| `uaa_map`          | object  | no       | Map placeholders to UAA names/SMILES |
| `protonate`        | boolean | no       | Protonate                            |
| `ph`               | number  | no       | pH value                             |
| `equil_length`     | number  | no       | Equilibration                        |
| `prod_length`      | number  | no       | Production                           |
| `platform`         | string  | no       | OpenMM platform                      |
| `protocol_repeats` | integer | no       | # of repeats                         |
| `keep_dirs`        | boolean | no       | Keep dirs                            |

### Example Input

```json
{
  "sequence_a": "YGH",
  "sequence_b": "xGH",
  "pdb_file": "protein.pdb",
  "uaa_map": "{\"x\": \"pF-Phe\"}"
}
```

---

## 16. Lipid Permeation Free Energy (`lipid_permeation`)

**Description:** Free energy of a molecule permeating through a lipid bilayer.

### Key Input Fields

| Field          | Type    | Required | Description                                                         |
| -------------- | ------- | -------- | ------------------------------------------------------------------- |
| `smiles`       | string  | yes      | Solute SMILES                                                       |
| `lipid_type`   | string  | yes      | Lipid type (`DPPC`, `DMPC`, `DOPC`, `DLPE`, `DLPC`, `POPE`, `POPC`) |
| `equil_length` | number  | no       | Equilibration length                                                |
| `prod_length`  | number  | no       | Production length                                                   |
| `platform`     | string  | no       | OpenMM platform                                                     |
| `keep_dirs`    | boolean | no       | Keep dirs                                                           |

### Example Input

```json
{
  "smiles": "O",
  "lipid_type": "POPC"
}
```

---

## 17. Pocket Finding and Ligand Docking (`pocket_docking`)

**Description:** Find the binding pocket and dock a ligand to a protein.

### Key Input Fields

| Field           | Type   | Required | Description           |
| --------------- | ------ | -------- | --------------------- |
| `pdb_file`      | file   | yes      | Protein PDB           |
| `ligand_smiles` | string | yes      | Ligand SMILES         |
| `ph`            | float  | no       | pH value (default: 7) |

### Example Input

```json
{
  "pdb_file": "protein.pdb",
  "ligand_smiles": "CC1=CC=CC=C1"
}
```

---

## 18. Upload File (`upload_file`)

**Description:** Uploads a file and returns its storage path.

### Input Schema

| Field       | Type | Required | Description               |
| ----------- | ---- | -------- | ------------------------- |
| `file_path` | file | yes      | Local file path to upload |

### Example Input

```json
{
  "file_path": "examples/input.txt"
}
```

---

## 19. Boltz-2 Affinity and Structure Prediction (`boltz_prediction`)

**Description:** Boltz-2 based affinity and structure prediction.

### Input Schema

| Field              | Type   | Required | Description                                   |
| ------------------ | ------ | -------- | --------------------------------------------- |
| `protein_sequence` | string | yes      | Protein sequence (one-letter amino acid code) |
| `ligand_smiles`    | string | yes      | Ligand SMILES                                 |

### Example Input

```json
{
  "protein_sequence": "MNIFEMLRIDEGLRLKIYKDTEGYYTIGIGHLLTKSPSLNAAK",
  "ligand_smiles": "CC1=CC=CC=C1"
}
```


---

For live job type info directly on Opal, always refer to:

```bash
python -m opal.main jobs get-job-types
```

or see the [API_Reference.md](API_Reference.md) for usage patterns and CLI/Python examples.



**All Rights Reserved**