dreid-forge 0.4.0

A pure Rust library and CLI that automates DREIDING force field parameterization by orchestrating structure repair, topology perception, and charge calculation for both biological and chemical systems.
Documentation
# DREID-Forge

**DREID-Forge** is a high-performance, pure-Rust library for automated DREIDING force field parameterization. It orchestrates atom typing, partial charge calculation, and potential energy function generation to produce simulation-ready inputs for both biological macromolecules and arbitrary chemical systems—all without leaving the Rust type system.

## Highlights

- **Automated atom typing** — assigns DREIDING atom types (e.g., `C_3`, `O_R`, `N_2`) based on element, hybridization, and local bonding environment via the `dreid-typer` crate.
- **Flexible charge assignment** — supports global QEq charge equilibration via `cheq`, or hybrid mode combining classical force field charges for biomolecules (AMBER/CHARMM) with QEq for ligands via `ffcharge`.
- **Embedded QEq for ligands** — polarizes ligand charges based on the surrounding protein electrostatic environment using efficient spatial indexing.
- **Comprehensive potential generation** — produces bond (harmonic/Morse), angle (cosine/theta-harmonic), torsion, inversion, van der Waals (LJ 12-6/Buckingham), and hydrogen bond potentials.
- **Format interoperability** — reads PDB, mmCIF, MOL2, and SDF structures with optional biomolecular preparation (cleaning, protonation, solvation); exports to BGF format.
- **Rust-first ergonomics** — no FFI, no global mutable state, edition 2024, and a carefully designed public API with comprehensive RustDoc documentation.

## Parameterization Pipeline at a Glance

```mermaid
flowchart LR
    Input[System] --> Intermediate[IntermediateSystem]
    Intermediate --> Typer[Atom Typing]
    Typer --> Charge[Charge Calculation]
    Charge --> ParamGen[Parameter Generation]
    ParamGen --> Output[ForgedSystem]
```

1. **Convert**`IntermediateSystem::from_system` builds neighbor lists and prepares bonds for physical order assignment.
2. **Type**`assign_atom_types` delegates to `dreid-typer` to assign DREIDING atom types and enumerate angles, torsions, and inversions.
3. **Charge**`assign_charges` computes partial charges using QEq (global or embedded) or classical force field parameters.
4. **Generate**`generate_parameters` produces all bonded and non-bonded potential parameters according to DREIDING rules.
5. **Output** — The resulting `ForgedSystem` is ready for export to BGF format.

## Quick Start

### For CLI Users

