Initial commit for rowan
This commit is contained in:
413
references/api_reference.md
Normal file
413
references/api_reference.md
Normal file
@@ -0,0 +1,413 @@
|
||||
# Rowan API Reference
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Workflow Class](#workflow-class)
|
||||
2. [Workflow Submission Functions](#workflow-submission-functions)
|
||||
3. [Workflow Retrieval Functions](#workflow-retrieval-functions)
|
||||
4. [Batch Operations](#batch-operations)
|
||||
5. [Utility Functions](#utility-functions)
|
||||
|
||||
---
|
||||
|
||||
## Workflow Class
|
||||
|
||||
The `Workflow` class represents a submitted computational job.
|
||||
|
||||
### Attributes
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `uuid` | str | Unique identifier |
|
||||
| `name` | str | User-assigned name |
|
||||
| `status` | str | Current status: "pending", "running", "completed", "failed" |
|
||||
| `created_at` | datetime | Submission timestamp |
|
||||
| `completed_at` | datetime | Completion timestamp (None if not finished) |
|
||||
| `credits_charged` | float | Credits consumed |
|
||||
| `data` | dict | Workflow results (lazy-loaded) |
|
||||
| `workflow_type` | str | Type of calculation |
|
||||
| `folder_uuid` | str | Parent folder UUID |
|
||||
|
||||
**Note:** Workflow data is not loaded by default to avoid unnecessary downloads. Call `fetch_latest()` to load results.
|
||||
|
||||
### Methods
|
||||
|
||||
#### Status Management
|
||||
|
||||
```python
|
||||
# Get current status
|
||||
status = workflow.get_status()
|
||||
|
||||
# Check if finished
|
||||
if workflow.is_finished():
|
||||
print("Done!")
|
||||
|
||||
# Block until completion
|
||||
workflow.wait_for_result(timeout=3600) # Optional timeout in seconds
|
||||
|
||||
# Refresh from API
|
||||
workflow.fetch_latest(in_place=True)
|
||||
```
|
||||
|
||||
#### Data Operations
|
||||
|
||||
```python
|
||||
# Update metadata
|
||||
workflow.update(
|
||||
name="New name",
|
||||
notes="Additional notes",
|
||||
starred=True
|
||||
)
|
||||
|
||||
# Delete workflow
|
||||
workflow.delete()
|
||||
|
||||
# Delete only results data (keep metadata)
|
||||
workflow.delete_data()
|
||||
|
||||
# Download trajectory files (for MD workflows)
|
||||
workflow.download_dcd_files(output_dir="trajectories/")
|
||||
|
||||
# Download SDF file
|
||||
workflow.download_sdf_file(output_path="molecule.sdf")
|
||||
```
|
||||
|
||||
#### Execution Control
|
||||
|
||||
```python
|
||||
# Stop a running workflow
|
||||
workflow.stop()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow Submission Functions
|
||||
|
||||
### Generic Submission
|
||||
|
||||
```python
|
||||
rowan.submit_workflow(
|
||||
name: str, # Workflow name
|
||||
initial_molecule: Molecule, # stjames.Molecule object
|
||||
workflow_type: str, # e.g., "pka", "optimization", "conformer_search"
|
||||
workflow_data: dict = {}, # Workflow-specific parameters
|
||||
folder_uuid: str = None, # Optional folder
|
||||
max_credits: float = None # Credit limit
|
||||
) -> Workflow
|
||||
```
|
||||
|
||||
### Specialized Submission Functions
|
||||
|
||||
All functions return a `Workflow` object.
|
||||
|
||||
#### Property Prediction
|
||||
|
||||
```python
|
||||
# pKa calculation
|
||||
rowan.submit_pka_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Redox potential
|
||||
rowan.submit_redox_potential_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Solubility prediction
|
||||
rowan.submit_solubility_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Fukui indices (reactivity)
|
||||
rowan.submit_fukui_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Bond dissociation energy
|
||||
rowan.submit_bde_workflow(
|
||||
initial_molecule: Molecule,
|
||||
bond_indices: tuple, # (atom1_idx, atom2_idx)
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
```
|
||||
|
||||
#### Molecular Modeling
|
||||
|
||||
```python
|
||||
# Geometry optimization
|
||||
rowan.submit_basic_calculation_workflow(
|
||||
initial_molecule: Molecule,
|
||||
workflow_type: str = "optimization", # or "single_point", "frequency"
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Conformer search
|
||||
rowan.submit_conformer_search_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Tautomer search
|
||||
rowan.submit_tautomer_search_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Dihedral scan
|
||||
rowan.submit_dihedral_scan_workflow(
|
||||
initial_molecule: Molecule,
|
||||
dihedral_indices: tuple, # (a1, a2, a3, a4)
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Transition state search
|
||||
rowan.submit_ts_search_workflow(
|
||||
initial_molecule: Molecule, # Starting guess
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
```
|
||||
|
||||
#### Protein-Ligand Workflows
|
||||
|
||||
```python
|
||||
# Docking
|
||||
rowan.submit_docking_workflow(
|
||||
protein: str, # Protein UUID
|
||||
pocket: dict, # {"center": [x,y,z], "size": [dx,dy,dz]}
|
||||
initial_molecule: Molecule,
|
||||
executable: str = "vina", # "vina" or "qvina2"
|
||||
scoring_function: str = "vinardo",
|
||||
exhaustiveness: int = 8,
|
||||
do_csearch: bool = True,
|
||||
do_optimization: bool = True,
|
||||
do_pose_refinement: bool = True,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Batch docking
|
||||
rowan.submit_batch_docking_workflow(
|
||||
protein: str,
|
||||
pocket: dict,
|
||||
smiles_list: list, # List of SMILES strings
|
||||
executable: str = "qvina2",
|
||||
scoring_function: str = "vina",
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Protein cofolding
|
||||
rowan.submit_protein_cofolding_workflow(
|
||||
initial_protein_sequences: list, # List of amino acid sequences
|
||||
initial_smiles_list: list = None, # Optional ligand SMILES
|
||||
ligand_binding_affinity_index: int = None,
|
||||
use_msa_server: bool = False,
|
||||
use_potentials: bool = True,
|
||||
compute_strain: bool = False,
|
||||
do_pose_refinement: bool = False,
|
||||
model: str = "boltz_2", # "boltz_1x", "boltz_2", "chai_1r"
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
```
|
||||
|
||||
#### Spectroscopy & Analysis
|
||||
|
||||
```python
|
||||
# NMR prediction
|
||||
rowan.submit_nmr_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Ion mobility (collision cross-section)
|
||||
rowan.submit_ion_mobility_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
|
||||
# Molecular descriptors
|
||||
rowan.submit_descriptors_workflow(
|
||||
initial_molecule: Molecule,
|
||||
name: str = None,
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow Retrieval Functions
|
||||
|
||||
```python
|
||||
# Retrieve single workflow by UUID
|
||||
workflow = rowan.retrieve_workflow(uuid: str) -> Workflow
|
||||
|
||||
# Retrieve multiple workflows
|
||||
workflows = rowan.retrieve_workflows(uuids: list) -> list[Workflow]
|
||||
|
||||
# List workflows with filtering
|
||||
workflows = rowan.list_workflows(
|
||||
name: str = None, # Filter by name (partial match)
|
||||
status: str = None, # "pending", "running", "completed", "failed"
|
||||
workflow_type: str = None, # e.g., "pka", "docking"
|
||||
starred: bool = None, # Filter by starred status
|
||||
folder_uuid: str = None, # Filter by folder
|
||||
page: int = 1, # Pagination
|
||||
size: int = 20 # Results per page
|
||||
) -> list[Workflow]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Batch Operations
|
||||
|
||||
```python
|
||||
# Submit multiple workflows at once
|
||||
workflows = rowan.batch_submit_workflow(
|
||||
molecules: list, # List of stjames.Molecule objects
|
||||
workflow_type: str, # Workflow type for all
|
||||
workflow_data: dict = {},
|
||||
folder_uuid: str = None,
|
||||
max_credits: float = None
|
||||
) -> list[Workflow]
|
||||
|
||||
# Poll status of multiple workflows
|
||||
statuses = rowan.batch_poll_status(
|
||||
uuids: list # List of workflow UUIDs
|
||||
) -> dict # {uuid: status}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Utility Functions
|
||||
|
||||
```python
|
||||
# Get current user info
|
||||
user = rowan.whoami() -> User
|
||||
# user.username, user.email, user.credits, user.weekly_credits
|
||||
|
||||
# Convert SMILES to stjames.Molecule
|
||||
mol = rowan.smiles_to_stjames(smiles: str) -> Molecule
|
||||
|
||||
# Get API key from environment
|
||||
api_key = rowan.get_api_key() -> str
|
||||
|
||||
# Low-level API client
|
||||
client = rowan.api_client() -> httpx.Client
|
||||
|
||||
# Molecule name lookup
|
||||
smiles = rowan.molecule_lookup(name: str) -> str
|
||||
# e.g., rowan.molecule_lookup("aspirin") -> "CC(=O)Oc1ccccc1C(=O)O"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User Class
|
||||
|
||||
Returned by `rowan.whoami()`.
|
||||
|
||||
### Attributes
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `username` | str | Username |
|
||||
| `email` | str | Email address |
|
||||
| `firstname` | str | First name |
|
||||
| `lastname` | str | Last name |
|
||||
| `credits` | float | Available credits |
|
||||
| `weekly_credits` | float | Weekly credit allocation |
|
||||
| `organization` | dict | Organization details |
|
||||
| `individual_subscription` | dict | Subscription information |
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
try:
|
||||
workflow = rowan.submit_pka_workflow(mol, name="test")
|
||||
except rowan.RowanAPIError as e:
|
||||
print(f"API error: {e}")
|
||||
except rowan.AuthenticationError as e:
|
||||
print(f"Authentication failed: {e}")
|
||||
except rowan.RateLimitError as e:
|
||||
print(f"Rate limited, retry after: {e.retry_after}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Waiting for Multiple Workflows
|
||||
|
||||
```python
|
||||
import rowan
|
||||
import time
|
||||
|
||||
workflows = [rowan.submit_pka_workflow(mol) for mol in molecules]
|
||||
|
||||
# Poll until all complete
|
||||
while True:
|
||||
statuses = rowan.batch_poll_status([wf.uuid for wf in workflows])
|
||||
if all(s in ["completed", "failed"] for s in statuses.values()):
|
||||
break
|
||||
time.sleep(10)
|
||||
|
||||
# Fetch results
|
||||
for wf in workflows:
|
||||
wf.fetch_latest(in_place=True)
|
||||
if wf.status == "completed":
|
||||
print(wf.data)
|
||||
```
|
||||
|
||||
### Organizing Workflows in Folders
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Create project structure
|
||||
project = rowan.create_project("Drug Discovery")
|
||||
lead_folder = rowan.create_folder("Lead Compounds", project_uuid=project.uuid)
|
||||
backup_folder = rowan.create_folder("Backup Series", project_uuid=project.uuid)
|
||||
|
||||
# Submit to specific folder
|
||||
workflow = rowan.submit_pka_workflow(
|
||||
mol,
|
||||
name="Lead 1 pKa",
|
||||
folder_uuid=lead_folder.uuid
|
||||
)
|
||||
```
|
||||
429
references/molecule_handling.md
Normal file
429
references/molecule_handling.md
Normal file
@@ -0,0 +1,429 @@
|
||||
# Rowan Molecule Handling Reference
|
||||
|
||||
## Overview
|
||||
|
||||
Rowan uses the `stjames` library for molecular representations. The `stjames.Molecule` class provides a unified interface for creating molecules from various sources and accessing molecular properties.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Creating Molecules](#creating-molecules)
|
||||
2. [Molecule Attributes](#molecule-attributes)
|
||||
3. [Geometry Methods](#geometry-methods)
|
||||
4. [File I/O](#file-io)
|
||||
5. [Conversion Functions](#conversion-functions)
|
||||
6. [Working with Atoms](#working-with-atoms)
|
||||
|
||||
---
|
||||
|
||||
## Creating Molecules
|
||||
|
||||
### From SMILES
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
# Simple SMILES
|
||||
mol = stjames.Molecule.from_smiles("CCO") # Ethanol
|
||||
mol = stjames.Molecule.from_smiles("c1ccccc1") # Benzene
|
||||
|
||||
# With stereochemistry
|
||||
mol = stjames.Molecule.from_smiles("C[C@H](O)[C@@H](O)C") # meso-2,3-butanediol
|
||||
|
||||
# Charged molecules
|
||||
mol = stjames.Molecule.from_smiles("[NH4+]") # Ammonium
|
||||
mol = stjames.Molecule.from_smiles("CC(=O)[O-]") # Acetate
|
||||
|
||||
# Complex drug-like molecules
|
||||
mol = stjames.Molecule.from_smiles("CC(=O)Oc1ccccc1C(=O)O") # Aspirin
|
||||
```
|
||||
|
||||
**Note:** `from_smiles()` automatically generates 3D coordinates.
|
||||
|
||||
---
|
||||
|
||||
### From XYZ String
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
xyz_string = """3
|
||||
Water molecule
|
||||
O 0.000 0.000 0.117
|
||||
H 0.000 0.757 -0.469
|
||||
H 0.000 -0.757 -0.469"""
|
||||
|
||||
mol = stjames.Molecule.from_xyz(xyz_string)
|
||||
```
|
||||
|
||||
**XYZ format with optional metadata in comment line:**
|
||||
```
|
||||
N_atoms
|
||||
charge=0 multiplicity=1 energy=-76.4 comment
|
||||
Element X Y Z
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### From XYZ File
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_file("structure.xyz")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### From Extended XYZ (EXTXYZ)
|
||||
|
||||
Extended XYZ supports additional properties like forces and cell parameters.
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
extxyz_string = """3
|
||||
Lattice="10.0 0.0 0.0 0.0 10.0 0.0 0.0 0.0 10.0" Properties=species:S:1:pos:R:3:forces:R:3 energy=-76.4
|
||||
O 0.000 0.000 0.117 0.01 0.02 0.03
|
||||
H 0.000 0.757 -0.469 0.00 0.00 0.00
|
||||
H 0.000 -0.757 -0.469 0.00 0.00 0.00"""
|
||||
|
||||
mol = stjames.Molecule.from_extxyz(extxyz_string)
|
||||
|
||||
# Access cell information
|
||||
if mol.cell:
|
||||
print(f"Cell: {mol.cell.lattice_vectors}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### From RDKit Molecule
|
||||
|
||||
```python
|
||||
import stjames
|
||||
from rdkit import Chem
|
||||
from rdkit.Chem import AllChem
|
||||
|
||||
# Create RDKit molecule with 3D coordinates
|
||||
rdkit_mol = Chem.MolFromSmiles("CCO")
|
||||
rdkit_mol = Chem.AddHs(rdkit_mol)
|
||||
AllChem.EmbedMolecule(rdkit_mol)
|
||||
AllChem.MMFFOptimizeMolecule(rdkit_mol)
|
||||
|
||||
# Convert to stjames
|
||||
mol = stjames.Molecule.from_rdkit(rdkit_mol)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Specifying Charge and Multiplicity
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
# Neutral singlet (default)
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Cation doublet
|
||||
mol = stjames.Molecule.from_smiles("CCO", charge=1, multiplicity=2)
|
||||
|
||||
# Anion singlet
|
||||
mol = stjames.Molecule.from_smiles("CC(=O)[O-]", charge=-1, multiplicity=1)
|
||||
|
||||
# Triplet oxygen
|
||||
mol = stjames.Molecule.from_smiles("[O][O]", charge=0, multiplicity=3)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Molecule Attributes
|
||||
|
||||
### Basic Properties
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Charge and spin
|
||||
print(f"Charge: {mol.charge}") # 0
|
||||
print(f"Multiplicity: {mol.multiplicity}") # 1
|
||||
|
||||
# Number of atoms
|
||||
print(f"Number of atoms: {len(mol.atoms)}")
|
||||
```
|
||||
|
||||
### Computed Properties (after calculation)
|
||||
|
||||
```python
|
||||
# After running a calculation
|
||||
print(f"Energy: {mol.energy} Hartree")
|
||||
print(f"Dipole: {mol.dipole}") # (x, y, z) in Debye
|
||||
|
||||
# Atomic properties
|
||||
print(f"Mulliken charges: {mol.mulliken_charges}")
|
||||
print(f"Mulliken spin densities: {mol.mulliken_spin_densities}")
|
||||
```
|
||||
|
||||
### Thermochemistry (after frequency calculation)
|
||||
|
||||
```python
|
||||
# After frequency calculation
|
||||
print(f"ZPE: {mol.zero_point_energy} Hartree")
|
||||
print(f"Thermal correction to enthalpy: {mol.thermal_correction_enthalpy}")
|
||||
print(f"Thermal correction to Gibbs: {mol.thermal_correction_gibbs}")
|
||||
print(f"Gibbs free energy: {mol.gibbs_free_energy} Hartree")
|
||||
```
|
||||
|
||||
### Vibrational Modes (after frequency calculation)
|
||||
|
||||
```python
|
||||
for mode in mol.vibrational_modes:
|
||||
print(f"Frequency: {mode.frequency} cm⁻¹")
|
||||
print(f"Reduced mass: {mode.reduced_mass} amu")
|
||||
print(f"IR intensity: {mode.ir_intensity} km/mol")
|
||||
print(f"Displacements: {mode.displacements}")
|
||||
```
|
||||
|
||||
### Periodic Cell
|
||||
|
||||
```python
|
||||
if mol.cell:
|
||||
print(f"Lattice vectors: {mol.cell.lattice_vectors}")
|
||||
print(f"Is periodic: True")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Geometry Methods
|
||||
|
||||
### Distance Between Atoms
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Distance between atoms 0 and 1 (in Angstroms)
|
||||
d = mol.distance(0, 1)
|
||||
print(f"C-C bond length: {d:.3f} Å")
|
||||
```
|
||||
|
||||
### Angle Between Three Atoms
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Angle formed by atoms 0-1-2 (C-C-O)
|
||||
angle = mol.angle(0, 1, 2, degrees=True)
|
||||
print(f"C-C-O angle: {angle:.1f}°")
|
||||
|
||||
# In radians
|
||||
angle_rad = mol.angle(0, 1, 2, degrees=False)
|
||||
```
|
||||
|
||||
### Dihedral Angle
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCCC")
|
||||
|
||||
# Dihedral angle for atoms 0-1-2-3
|
||||
dihedral = mol.dihedral(0, 1, 2, 3, degrees=True)
|
||||
print(f"Dihedral: {dihedral:.1f}°")
|
||||
|
||||
# Use positive domain (0 to 360)
|
||||
dihedral_pos = mol.dihedral(0, 1, 2, 3, degrees=True, positive_domain=True)
|
||||
```
|
||||
|
||||
### Translation
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Translate by vector
|
||||
translated = mol.translated([1.0, 0.0, 0.0]) # Move 1 Å in x direction
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File I/O
|
||||
|
||||
### Export to XYZ
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Get XYZ string
|
||||
xyz_str = mol.to_xyz(comment="Ethanol optimized structure")
|
||||
print(xyz_str)
|
||||
|
||||
# Write to file
|
||||
mol.to_xyz(comment="Ethanol", out_file="ethanol.xyz")
|
||||
```
|
||||
|
||||
### Export to Extended XYZ
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Include energy in comment
|
||||
xyz_str = mol.to_xyz(comment=f"energy={mol.energy}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conversion Functions
|
||||
|
||||
### SMILES to Molecule (Rowan Utility)
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Quick conversion using Rowan's utility
|
||||
mol = rowan.smiles_to_stjames("CCO")
|
||||
```
|
||||
|
||||
### Molecule Lookup by Name
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Convert common names to SMILES
|
||||
smiles = rowan.molecule_lookup("aspirin")
|
||||
print(smiles) # "CC(=O)Oc1ccccc1C(=O)O"
|
||||
|
||||
smiles = rowan.molecule_lookup("caffeine")
|
||||
print(smiles) # "Cn1cnc2c1c(=O)n(c(=O)n2C)C"
|
||||
|
||||
# Use with workflow submission
|
||||
mol = stjames.Molecule.from_smiles(rowan.molecule_lookup("ibuprofen"))
|
||||
workflow = rowan.submit_pka_workflow(mol, name="Ibuprofen pKa")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Working with Atoms
|
||||
|
||||
### Atom Class
|
||||
|
||||
Each atom in `mol.atoms` is an `Atom` object.
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
for i, atom in enumerate(mol.atoms):
|
||||
print(f"Atom {i}: {atom.element}")
|
||||
print(f" Position: ({atom.x:.3f}, {atom.y:.3f}, {atom.z:.3f})")
|
||||
```
|
||||
|
||||
### Atom Attributes
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `element` | str | Element symbol (e.g., "C", "O", "H") |
|
||||
| `x` | float | X coordinate (Å) |
|
||||
| `y` | float | Y coordinate (Å) |
|
||||
| `z` | float | Z coordinate (Å) |
|
||||
| `atomic_number` | int | Atomic number |
|
||||
|
||||
### Getting Coordinates as Array
|
||||
|
||||
```python
|
||||
import stjames
|
||||
import numpy as np
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
|
||||
# Extract positions as numpy array
|
||||
positions = np.array([[atom.x, atom.y, atom.z] for atom in mol.atoms])
|
||||
print(f"Positions shape: {positions.shape}") # (N_atoms, 3)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Batch Molecule Creation
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
smiles_list = ["CCO", "CC(=O)O", "c1ccccc1", "c1ccccc1O"]
|
||||
|
||||
molecules = []
|
||||
for smi in smiles_list:
|
||||
try:
|
||||
mol = stjames.Molecule.from_smiles(smi)
|
||||
molecules.append(mol)
|
||||
except Exception as e:
|
||||
print(f"Failed to create molecule from {smi}: {e}")
|
||||
|
||||
print(f"Created {len(molecules)} molecules")
|
||||
```
|
||||
|
||||
### Modifying Charge/Multiplicity
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
# Create neutral molecule
|
||||
mol = stjames.Molecule.from_smiles("c1ccccc1")
|
||||
|
||||
# Create cation version
|
||||
mol_cation = stjames.Molecule.from_smiles("c1ccccc1", charge=1, multiplicity=2)
|
||||
|
||||
# Or modify existing (if supported)
|
||||
# Note: May need to recreate from coordinates
|
||||
```
|
||||
|
||||
### Combining Geometry Analysis
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCCC")
|
||||
|
||||
# Analyze butane conformer
|
||||
print("Butane geometry analysis:")
|
||||
print(f" C1-C2 bond: {mol.distance(0, 1):.3f} Å")
|
||||
print(f" C2-C3 bond: {mol.distance(1, 2):.3f} Å")
|
||||
print(f" C3-C4 bond: {mol.distance(2, 3):.3f} Å")
|
||||
print(f" C-C-C angle: {mol.angle(0, 1, 2, degrees=True):.1f}°")
|
||||
print(f" C-C-C-C dihedral: {mol.dihedral(0, 1, 2, 3, degrees=True):.1f}°")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Electron Sanity Check
|
||||
|
||||
The `stjames.Molecule` class validates that charge and multiplicity are consistent with the number of electrons:
|
||||
|
||||
```python
|
||||
import stjames
|
||||
|
||||
# This will fail validation
|
||||
try:
|
||||
# Oxygen with wrong multiplicity
|
||||
mol = stjames.Molecule.from_smiles("[O][O]", charge=0, multiplicity=1)
|
||||
except ValueError as e:
|
||||
print(f"Validation error: {e}")
|
||||
|
||||
# Correct: triplet oxygen
|
||||
mol = stjames.Molecule.from_smiles("[O][O]", charge=0, multiplicity=3)
|
||||
```
|
||||
|
||||
The validation ensures:
|
||||
- Number of electrons = sum(atomic_numbers) - charge
|
||||
- Multiplicity is compatible with electron count (odd/even)
|
||||
499
references/proteins_and_organization.md
Normal file
499
references/proteins_and_organization.md
Normal file
@@ -0,0 +1,499 @@
|
||||
# Rowan Proteins and Organization Reference
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Protein Management](#protein-management)
|
||||
2. [Folder Organization](#folder-organization)
|
||||
3. [Project Management](#project-management)
|
||||
4. [Best Practices](#best-practices)
|
||||
|
||||
---
|
||||
|
||||
## Protein Management
|
||||
|
||||
### Protein Class
|
||||
|
||||
The `Protein` class represents a protein structure stored on Rowan.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `uuid` | str | Unique identifier |
|
||||
| `name` | str | User-assigned name |
|
||||
| `data` | str | PDB structure data (lazy-loaded) |
|
||||
| `sanitized` | bool | Whether structure has been cleaned |
|
||||
| `public` | bool | Public visibility flag |
|
||||
| `created_at` | datetime | Upload timestamp |
|
||||
|
||||
---
|
||||
|
||||
### Upload Protein from File
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Upload PDB file
|
||||
protein = rowan.upload_protein(
|
||||
name="EGFR Kinase",
|
||||
file_path="protein.pdb"
|
||||
)
|
||||
|
||||
print(f"Protein UUID: {protein.uuid}")
|
||||
print(f"Name: {protein.name}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Create from PDB ID
|
||||
|
||||
Fetch structure directly from RCSB PDB database.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Download from PDB
|
||||
protein = rowan.create_protein_from_pdb_id(
|
||||
name="EGFR Kinase (1M17)",
|
||||
code="1M17"
|
||||
)
|
||||
|
||||
print(f"Created protein: {protein.uuid}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Retrieve Protein
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Get by UUID
|
||||
protein = rowan.retrieve_protein("protein-uuid")
|
||||
|
||||
# List all proteins
|
||||
proteins = rowan.list_proteins()
|
||||
for p in proteins:
|
||||
print(f"{p.name}: {p.uuid}")
|
||||
|
||||
# Filter by name
|
||||
proteins = rowan.list_proteins(name="EGFR")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Sanitize Protein
|
||||
|
||||
Clean up protein structure (remove waters, artifacts, fix residues).
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
protein = rowan.create_protein_from_pdb_id("Target", "1M17")
|
||||
|
||||
# Sanitize the structure
|
||||
protein.sanitize()
|
||||
|
||||
# Check status
|
||||
print(f"Sanitized: {protein.sanitized}")
|
||||
```
|
||||
|
||||
**Sanitization performs:**
|
||||
- Removes non-protein molecules (waters, ligands, ions)
|
||||
- Fixes missing atoms in residues
|
||||
- Resolves alternate conformations
|
||||
- Standardizes residue names
|
||||
|
||||
---
|
||||
|
||||
### Update Protein Metadata
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
protein = rowan.retrieve_protein("protein-uuid")
|
||||
|
||||
# Update name
|
||||
protein.update(name="EGFR Kinase Domain")
|
||||
|
||||
# Define binding pocket
|
||||
protein.update(
|
||||
pocket={
|
||||
"center": [10.0, 20.0, 30.0],
|
||||
"size": [20.0, 20.0, 20.0]
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Download Protein Structure
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
protein = rowan.retrieve_protein("protein-uuid")
|
||||
|
||||
# Load structure data
|
||||
protein.refresh() # Fetches PDB data if not loaded
|
||||
|
||||
# Download to file
|
||||
protein.download_pdb_file("output.pdb")
|
||||
|
||||
# Or access data directly
|
||||
pdb_content = protein.data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Delete Protein
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
protein = rowan.retrieve_protein("protein-uuid")
|
||||
protein.delete()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Folder Organization
|
||||
|
||||
### Folder Class
|
||||
|
||||
Folders provide hierarchical organization for workflows.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `uuid` | str | Unique identifier |
|
||||
| `name` | str | Folder name |
|
||||
| `parent_uuid` | str | Parent folder UUID (None for root) |
|
||||
| `starred` | bool | Starred status |
|
||||
| `public` | bool | Public visibility |
|
||||
| `created_at` | datetime | Creation timestamp |
|
||||
|
||||
---
|
||||
|
||||
### Create Folder
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Create root folder
|
||||
folder = rowan.create_folder(name="Drug Discovery Project")
|
||||
|
||||
# Create subfolder
|
||||
subfolder = rowan.create_folder(
|
||||
name="Lead Compounds",
|
||||
parent_uuid=folder.uuid
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Retrieve Folder
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Get by UUID
|
||||
folder = rowan.retrieve_folder("folder-uuid")
|
||||
|
||||
# List all folders
|
||||
folders = rowan.list_folders()
|
||||
for f in folders:
|
||||
print(f"{f.name}: {f.uuid}")
|
||||
|
||||
# Filter
|
||||
folders = rowan.list_folders(name="Project", starred=True)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Update Folder
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
folder = rowan.retrieve_folder("folder-uuid")
|
||||
|
||||
# Rename
|
||||
folder.update(name="New Name")
|
||||
|
||||
# Move to different parent
|
||||
folder.update(parent_uuid="new-parent-uuid")
|
||||
|
||||
# Star folder
|
||||
folder.update(starred=True)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Print Folder Tree
|
||||
|
||||
Visualize folder hierarchy.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Print structure starting from root
|
||||
rowan.print_folder_tree()
|
||||
|
||||
# Print from specific folder
|
||||
rowan.print_folder_tree(root_uuid="folder-uuid")
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
📁 Drug Discovery Project
|
||||
├── 📁 Lead Compounds
|
||||
│ ├── 📄 Lead 1 pKa (completed)
|
||||
│ └── 📄 Lead 2 pKa (completed)
|
||||
└── 📁 Backup Series
|
||||
└── 📄 Backup 1 conformers (running)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Delete Folder
|
||||
|
||||
**Warning:** Deleting a folder removes all workflows inside!
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
folder = rowan.retrieve_folder("folder-uuid")
|
||||
folder.delete() # Deletes folder and all contents
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Submit Workflow to Folder
|
||||
|
||||
```python
|
||||
import rowan
|
||||
import stjames
|
||||
|
||||
folder = rowan.create_folder(name="pKa Calculations")
|
||||
|
||||
mol = stjames.Molecule.from_smiles("CCO")
|
||||
workflow = rowan.submit_pka_workflow(
|
||||
initial_molecule=mol,
|
||||
name="Ethanol pKa",
|
||||
folder_uuid=folder.uuid # Organize in folder
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### List Workflows in Folder
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
folder = rowan.retrieve_folder("folder-uuid")
|
||||
workflows = rowan.list_workflows(folder_uuid=folder.uuid)
|
||||
|
||||
for wf in workflows:
|
||||
print(f"{wf.name}: {wf.status}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Management
|
||||
|
||||
### Project Class
|
||||
|
||||
Projects are top-level containers for organizing folders and workflows.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `uuid` | str | Unique identifier |
|
||||
| `name` | str | Project name |
|
||||
| `created_at` | datetime | Creation timestamp |
|
||||
|
||||
---
|
||||
|
||||
### Create Project
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
project = rowan.create_project(name="Cancer Drug Discovery")
|
||||
print(f"Project UUID: {project.uuid}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Retrieve Project
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Get by UUID
|
||||
project = rowan.retrieve_project("project-uuid")
|
||||
|
||||
# List all projects
|
||||
projects = rowan.list_projects()
|
||||
for p in projects:
|
||||
print(f"{p.name}: {p.uuid}")
|
||||
|
||||
# Get default project
|
||||
default = rowan.default_project()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Update Project
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
project = rowan.retrieve_project("project-uuid")
|
||||
project.update(name="Renamed Project")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Delete Project
|
||||
|
||||
**Warning:** Deletes all folders and workflows in project!
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
project = rowan.retrieve_project("project-uuid")
|
||||
project.delete()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Create Folder in Project
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
project = rowan.create_project("Drug Discovery")
|
||||
folder = rowan.create_folder(
|
||||
name="Phase 1 Compounds",
|
||||
project_uuid=project.uuid
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Organizing a Drug Discovery Campaign
|
||||
|
||||
```python
|
||||
import rowan
|
||||
import stjames
|
||||
|
||||
# Create project structure
|
||||
project = rowan.create_project("EGFR Inhibitor Campaign")
|
||||
|
||||
# Create organized folders
|
||||
target_folder = rowan.create_folder("Target Preparation", project_uuid=project.uuid)
|
||||
hit_folder = rowan.create_folder("Hit Finding", project_uuid=project.uuid)
|
||||
lead_folder = rowan.create_folder("Lead Optimization", project_uuid=project.uuid)
|
||||
|
||||
# Upload and prepare protein
|
||||
protein = rowan.create_protein_from_pdb_id("EGFR", "1M17")
|
||||
protein.sanitize()
|
||||
|
||||
# Define binding site
|
||||
pocket = {
|
||||
"center": [10.0, 20.0, 30.0], # From crystal ligand
|
||||
"size": [20.0, 20.0, 20.0]
|
||||
}
|
||||
|
||||
# Submit docking workflows to hit folder
|
||||
for smiles in hit_compounds:
|
||||
mol = stjames.Molecule.from_smiles(smiles)
|
||||
workflow = rowan.submit_docking_workflow(
|
||||
protein=protein.uuid,
|
||||
pocket=pocket,
|
||||
initial_molecule=mol,
|
||||
name=f"Dock: {smiles[:20]}",
|
||||
folder_uuid=hit_folder.uuid
|
||||
)
|
||||
```
|
||||
|
||||
### Reusing Proteins Across Workflows
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Upload once
|
||||
protein = rowan.upload_protein("My Target", "target.pdb")
|
||||
protein.sanitize()
|
||||
|
||||
# Save UUID for later use
|
||||
protein_uuid = protein.uuid
|
||||
|
||||
# Use in multiple workflows
|
||||
for compound in compounds:
|
||||
workflow = rowan.submit_docking_workflow(
|
||||
protein=protein_uuid, # Reuse same protein
|
||||
pocket=pocket,
|
||||
initial_molecule=compound,
|
||||
name=f"Dock: {compound.name}"
|
||||
)
|
||||
```
|
||||
|
||||
### Folder Naming Conventions
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from datetime import datetime
|
||||
|
||||
# Include date in folder name
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
folder = rowan.create_folder(f"{date_str}_Lead_Optimization")
|
||||
|
||||
# Include project phase
|
||||
folder = rowan.create_folder("Phase2_pKa_Calculations")
|
||||
|
||||
# Include target name
|
||||
folder = rowan.create_folder("EGFR_Conformer_Search")
|
||||
```
|
||||
|
||||
### Cleaning Up Old Workflows
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Find old completed workflows
|
||||
old_cutoff = datetime.now() - timedelta(days=30)
|
||||
workflows = rowan.list_workflows(status="completed")
|
||||
|
||||
for wf in workflows:
|
||||
if wf.completed_at < old_cutoff:
|
||||
# Delete data but keep metadata
|
||||
wf.delete_data()
|
||||
# Or delete entirely
|
||||
# wf.delete()
|
||||
```
|
||||
|
||||
### Monitoring Credit Usage
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
# Check before submitting
|
||||
user = rowan.whoami()
|
||||
print(f"Available credits: {user.credits}")
|
||||
|
||||
# Set credit limit per workflow
|
||||
workflow = rowan.submit_pka_workflow(
|
||||
initial_molecule=mol,
|
||||
name="pKa calculation",
|
||||
max_credits=10.0 # Fail if exceeds 10 credits
|
||||
)
|
||||
```
|
||||
438
references/rdkit_native.md
Normal file
438
references/rdkit_native.md
Normal file
@@ -0,0 +1,438 @@
|
||||
# Rowan RDKit-Native API Reference
|
||||
|
||||
## Overview
|
||||
|
||||
The RDKit-native API provides a simplified interface for users working with RDKit molecules. Functions automatically handle:
|
||||
|
||||
1. Converting RDKit molecules to Rowan's internal format
|
||||
2. Allocating cloud compute resources
|
||||
3. Executing multi-step workflows
|
||||
4. Monitoring job completion
|
||||
5. Returning RDKit-compatible results
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [pKa Functions](#pka-functions)
|
||||
2. [Tautomer Functions](#tautomer-functions)
|
||||
3. [Conformer Functions](#conformer-functions)
|
||||
4. [Energy Functions](#energy-functions)
|
||||
5. [Optimization Functions](#optimization-functions)
|
||||
6. [Batch Processing Patterns](#batch-processing-patterns)
|
||||
|
||||
---
|
||||
|
||||
## pKa Functions
|
||||
|
||||
### `run_pka`
|
||||
|
||||
Calculate pKa for a single molecule.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
mol = Chem.MolFromSmiles("c1ccccc1O") # Phenol
|
||||
result = rowan.run_pka(mol)
|
||||
|
||||
print(f"Strongest acid pKa: {result.strongest_acid}")
|
||||
print(f"Strongest base pKa: {result.strongest_base}")
|
||||
print(f"Microscopic pKas: {result.microscopic_pkas}")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mol` (rdkit.Chem.Mol): RDKit molecule object
|
||||
|
||||
**Returns:** `PKAResult` object with attributes:
|
||||
- `strongest_acid`: float - pKa of most acidic proton
|
||||
- `strongest_base`: float - pKa of most basic site
|
||||
- `microscopic_pkas`: list - Site-specific pKa values
|
||||
- `tautomer_populations`: dict - Populations at pH 7
|
||||
|
||||
---
|
||||
|
||||
### `batch_pka`
|
||||
|
||||
Calculate pKa for multiple molecules in parallel.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
smiles_list = ["CCO", "CC(=O)O", "c1ccccc1O", "c1ccccc1N"]
|
||||
mols = [Chem.MolFromSmiles(smi) for smi in smiles_list]
|
||||
|
||||
results = rowan.batch_pka(mols)
|
||||
|
||||
for smi, result in zip(smiles_list, results):
|
||||
if result is not None:
|
||||
print(f"{smi}: pKa = {result.strongest_acid:.2f}")
|
||||
else:
|
||||
print(f"{smi}: Failed")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mols` (list[rdkit.Chem.Mol]): List of RDKit molecules
|
||||
|
||||
**Returns:** `list[PKAResult | None]` - Results for each molecule (None if failed)
|
||||
|
||||
---
|
||||
|
||||
## Tautomer Functions
|
||||
|
||||
### `run_tautomers`
|
||||
|
||||
Enumerate and rank tautomers.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
mol = Chem.MolFromSmiles("Oc1ncnc2[nH]cnc12") # Hypoxanthine
|
||||
result = rowan.run_tautomers(mol)
|
||||
|
||||
print(f"Number of tautomers: {len(result.tautomers)}")
|
||||
for i, (taut, pop) in enumerate(zip(result.tautomers, result.populations)):
|
||||
print(f"Tautomer {i}: {Chem.MolToSmiles(taut)}, Population: {pop:.1%}")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mol` (rdkit.Chem.Mol): RDKit molecule object
|
||||
|
||||
**Returns:** `TautomerResult` object with attributes:
|
||||
- `tautomers`: list[rdkit.Chem.Mol] - Tautomer structures
|
||||
- `energies`: list[float] - Relative energies (kcal/mol)
|
||||
- `populations`: list[float] - Boltzmann populations at 298 K
|
||||
|
||||
---
|
||||
|
||||
### `batch_tautomers`
|
||||
|
||||
Enumerate tautomers for multiple molecules.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
mols = [Chem.MolFromSmiles(smi) for smi in smiles_list]
|
||||
results = rowan.batch_tautomers(mols)
|
||||
|
||||
for smi, result in zip(smiles_list, results):
|
||||
if result:
|
||||
print(f"{smi}: {len(result.tautomers)} tautomers")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mols` (list[rdkit.Chem.Mol]): List of RDKit molecules
|
||||
|
||||
**Returns:** `list[TautomerResult | None]`
|
||||
|
||||
---
|
||||
|
||||
## Conformer Functions
|
||||
|
||||
### `run_conformers`
|
||||
|
||||
Generate and optimize conformer ensemble.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
mol = Chem.MolFromSmiles("CCCC") # Butane
|
||||
result = rowan.run_conformers(mol)
|
||||
|
||||
print(f"Number of conformers: {len(result.conformers)}")
|
||||
print(f"Energy range: {result.energy_range:.2f} kcal/mol")
|
||||
|
||||
# Get lowest energy conformer
|
||||
best_conformer = result.lowest_energy_conformer
|
||||
print(f"Lowest energy: {result.energies[0]:.4f} Hartree")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mol` (rdkit.Chem.Mol): RDKit molecule object
|
||||
|
||||
**Returns:** `ConformerResult` object with attributes:
|
||||
- `conformers`: list[rdkit.Chem.Mol] - Conformer structures (with 3D coordinates)
|
||||
- `energies`: list[float] - Energies in Hartree
|
||||
- `lowest_energy_conformer`: rdkit.Chem.Mol - Global minimum
|
||||
- `energy_range`: float - Energy span in kcal/mol
|
||||
- `boltzmann_weights`: list[float] - Population weights
|
||||
|
||||
---
|
||||
|
||||
### `batch_conformers`
|
||||
|
||||
Generate conformers for multiple molecules.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
mols = [Chem.MolFromSmiles(smi) for smi in smiles_list]
|
||||
results = rowan.batch_conformers(mols)
|
||||
|
||||
for smi, result in zip(smiles_list, results):
|
||||
if result:
|
||||
print(f"{smi}: {len(result.conformers)} conformers, range = {result.energy_range:.2f} kcal/mol")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mols` (list[rdkit.Chem.Mol]): List of RDKit molecules
|
||||
|
||||
**Returns:** `list[ConformerResult | None]`
|
||||
|
||||
---
|
||||
|
||||
## Energy Functions
|
||||
|
||||
### `run_energy`
|
||||
|
||||
Calculate single-point energy.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
from rdkit.Chem import AllChem
|
||||
|
||||
# Create molecule with 3D coordinates
|
||||
mol = Chem.MolFromSmiles("CCO")
|
||||
mol = Chem.AddHs(mol)
|
||||
AllChem.EmbedMolecule(mol)
|
||||
AllChem.MMFFOptimizeMolecule(mol)
|
||||
|
||||
result = rowan.run_energy(mol)
|
||||
|
||||
print(f"Energy: {result.energy:.6f} Hartree")
|
||||
print(f"Dipole moment: {result.dipole_magnitude:.2f} Debye")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mol` (rdkit.Chem.Mol): RDKit molecule with 3D coordinates
|
||||
|
||||
**Returns:** `EnergyResult` object with attributes:
|
||||
- `energy`: float - Total energy (Hartree)
|
||||
- `dipole`: tuple[float, float, float] - Dipole vector
|
||||
- `dipole_magnitude`: float - Dipole magnitude (Debye)
|
||||
- `mulliken_charges`: list[float] - Atomic charges
|
||||
|
||||
---
|
||||
|
||||
### `batch_energy`
|
||||
|
||||
Calculate energies for multiple molecules.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
# Molecules must have 3D coordinates
|
||||
results = rowan.batch_energy(mols_3d)
|
||||
|
||||
for mol, result in zip(mols_3d, results):
|
||||
if result:
|
||||
print(f"{Chem.MolToSmiles(mol)}: E = {result.energy:.6f} Ha")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mols` (list[rdkit.Chem.Mol]): List of molecules with 3D coordinates
|
||||
|
||||
**Returns:** `list[EnergyResult | None]`
|
||||
|
||||
---
|
||||
|
||||
## Optimization Functions
|
||||
|
||||
### `run_optimization`
|
||||
|
||||
Optimize molecular geometry.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
from rdkit.Chem import AllChem
|
||||
|
||||
# Start from initial guess
|
||||
mol = Chem.MolFromSmiles("CC(=O)O")
|
||||
mol = Chem.AddHs(mol)
|
||||
AllChem.EmbedMolecule(mol)
|
||||
|
||||
result = rowan.run_optimization(mol)
|
||||
|
||||
print(f"Final energy: {result.energy:.6f} Hartree")
|
||||
print(f"Converged: {result.converged}")
|
||||
|
||||
# Get optimized structure
|
||||
optimized_mol = result.molecule
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mol` (rdkit.Chem.Mol): RDKit molecule (3D coordinates optional)
|
||||
|
||||
**Returns:** `OptimizationResult` object with attributes:
|
||||
- `molecule`: rdkit.Chem.Mol - Optimized structure
|
||||
- `energy`: float - Final energy (Hartree)
|
||||
- `converged`: bool - Optimization convergence
|
||||
- `n_steps`: int - Number of optimization steps
|
||||
|
||||
---
|
||||
|
||||
### `batch_optimization`
|
||||
|
||||
Optimize multiple molecules.
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
results = rowan.batch_optimization(mols)
|
||||
|
||||
for mol, result in zip(mols, results):
|
||||
if result and result.converged:
|
||||
print(f"{Chem.MolToSmiles(mol)}: E = {result.energy:.6f} Ha")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mols` (list[rdkit.Chem.Mol]): List of RDKit molecules
|
||||
|
||||
**Returns:** `list[OptimizationResult | None]`
|
||||
|
||||
---
|
||||
|
||||
## Batch Processing Patterns
|
||||
|
||||
### Parallel Processing with Progress
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
from tqdm import tqdm
|
||||
|
||||
smiles_list = ["CCO", "CC(=O)O", "c1ccccc1O", "c1ccc(O)c(O)c1"]
|
||||
mols = [Chem.MolFromSmiles(smi) for smi in smiles_list]
|
||||
|
||||
# Batch functions automatically distribute across multiple workers
|
||||
print("Submitting batch pKa calculations...")
|
||||
results = rowan.batch_pka(mols)
|
||||
|
||||
# Process results
|
||||
for smi, result in zip(smiles_list, results):
|
||||
if result:
|
||||
print(f"{smi}: pKa = {result.strongest_acid:.2f}")
|
||||
else:
|
||||
print(f"{smi}: calculation failed")
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
|
||||
def safe_pka(smiles):
|
||||
"""Safely calculate pKa with error handling."""
|
||||
try:
|
||||
mol = Chem.MolFromSmiles(smiles)
|
||||
if mol is None:
|
||||
return None, "Invalid SMILES"
|
||||
|
||||
result = rowan.run_pka(mol)
|
||||
return result, None
|
||||
|
||||
except rowan.RowanAPIError as e:
|
||||
return None, f"API error: {e}"
|
||||
except Exception as e:
|
||||
return None, f"Error: {e}"
|
||||
|
||||
# Usage
|
||||
result, error = safe_pka("c1ccccc1O")
|
||||
if error:
|
||||
print(f"Failed: {error}")
|
||||
else:
|
||||
print(f"pKa: {result.strongest_acid}")
|
||||
```
|
||||
|
||||
### Combining with RDKit Workflows
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
from rdkit.Chem import Descriptors, AllChem
|
||||
|
||||
# Load molecules
|
||||
mols = [Chem.MolFromSmiles(smi) for smi in smiles_list]
|
||||
|
||||
# Filter by RDKit descriptors first
|
||||
filtered_mols = [
|
||||
mol for mol in mols
|
||||
if mol and Descriptors.MolWt(mol) < 500
|
||||
]
|
||||
|
||||
# Calculate pKa only for filtered set
|
||||
pka_results = rowan.batch_pka(filtered_mols)
|
||||
|
||||
# Combine results
|
||||
for mol, pka in zip(filtered_mols, pka_results):
|
||||
if pka:
|
||||
mw = Descriptors.MolWt(mol)
|
||||
print(f"{Chem.MolToSmiles(mol)}: MW={mw:.1f}, pKa={pka.strongest_acid:.2f}")
|
||||
```
|
||||
|
||||
### Virtual Screening Pipeline
|
||||
|
||||
```python
|
||||
import rowan
|
||||
from rdkit import Chem
|
||||
from rdkit.Chem import Descriptors
|
||||
import pandas as pd
|
||||
|
||||
def screen_compounds(smiles_list):
|
||||
"""Screen compounds for drug-likeness and calculate pKa."""
|
||||
results = []
|
||||
|
||||
mols = [Chem.MolFromSmiles(smi) for smi in smiles_list]
|
||||
valid_mols = [(smi, mol) for smi, mol in zip(smiles_list, mols) if mol]
|
||||
|
||||
# Batch pKa calculation
|
||||
pka_results = rowan.batch_pka([mol for _, mol in valid_mols])
|
||||
|
||||
for (smi, mol), pka in zip(valid_mols, pka_results):
|
||||
result = {
|
||||
'smiles': smi,
|
||||
'mw': Descriptors.MolWt(mol),
|
||||
'logp': Descriptors.MolLogP(mol),
|
||||
'hbd': Descriptors.NumHDonors(mol),
|
||||
'hba': Descriptors.NumHAcceptors(mol),
|
||||
'pka': pka.strongest_acid if pka else None
|
||||
}
|
||||
results.append(result)
|
||||
|
||||
return pd.DataFrame(results)
|
||||
|
||||
# Usage
|
||||
df = screen_compounds(compound_library)
|
||||
print(df[df['pka'].notna()].sort_values('pka'))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
1. **Batch functions are more efficient** - Submit multiple molecules at once rather than one by one
|
||||
2. **Fractional credits** - Low-cost calculations may use < 1 credit (e.g., 0.17 credits for fast pKa)
|
||||
3. **Automatic parallelization** - Batch functions distribute work across Rowan's compute cluster
|
||||
4. **Results caching** - Previously calculated molecules may return faster
|
||||
|
||||
---
|
||||
|
||||
## Comparison with Full API
|
||||
|
||||
| Feature | RDKit-Native | Full API |
|
||||
|---------|--------------|----------|
|
||||
| Input format | RDKit Mol | stjames.Molecule |
|
||||
| Output format | RDKit Mol + results | Workflow object |
|
||||
| Workflow control | Automatic | Manual wait/fetch |
|
||||
| Folder organization | No | Yes |
|
||||
| Advanced parameters | Default only | Full control |
|
||||
|
||||
Use RDKit-native API for quick calculations; use full API for complex workflows or when you need fine-grained control.
|
||||
481
references/results_interpretation.md
Normal file
481
references/results_interpretation.md
Normal file
@@ -0,0 +1,481 @@
|
||||
# Rowan Results Interpretation Reference
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Accessing Workflow Results](#accessing-workflow-results)
|
||||
2. [Property Prediction Results](#property-prediction-results)
|
||||
3. [Molecular Modeling Results](#molecular-modeling-results)
|
||||
4. [Docking Results](#docking-results)
|
||||
5. [Cofolding Results](#cofolding-results)
|
||||
6. [Validation and Quality Assessment](#validation-and-quality-assessment)
|
||||
|
||||
---
|
||||
|
||||
## Accessing Workflow Results
|
||||
|
||||
### Basic Pattern
|
||||
|
||||
```python
|
||||
import rowan
|
||||
|
||||
workflow = rowan.submit_pka_workflow(mol, name="test")
|
||||
|
||||
# Wait for completion
|
||||
workflow.wait_for_result()
|
||||
|
||||
# Fetch results (not loaded by default)
|
||||
workflow.fetch_latest(in_place=True)
|
||||
|
||||
# Check status before accessing data
|
||||
if workflow.status == "completed":
|
||||
print(workflow.data)
|
||||
elif workflow.status == "failed":
|
||||
print(f"Failed: {workflow.error_message}")
|
||||
```
|
||||
|
||||
### Workflow Status Values
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `pending` | Queued, waiting for resources |
|
||||
| `running` | Currently executing |
|
||||
| `completed` | Successfully finished |
|
||||
| `failed` | Execution failed |
|
||||
| `stopped` | Manually stopped |
|
||||
|
||||
### Credits Charged
|
||||
|
||||
```python
|
||||
# After completion
|
||||
print(f"Credits used: {workflow.credits_charged}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Property Prediction Results
|
||||
|
||||
### pKa Results
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_pka_workflow(mol, name="pKa")
|
||||
workflow.wait_for_result()
|
||||
workflow.fetch_latest(in_place=True)
|
||||
|
||||
data = workflow.data
|
||||
|
||||
# Macroscopic pKa
|
||||
strongest_acid = data['strongest_acid'] # Most acidic pKa
|
||||
strongest_base = data['strongest_base'] # Most basic pKa (if applicable)
|
||||
|
||||
# Microscopic pKa (site-specific)
|
||||
micro_pkas = data['microscopic_pkas']
|
||||
for site in micro_pkas:
|
||||
print(f"Site {site['atom_index']}: pKa = {site['pka']:.2f}")
|
||||
|
||||
# Tautomer analysis
|
||||
tautomers = data.get('tautomer_populations', {})
|
||||
for smiles, pop in tautomers.items():
|
||||
print(f"{smiles}: {pop:.1%}")
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- pKa < 0: Strong acid
|
||||
- pKa 0-7: Acidic
|
||||
- pKa 7-14: Basic
|
||||
- pKa > 14: Very weak acid
|
||||
|
||||
---
|
||||
|
||||
### Redox Potential Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
oxidation_potential = data['oxidation_potential'] # V vs SHE
|
||||
reduction_potential = data['reduction_potential'] # V vs SHE
|
||||
|
||||
print(f"Oxidation: {oxidation_potential:.2f} V vs SHE")
|
||||
print(f"Reduction: {reduction_potential:.2f} V vs SHE")
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- Higher oxidation potential = harder to oxidize
|
||||
- Lower reduction potential = harder to reduce
|
||||
- Compare to reference compounds for context
|
||||
|
||||
---
|
||||
|
||||
### Solubility Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
log_s = data['aqueous_solubility'] # Log10(mol/L)
|
||||
classification = data['solubility_class']
|
||||
|
||||
print(f"Log S: {log_s:.2f}")
|
||||
print(f"Classification: {classification}") # "High", "Medium", "Low"
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- Log S > -1: High solubility (>0.1 M)
|
||||
- Log S -1 to -3: Medium solubility
|
||||
- Log S < -3: Low solubility (<0.001 M)
|
||||
|
||||
---
|
||||
|
||||
### Fukui Index Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
# Per-atom reactivity indices
|
||||
fukui_plus = data['fukui_plus'] # Nucleophilic attack sites
|
||||
fukui_minus = data['fukui_minus'] # Electrophilic attack sites
|
||||
fukui_dual = data['fukui_dual'] # Dual descriptor
|
||||
|
||||
# Find most reactive sites
|
||||
for i, (fp, fm, fd) in enumerate(zip(fukui_plus, fukui_minus, fukui_dual)):
|
||||
print(f"Atom {i}: f+ = {fp:.3f}, f- = {fm:.3f}, dual = {fd:.3f}")
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- High f+ = susceptible to nucleophilic attack
|
||||
- High f- = susceptible to electrophilic attack
|
||||
- Dual > 0 = electrophilic character, Dual < 0 = nucleophilic character
|
||||
|
||||
---
|
||||
|
||||
## Molecular Modeling Results
|
||||
|
||||
### Geometry Optimization Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
final_mol = data['final_molecule'] # stjames.Molecule
|
||||
final_energy = data['energy'] # Hartree
|
||||
converged = data['convergence']
|
||||
|
||||
print(f"Final energy: {final_energy:.6f} Hartree")
|
||||
print(f"Converged: {converged}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Conformer Search Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
conformers = data['conformers']
|
||||
lowest_energy = data['lowest_energy_conformer']
|
||||
|
||||
# Analyze conformer distribution
|
||||
for i, conf in enumerate(conformers):
|
||||
rel_energy = (conf['energy'] - conformers[0]['energy']) * 627.509 # kcal/mol
|
||||
print(f"Conformer {i}: ΔE = {rel_energy:.2f} kcal/mol")
|
||||
|
||||
# Boltzmann weights
|
||||
weights = data.get('boltzmann_weights', [])
|
||||
for i, w in enumerate(weights):
|
||||
print(f"Conformer {i}: population = {w:.1%}")
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- Conformers within 3 kcal/mol are typically accessible at room temperature
|
||||
- Lowest energy conformer may not be most populated in solution
|
||||
- Consider ensemble averaging for properties
|
||||
|
||||
---
|
||||
|
||||
### Frequency Calculation Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
frequencies = data['frequencies'] # cm⁻¹
|
||||
ir_intensities = data['ir_intensities'] # km/mol
|
||||
zpe = data['zpe'] # Hartree
|
||||
gibbs = data['gibbs_free_energy'] # Hartree
|
||||
|
||||
# Check for imaginary frequencies
|
||||
imaginary = [f for f in frequencies if f < 0]
|
||||
if imaginary:
|
||||
print(f"Warning: {len(imaginary)} imaginary frequencies")
|
||||
print("Structure may be a transition state or saddle point")
|
||||
else:
|
||||
print("Structure is a true minimum")
|
||||
|
||||
# Thermochemistry at 298 K
|
||||
print(f"ZPE: {zpe * 627.509:.2f} kcal/mol")
|
||||
print(f"Gibbs free energy: {gibbs:.6f} Hartree")
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- 0 imaginary frequencies = minimum
|
||||
- 1 imaginary frequency = transition state
|
||||
- >1 imaginary frequencies = higher-order saddle point
|
||||
|
||||
---
|
||||
|
||||
### Dihedral Scan Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
angles = data['angles'] # degrees
|
||||
energies = data['energies'] # Hartree
|
||||
|
||||
# Find barrier
|
||||
min_e = min(energies)
|
||||
max_e = max(energies)
|
||||
barrier = (max_e - min_e) * 627.509 # kcal/mol
|
||||
|
||||
print(f"Rotation barrier: {barrier:.2f} kcal/mol")
|
||||
|
||||
# Find minima
|
||||
import numpy as np
|
||||
rel_energies = [(e - min_e) * 627.509 for e in energies]
|
||||
for angle, e in zip(angles, rel_energies):
|
||||
if e < 0.5: # Near minimum
|
||||
print(f"Minimum at {angle}°")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docking Results
|
||||
|
||||
### Single Docking Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
# Docking score (more negative = better)
|
||||
score = data['docking_score'] # kcal/mol
|
||||
print(f"Docking score: {score:.2f} kcal/mol")
|
||||
|
||||
# All poses
|
||||
poses = data['poses']
|
||||
for i, pose in enumerate(poses):
|
||||
print(f"Pose {i}: score = {pose['score']:.2f} kcal/mol")
|
||||
|
||||
# Ligand strain
|
||||
strain = data.get('ligand_strain', 0)
|
||||
print(f"Ligand strain: {strain:.2f} kcal/mol")
|
||||
|
||||
# Download poses
|
||||
workflow.download_sdf_file("docked_poses.sdf")
|
||||
```
|
||||
|
||||
**Interpretation:**
|
||||
- Vina scores typically -12 to -6 kcal/mol for drug-like molecules
|
||||
- More negative = stronger predicted binding
|
||||
- Ligand strain > 3 kcal/mol suggests unlikely binding mode
|
||||
|
||||
---
|
||||
|
||||
### Batch Docking Results
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
results = data['results']
|
||||
for r in results:
|
||||
smiles = r['smiles']
|
||||
score = r['best_score']
|
||||
strain = r.get('ligand_strain', 0)
|
||||
print(f"{smiles[:30]}: score = {score:.2f}, strain = {strain:.2f}")
|
||||
|
||||
# Sort by score
|
||||
sorted_results = sorted(results, key=lambda x: x['best_score'])
|
||||
print("\nTop 10 hits:")
|
||||
for r in sorted_results[:10]:
|
||||
print(f"{r['smiles']}: {r['best_score']:.2f}")
|
||||
```
|
||||
|
||||
**Scoring Function Differences:**
|
||||
- **Vina**: Original scoring function
|
||||
- **Vinardo**: Updated parameters, often more accurate
|
||||
|
||||
---
|
||||
|
||||
## Cofolding Results
|
||||
|
||||
### Protein-Ligand Complex Prediction
|
||||
|
||||
```python
|
||||
data = workflow.data
|
||||
|
||||
# Confidence scores
|
||||
ptm = data['ptm_score'] # Predicted TM score (0-1)
|
||||
interface_ptm = data['interface_ptm'] # Interface confidence
|
||||
aggregate = data['aggregate_score'] # Combined score
|
||||
|
||||
print(f"Predicted TM score: {ptm:.3f}")
|
||||
print(f"Interface pTM: {interface_ptm:.3f}")
|
||||
print(f"Aggregate score: {aggregate:.3f}")
|
||||
|
||||
# Download structure
|
||||
pdb_content = data['structure_pdb']
|
||||
with open("complex.pdb", "w") as f:
|
||||
f.write(pdb_content)
|
||||
```
|
||||
|
||||
**Confidence Score Interpretation:**
|
||||
|
||||
| Score Range | Confidence | Recommendation |
|
||||
|-------------|------------|----------------|
|
||||
| > 0.8 | High | Likely accurate |
|
||||
| 0.5 - 0.8 | Moderate | Use with caution |
|
||||
| < 0.5 | Low | Validate experimentally |
|
||||
|
||||
---
|
||||
|
||||
### Interpreting Low Confidence
|
||||
|
||||
Low confidence may indicate:
|
||||
- Novel protein fold not well-represented in training data
|
||||
- Flexible or disordered regions
|
||||
- Unusual ligand (large, charged, or complex)
|
||||
- Multiple possible binding modes
|
||||
|
||||
**Recommendations for low confidence:**
|
||||
1. Try multiple models (Chai-1, Boltz-1, Boltz-2)
|
||||
2. Compare predictions across models
|
||||
3. Use docking for binding pose refinement
|
||||
4. Validate with experimental data if available
|
||||
|
||||
---
|
||||
|
||||
## Validation and Quality Assessment
|
||||
|
||||
### Cross-Validation with Multiple Methods
|
||||
|
||||
```python
|
||||
import rowan
|
||||
import stjames
|
||||
|
||||
mol = stjames.Molecule.from_smiles("c1ccccc1O")
|
||||
|
||||
# Run with different methods
|
||||
results = {}
|
||||
|
||||
for method in ['gfn2_xtb', 'aimnet2']:
|
||||
wf = rowan.submit_basic_calculation_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="optimization",
|
||||
workflow_data={"method": method},
|
||||
name=f"opt_{method}"
|
||||
)
|
||||
wf.wait_for_result()
|
||||
wf.fetch_latest(in_place=True)
|
||||
results[method] = wf.data['energy']
|
||||
|
||||
# Compare energies
|
||||
for method, energy in results.items():
|
||||
print(f"{method}: {energy:.6f} Hartree")
|
||||
```
|
||||
|
||||
### Consistency Checks
|
||||
|
||||
```python
|
||||
# For pKa
|
||||
def validate_pka(data):
|
||||
pka = data['strongest_acid']
|
||||
|
||||
# Check reasonable range
|
||||
if pka < -5 or pka > 20:
|
||||
print("Warning: pKa outside typical range")
|
||||
|
||||
# Compare with known references
|
||||
# (implementation depends on reference data)
|
||||
|
||||
# For docking
|
||||
def validate_docking(data):
|
||||
score = data['docking_score']
|
||||
strain = data.get('ligand_strain', 0)
|
||||
|
||||
if score > 0:
|
||||
print("Warning: Positive docking score suggests poor binding")
|
||||
|
||||
if strain > 5:
|
||||
print("Warning: High ligand strain - binding mode may be unrealistic")
|
||||
```
|
||||
|
||||
### Experimental Validation Guidelines
|
||||
|
||||
| Property | Validation Method |
|
||||
|----------|-------------------|
|
||||
| pKa | Potentiometric titration, UV spectroscopy |
|
||||
| Solubility | Shake-flask, nephelometry |
|
||||
| Docking pose | X-ray crystallography, cryo-EM |
|
||||
| Binding affinity | SPR, ITC, fluorescence polarization |
|
||||
| Cofolding | X-ray, NMR, HDX-MS |
|
||||
|
||||
---
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Issue: Workflow Failed
|
||||
|
||||
```python
|
||||
if workflow.status == "failed":
|
||||
print(f"Error: {workflow.error_message}")
|
||||
|
||||
# Common causes:
|
||||
# - Invalid SMILES
|
||||
# - Molecule too large
|
||||
# - Convergence failure
|
||||
# - Credit limit exceeded
|
||||
```
|
||||
|
||||
### Issue: Unexpected Results
|
||||
|
||||
1. **pKa off by >2 units**: Check tautomers, ensure correct protonation state
|
||||
2. **Docking gives positive scores**: Ligand may not fit binding site
|
||||
3. **Optimization not converged**: Try different starting geometry
|
||||
4. **High strain energy**: Conformer may be wrong
|
||||
|
||||
### Issue: Missing Data Fields
|
||||
|
||||
```python
|
||||
# Use .get() with defaults
|
||||
energy = data.get('energy', None)
|
||||
if energy is None:
|
||||
print("Energy not available")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Export Patterns
|
||||
|
||||
### Export to CSV
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
|
||||
# Collect results from multiple workflows
|
||||
results = []
|
||||
for wf in workflows:
|
||||
wf.fetch_latest(in_place=True)
|
||||
if wf.status == "completed":
|
||||
results.append({
|
||||
'name': wf.name,
|
||||
'pka': wf.data.get('strongest_acid'),
|
||||
'credits': wf.credits_charged
|
||||
})
|
||||
|
||||
df = pd.DataFrame(results)
|
||||
df.to_csv("results.csv", index=False)
|
||||
```
|
||||
|
||||
### Export Structures
|
||||
|
||||
```python
|
||||
# Download SDF with all poses
|
||||
workflow.download_sdf_file("poses.sdf")
|
||||
|
||||
# Download trajectory (for MD)
|
||||
workflow.download_dcd_files(output_dir="trajectories/")
|
||||
```
|
||||
591
references/workflow_types.md
Normal file
591
references/workflow_types.md
Normal file
@@ -0,0 +1,591 @@
|
||||
# Rowan Workflow Types Reference
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Property Prediction Workflows](#property-prediction-workflows)
|
||||
2. [Molecular Modeling Workflows](#molecular-modeling-workflows)
|
||||
3. [Protein-Ligand Workflows](#protein-ligand-workflows)
|
||||
4. [Spectroscopy Workflows](#spectroscopy-workflows)
|
||||
5. [Advanced Workflows](#advanced-workflows)
|
||||
|
||||
---
|
||||
|
||||
## Property Prediction Workflows
|
||||
|
||||
### pKa Calculation
|
||||
|
||||
Predict acid dissociation constants.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_pka_workflow(
|
||||
initial_molecule=mol,
|
||||
name="pKa calculation"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `strongest_acid`: pKa of most acidic proton
|
||||
- `strongest_base`: pKa of most basic site
|
||||
- `microscopic_pkas`: List of site-specific pKa values
|
||||
- `tautomer_populations`: Relative populations at pH 7
|
||||
|
||||
---
|
||||
|
||||
### Redox Potential
|
||||
|
||||
Calculate oxidation/reduction potentials.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_redox_potential_workflow(
|
||||
initial_molecule=mol,
|
||||
name="redox potential"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `oxidation_potential`: E° for oxidation (V vs SHE)
|
||||
- `reduction_potential`: E° for reduction (V vs SHE)
|
||||
|
||||
---
|
||||
|
||||
### Solubility Prediction
|
||||
|
||||
Predict aqueous and nonaqueous solubility.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_solubility_workflow(
|
||||
initial_molecule=mol,
|
||||
name="solubility"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `aqueous_solubility`: Log S in water
|
||||
- `solubility_class`: "High", "Medium", or "Low"
|
||||
|
||||
---
|
||||
|
||||
### Hydrogen-Bond Basicity
|
||||
|
||||
Calculate H-bond acceptor strength.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="hydrogen_bond_basicity",
|
||||
workflow_data={},
|
||||
name="H-bond basicity"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `hb_basicity`: pKBHX value
|
||||
|
||||
---
|
||||
|
||||
### Bond Dissociation Energy (BDE)
|
||||
|
||||
Calculate homolytic bond dissociation energies.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_bde_workflow(
|
||||
initial_molecule=mol,
|
||||
bond_indices=(0, 1), # Atom indices of bond
|
||||
name="BDE calculation"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `bde`: Bond dissociation energy (kcal/mol)
|
||||
- `radical_stability`: Stability of resulting radicals
|
||||
|
||||
---
|
||||
|
||||
### Fukui Indices
|
||||
|
||||
Calculate reactivity indices for nucleophilic/electrophilic attack.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_fukui_workflow(
|
||||
initial_molecule=mol,
|
||||
name="Fukui indices"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `fukui_plus`: Electrophilic attack susceptibility per atom
|
||||
- `fukui_minus`: Nucleophilic attack susceptibility per atom
|
||||
- `fukui_dual`: Dual descriptor per atom
|
||||
|
||||
---
|
||||
|
||||
### Spin States
|
||||
|
||||
Calculate relative energies of different spin multiplicities.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="spin_states",
|
||||
workflow_data={},
|
||||
name="spin states"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `spin_state_energies`: Energy of each multiplicity
|
||||
- `ground_state`: Lowest energy multiplicity
|
||||
|
||||
---
|
||||
|
||||
### ADME-Tox Predictions
|
||||
|
||||
Predict absorption, distribution, metabolism, excretion, and toxicity.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="admet",
|
||||
workflow_data={},
|
||||
name="ADMET"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- Various ADMET descriptors including:
|
||||
- `logP`, `logD`
|
||||
- `herg_inhibition`
|
||||
- `cyp_inhibition`
|
||||
- `bioavailability`
|
||||
- `bbb_permeability`
|
||||
|
||||
---
|
||||
|
||||
## Molecular Modeling Workflows
|
||||
|
||||
### Single-Point Energy
|
||||
|
||||
Calculate energy at fixed geometry.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_basic_calculation_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="single_point",
|
||||
name="single point"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `energy`: Total energy (Hartree)
|
||||
- `dipole`: Dipole moment vector
|
||||
- `mulliken_charges`: Atomic partial charges
|
||||
|
||||
---
|
||||
|
||||
### Geometry Optimization
|
||||
|
||||
Optimize molecular geometry to minimum energy.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_basic_calculation_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="optimization",
|
||||
name="optimization"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `final_molecule`: Optimized structure
|
||||
- `energy`: Final energy (Hartree)
|
||||
- `convergence`: Optimization details
|
||||
|
||||
---
|
||||
|
||||
### Vibrational Frequencies
|
||||
|
||||
Calculate IR/Raman frequencies and thermochemistry.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_basic_calculation_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="frequency",
|
||||
name="frequency"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `frequencies`: Vibrational frequencies (cm⁻¹)
|
||||
- `ir_intensities`: IR intensities
|
||||
- `zpe`: Zero-point energy
|
||||
- `thermal_corrections`: Enthalpy, entropy, Gibbs free energy
|
||||
- `imaginary_frequencies`: Count of negative frequencies
|
||||
|
||||
---
|
||||
|
||||
### Conformer Search
|
||||
|
||||
Generate and optimize conformer ensemble.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_conformer_search_workflow(
|
||||
initial_molecule=mol,
|
||||
name="conformer search"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `conformers`: List of conformer structures with energies
|
||||
- `lowest_energy_conformer`: Global minimum structure
|
||||
- `boltzmann_weights`: Population weights at 298 K
|
||||
|
||||
---
|
||||
|
||||
### Tautomer Search
|
||||
|
||||
Enumerate and rank tautomers.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_tautomer_search_workflow(
|
||||
initial_molecule=mol,
|
||||
name="tautomer search"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `tautomers`: List of tautomer structures
|
||||
- `energies`: Relative energies
|
||||
- `populations`: Boltzmann populations
|
||||
|
||||
---
|
||||
|
||||
### Dihedral Scan
|
||||
|
||||
Scan torsion angle energy surface.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_dihedral_scan_workflow(
|
||||
initial_molecule=mol,
|
||||
dihedral_indices=(0, 1, 2, 3), # Atom indices
|
||||
name="dihedral scan"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `angles`: Dihedral angles scanned (degrees)
|
||||
- `energies`: Energy at each angle
|
||||
- `barrier_height`: Rotation barrier (kcal/mol)
|
||||
|
||||
---
|
||||
|
||||
### Multistage Optimization
|
||||
|
||||
Progressive refinement with multiple methods.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="multistage_optimization",
|
||||
workflow_data={
|
||||
"stages": ["gfn2_xtb", "aimnet2", "dft"]
|
||||
},
|
||||
name="multistage opt"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `final_molecule`: Optimized structure
|
||||
- `stage_energies`: Energy after each stage
|
||||
|
||||
---
|
||||
|
||||
### Transition State Search
|
||||
|
||||
Find transition state geometry.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_ts_search_workflow(
|
||||
initial_molecule=mol, # Starting guess near TS
|
||||
name="TS search"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `ts_structure`: Transition state geometry
|
||||
- `imaginary_frequency`: Single imaginary frequency
|
||||
- `barrier_height`: Activation energy
|
||||
|
||||
---
|
||||
|
||||
### Strain Calculation
|
||||
|
||||
Calculate ligand strain energy.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="strain",
|
||||
workflow_data={},
|
||||
name="strain"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `strain_energy`: Conformational strain (kcal/mol)
|
||||
- `reference_energy`: Lowest energy conformer energy
|
||||
|
||||
---
|
||||
|
||||
### Orbital Calculation
|
||||
|
||||
Calculate molecular orbitals.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="orbitals",
|
||||
workflow_data={},
|
||||
name="orbitals"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `homo_energy`: HOMO energy (eV)
|
||||
- `lumo_energy`: LUMO energy (eV)
|
||||
- `homo_lumo_gap`: Band gap (eV)
|
||||
- `orbital_coefficients`: MO coefficients
|
||||
|
||||
---
|
||||
|
||||
## Protein-Ligand Workflows
|
||||
|
||||
### Docking
|
||||
|
||||
Dock ligand to protein binding site.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_docking_workflow(
|
||||
protein=protein_uuid,
|
||||
pocket={
|
||||
"center": [10.0, 20.0, 30.0],
|
||||
"size": [20.0, 20.0, 20.0]
|
||||
},
|
||||
initial_molecule=mol,
|
||||
executable="vina", # "vina" or "qvina2"
|
||||
scoring_function="vinardo", # "vina" or "vinardo"
|
||||
exhaustiveness=8,
|
||||
do_csearch=True, # Conformer search before docking
|
||||
do_optimization=True, # Optimize conformers
|
||||
do_pose_refinement=True, # Refine poses with QM
|
||||
name="docking"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `docking_score`: Best Vina score (kcal/mol)
|
||||
- `poses`: List of docked poses with scores
|
||||
- `ligand_strain`: Strain energy of bound conformer
|
||||
- `pose_sdf`: SDF file of poses
|
||||
|
||||
---
|
||||
|
||||
### Batch Docking
|
||||
|
||||
Screen multiple ligands against one target.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_batch_docking_workflow(
|
||||
protein=protein_uuid,
|
||||
pocket=pocket_dict,
|
||||
smiles_list=["CCO", "c1ccccc1", "CC(=O)O"],
|
||||
executable="qvina2",
|
||||
scoring_function="vina",
|
||||
name="batch docking"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `results`: List of docking results per ligand
|
||||
- `rankings`: Sorted by score
|
||||
|
||||
---
|
||||
|
||||
### Protein Cofolding
|
||||
|
||||
Predict protein-ligand complex structure using AI.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_protein_cofolding_workflow(
|
||||
initial_protein_sequences=["MSKGEELFT..."],
|
||||
initial_smiles_list=["CCO"],
|
||||
model="boltz_2", # "boltz_1x", "boltz_2", "chai_1r"
|
||||
use_msa_server=False, # Use MSA for better accuracy
|
||||
use_potentials=True, # Apply physical constraints
|
||||
compute_strain=False, # Calculate ligand strain
|
||||
do_pose_refinement=False,
|
||||
name="cofolding"
|
||||
)
|
||||
```
|
||||
|
||||
**Models:**
|
||||
- `chai_1r`: Chai-1 model (~2 min)
|
||||
- `boltz_1x`: Boltz-1 model (~2 min)
|
||||
- `boltz_2`: Boltz-2 model (latest, recommended)
|
||||
|
||||
**Output:**
|
||||
- `structure_pdb`: Predicted complex structure
|
||||
- `ptm_score`: Predicted TM score (0-1, higher = more confident)
|
||||
- `interface_ptm`: Interface prediction confidence
|
||||
- `aggregate_score`: Combined confidence metric
|
||||
- `ligand_rmsd`: If reference available
|
||||
|
||||
---
|
||||
|
||||
### Pose-Analysis MD
|
||||
|
||||
Molecular dynamics simulation of docked pose.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="pose_analysis_md",
|
||||
workflow_data={
|
||||
"protein_uuid": protein_uuid,
|
||||
"pose_sdf": pose_sdf_content
|
||||
},
|
||||
name="pose MD"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `trajectory`: MD trajectory file
|
||||
- `rmsd_over_time`: Ligand RMSD
|
||||
- `interactions`: Protein-ligand interactions
|
||||
|
||||
---
|
||||
|
||||
## Spectroscopy Workflows
|
||||
|
||||
### NMR Prediction
|
||||
|
||||
Predict NMR chemical shifts.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_nmr_workflow(
|
||||
initial_molecule=mol,
|
||||
name="NMR"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `h_shifts`: ¹H chemical shifts (ppm)
|
||||
- `c_shifts`: ¹³C chemical shifts (ppm)
|
||||
- `coupling_constants`: J-coupling values
|
||||
|
||||
---
|
||||
|
||||
### Ion Mobility
|
||||
|
||||
Predict collision cross-section for mass spectrometry.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_ion_mobility_workflow(
|
||||
initial_molecule=mol,
|
||||
name="ion mobility"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `ccs`: Collision cross-section (Ų)
|
||||
- `conformer_ccs`: CCS per conformer
|
||||
|
||||
---
|
||||
|
||||
## Advanced Workflows
|
||||
|
||||
### Molecular Descriptors
|
||||
|
||||
Calculate comprehensive descriptor set.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_descriptors_workflow(
|
||||
initial_molecule=mol,
|
||||
name="descriptors"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- 2D descriptors (RDKit-based)
|
||||
- 3D descriptors (xTB-based)
|
||||
- Electronic descriptors
|
||||
|
||||
---
|
||||
|
||||
### MSA (Multiple Sequence Alignment)
|
||||
|
||||
Generate MSA for protein sequences.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_msa_workflow(
|
||||
sequences=["MSKGEELFT..."],
|
||||
name="MSA"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `msa`: Multiple sequence alignment
|
||||
- `coverage`: Sequence coverage
|
||||
|
||||
---
|
||||
|
||||
### Protein Binder Design (BoltzGen)
|
||||
|
||||
Design protein binders.
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_workflow(
|
||||
workflow_type="protein_binder_design",
|
||||
workflow_data={
|
||||
"target_sequence": "MSKGEELFT...",
|
||||
"target_hotspots": [10, 15, 20]
|
||||
},
|
||||
name="binder design"
|
||||
)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `designed_sequences`: Binder sequences
|
||||
- `confidence_scores`: Per-design confidence
|
||||
|
||||
---
|
||||
|
||||
## Workflow Parameters Reference
|
||||
|
||||
### Common Parameters
|
||||
|
||||
All workflow submission functions accept:
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `name` | str | Workflow name (optional) |
|
||||
| `folder_uuid` | str | Organize in folder |
|
||||
| `max_credits` | float | Credit limit |
|
||||
|
||||
### Method Selection
|
||||
|
||||
For basic calculations, specify method:
|
||||
|
||||
```python
|
||||
workflow = rowan.submit_basic_calculation_workflow(
|
||||
initial_molecule=mol,
|
||||
workflow_type="optimization",
|
||||
workflow_data={
|
||||
"method": "gfn2_xtb", # or "aimnet2", "dft"
|
||||
"basis_set": "def2-SVP" # for DFT
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Available Methods:**
|
||||
- Neural network: `aimnet2`, `egret`
|
||||
- Semiempirical: `gfn1_xtb`, `gfn2_xtb`
|
||||
- DFT: `b3lyp`, `pbe`, `wb97x`
|
||||
Reference in New Issue
Block a user