Install the latest DREID-Forge CLI binary from the [releases page](https://github.com/caltechmsc/dreid-forge/releases) or via `cargo`:

```bash
cargo install dreid-forge
```

Once the `dforge` binary is installed, you can parameterize a molecule in a single step:

```bash
dforge bio -i input.pdb -o output.bgf
```

Explore the complete parameterization pipeline and more options in the [user manual](MANUAL.md) and browse the [examples directory](https://github.com/caltechmsc/dreid-forge/tree/main/examples) for runnable walkthroughs.

### For Library Developers

DREID-Forge is also available as a library crate. Add it to your `Cargo.toml` dependencies:

```toml
[dependencies]
dreid-forge = "0.4.0"
```

#### Example: Parameterizing a Molecule

```rust
use dreid_forge::{Atom, Bond, BondOrder, Element, System};
use dreid_forge::{forge, ForgeConfig, ChargeMethod, QeqConfig, ForgeError};

fn main() -> Result<(), ForgeError> {
    // Build a water molecule
    let mut system = System::new();
    system.atoms.push(Atom::new(Element::O, [0.0, 0.0, 0.0]));
    system.atoms.push(Atom::new(Element::H, [0.9575, 0.0, 0.0]));
    system.atoms.push(Atom::new(Element::H, [-0.2399, 0.9272, 0.0]));
    system.bonds.push(Bond::new(0, 1, BondOrder::Single));
    system.bonds.push(Bond::new(0, 2, BondOrder::Single));

    // Parameterize with QEq charges
    let config = ForgeConfig {
        charge_method: ChargeMethod::Qeq(QeqConfig::default()),
        ..Default::default()
    };
    let forged = forge(&system, &config)?;

    // Inspect results
    println!("Atom types: {:?}", forged.atom_types);
    println!("Bonds: {}", forged.potentials.bonds.len());
    println!("Angles: {}", forged.potentials.angles.len());

    // Oxygen should be negatively charged, hydrogens positive
    assert!(forged.atom_properties[0].charge < 0.0);
    assert!(forged.atom_properties[1].charge > 0.0);

    Ok(())
}
```

#### Example: Reading PDB and Writing BGF

```rust
use std::fs::File;
use std::io::{BufReader, BufWriter};

use dreid_forge::{forge, ForgeConfig};
use dreid_forge::io::{BioReader, Format, CleanConfig, ProtonationConfig, write_bgf};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Read and prepare a PDB structure
    let file = File::open("protein.pdb")?;
    let system = BioReader::new(BufReader::new(file), Format::Pdb)
        .clean(CleanConfig { remove_water: true, remove_ions: true, ..Default::default() })
        .protonate(ProtonationConfig::default())
        .read()?;

    // Parameterize with DREIDING force field
    let forged = forge(&system, &ForgeConfig::default())?;

    // Write BGF file
    let mut output = BufWriter::new(File::create("system.bgf")?);
    write_bgf(&mut output, &forged)?;

    Ok(())
}
```

#### Example: Hybrid Charges for Protein-Ligand Systems

```rust
use std::fs::File;
use std::io::BufReader;

use dreid_forge::{forge, ForgeConfig, ForgeError};
use dreid_forge::{ChargeMethod, HybridConfig, LigandChargeConfig, LigandQeqMethod};
use dreid_forge::{ResidueSelector, EmbeddedQeqConfig, QeqConfig};
use dreid_forge::io::{BioReader, Format, ProtonationConfig, TopologyConfig};

fn main() -> Result<(), ForgeError> {
    // Read a protein-ligand complex
    let file = File::open("complex.pdb").unwrap();
    let system = BioReader::new(BufReader::new(file), Format::Pdb)
        .protonate(ProtonationConfig { target_ph: Some(7.4), ..Default::default() })
        .topology(TopologyConfig::default())
        .read()
        .unwrap();

    // Configure hybrid charges:
    // - Protein: AMBER ff99SB charges
    // - Ligand at chain A, residue 500: embedded QEq (polarized by protein)
    let config = ForgeConfig {
        charge_method: ChargeMethod::Hybrid(HybridConfig {
            ligand_configs: vec![
                LigandChargeConfig {
                    selector: ResidueSelector::new("A", 500, None),
                    method: LigandQeqMethod::Embedded(EmbeddedQeqConfig {
                        cutoff_radius: 12.0,  // Include protein atoms within 12 Å
                        qeq: QeqConfig::default(),
                    }),
                },
            ],
            ..Default::default()
        }),
        ..Default::default()
    };

    let forged = forge(&system, &config)?;

    // Protein atoms have classical AMBER charges
    // Ligand atoms have QEq charges polarized by protein environment
    println!("Total atoms: {}", forged.atom_properties.len());

    Ok(())
}
```

> **Tip**: For small molecules without biological context, use `ChemReader` with MOL2 or SDF formats instead.

For detailed usage instructions and configuration options, refer to the [API Documentation](https://docs.rs/dreid-forge).

## Documentation

- [CLI User Manual]MANUAL.md — detailed explanation of command-line usage and options.
- [API Documentation]https://docs.rs/dreid-forge — comprehensive reference for all public types and functions.
- [Architecture Overview]ARCHITECTURE.md — detailed explanation of the internal design, algorithms, and data flow.

## Dependencies

`dreid-forge` builds on several specialized crates:

| Crate                                                   | Purpose                                                                         |
| ------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`dreid-typer`]https://crates.io/crates/dreid-typer   | DREIDING atom type assignment and topology enumeration                          |
| [`cheq`]https://crates.io/crates/cheq                 | Charge equilibration (QEq) solver with embedded field support                   |
| [`ffcharge`]https://crates.io/crates/ffcharge         | Classical force field charges for proteins, nucleic acids, water, and ions      |
| [`dreid-kernel`]https://crates.io/crates/dreid-kernel | Stateless DREIDING energy/force kernels with precomputed parameters             |
| [`bio-forge`]https://crates.io/crates/bio-forge       | Biomolecular structure preparation (cleaning, protonation, solvation, topology) |

## License

This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.