22 unstable releases (9 breaking)

new 0.10.0-dev.2 Jan 13, 2025
0.9.0 Dec 6, 2024
0.9.0-dev.2 Nov 23, 2024
0.8.1 Jun 23, 2024
0.5.0 Nov 24, 2023

#292 in Science

Download history 23/week @ 2024-09-18 46/week @ 2024-09-25 17/week @ 2024-10-02 1/week @ 2024-10-09 1/week @ 2024-10-30 1/week @ 2024-11-06 92/week @ 2024-11-20 34/week @ 2024-11-27 360/week @ 2024-12-04 196/week @ 2024-12-11 44/week @ 2024-12-18 2/week @ 2024-12-25 181/week @ 2025-01-01

513 downloads per month
Used in 2 crates

MIT license

1.5MB
34K SLoC

groan_rs: Gromacs Analysis Library for Rust

Rust library for analyzing Gromacs simulations.

While the library is no longer in an early stage of development, it is still unstable. Breaking changes can appear in any new version.

Usage

Run

$ cargo add groan_rs

Import the crate in your Rust code:

use groan_rs::prelude::*;

License

This library is released under the MIT License.

Full documentation

For full documentation see the corresponding docs.rs page.


lib.rs:

groan_rs: Gromacs Analysis Library for Rust

Rust library for analyzing Gromacs simulations.

While the library is no longer in an early stage of development, it is still unstable. Breaking changes can appear in any new version.

What it can do

What it CAN'T do (at the moment)

  • Work with non-orthogonal periodic boundary conditions.
  • Perform advanced analyses of structure and dynamics out of the box. (But groan_rs library tries to make it simple to implement your own!)

Usage

Run

$ cargo add groan_rs

Import the crate in your Rust code:

use groan_rs::prelude::*;

Examples

Analyzing structure files

You can read structure files in various formats (GRO, PDB, PQR, TPR), add groups from NDX files, and perform analyses.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    // read a structure file (in GRO, PDB, PQR, or TPR format)
    let mut system = System::from_file("system.gro")?;

    // read an NDX file
    // NDX groups will be automatically created inside `system`
    system.read_ndx("index.ndx")?;

    // calculate the center of geometry of a protein
    // 'Protein' is the name of a group from the NDX file
    let center = system.group_get_center("Protein")?;

    // print the result
    println!("{:?}", center);

    Ok(())
}

Selecting atoms

You can select atoms using a query language similar to VMD.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let system = System::from_file("system.gro")?;

    // select some atoms using the groan selection language and iterate through them
    for atom in system.selection_iter("serial 1-23 or (resname POPC and name P)")? {
        // perform some operation with the atom
    }

    // you can temporarily store the selection iterator in a variable
    // see the `@protein` query? => groan can autodetect common structures
    // like atoms of membrane lipids or proteins
    let iterator = system.selection_iter("@protein")?;

    Ok(())
}

Creating groups

You can select atoms and save them into a group. This group is stored inside the system and can be quickly accessed multiple times.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let mut system = System::from_file("system.gro")?;

    // select atoms and store them into a group 'Selected'
    system.group_create("Selected", "serial 1-23 or (resname POPC and name P)")?;

    // iterate through the selected atoms
    for atom in system.group_iter("Selected")? {
        // perform some operation with the atom
    }

    // use the previously created group to construct another group
    system.group_create("Some Atoms", "Selected || resid 87 to 124")?;

    // modify the atoms in the group 'Some Atoms'
    for atom in system.group_iter_mut("Some Atoms")? {
        atom.set_residue_name("RES");
    }

    // each system always contains two groups called 'all' and 'All'
    // these groups contain all the atoms in the system
    assert!(system.group_exists("all"));
    assert!(system.group_exists("All"));

    Ok(())
}

Writing output structure files

You can write structure files in GRO, PDB, or PQR format.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let mut system = System::from_file("system.gro")?;

    // write the entire system as a PDB file
    system.write_pdb("system.pdb", false)?;

    // write only DNA atoms as a GRO file
    system.group_create("DNA", "@dna")?;
    system.group_write_gro("DNA", "dna.gro", false)?;

    Ok(())
}

Geometry filtering of atoms

You can select atoms based on geometric conditions.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    // when reading a TPR file, you get information about
    // the masses of atoms and connectivity between atoms
    let mut system = System::from_file("system.tpr")?;

    // load groups into the system
    system.read_ndx("index.ndx")?;

    // get the center of mass of the group 'Protein'
    let protein_com = system.group_get_com("Protein")?;

    // construct a cylinder with its base in the protein center of mass,
    // a radius of 2 nm, height of 4 nm, and oriented along the z-axis
    let cylinder = Cylinder::new(protein_com, 2.0, 4.0, Dimension::Z);

    // iterate over atoms of water molecules located inside the cylinder
    for atom in system.group_iter("Water")?.filter_geometry(cylinder) {
        // perform some operation with the atom
    }

    Ok(())
}

Analyzing trajectory files

You can read trajectory files in XTC, TRR, or GRO format.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let mut system = System::from_file("system.gro")?;

    // load groups into the system
    system.read_ndx("index.ndx")?;

    for frame in system.xtc_iter("trajectory.xtc")? {
        // check that the frame has been read correctly
        let frame = frame?;

        // calculate distance between two groups of atoms
        let distance = frame.group_distance("Protein1", "Protein2", Dimension::XYZ)?;
    }

    Ok(())
}

You can also read only part of the trajectory file and/or skip some trajectory frames. You can concatenate trajectory files and print the progress of any trajectory iteration.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let mut system = System::from_file("system.gro")?;

    // read multiple trajectory files with additional options
    for frame in system
        .xtc_cat_iter(&["md1.xtc", "md2.xtc", "md3.xtc"])?
        .with_range(50_000.0, 225_000.0)? // start at 50 ns, end at 225 ns
        .with_step(3)?                    // read every 3rd step
        .print_progress(ProgressPrinter::default()) {

        // check that the frame has been read correctly
        let frame = frame?;

        // continue working with the frame
    }

    Ok(())
}

Calculating RMSD

You can calculate RMSD for two systems or for entire trajectories.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let mut system = System::from_file("system.gro")?;
    let system2 = System::from_file("system2.gro")?;

    // calculate RMSD between all atoms of `system` and `system2`
    let rmsd = system.calc_rmsd(&system2, "all")?;

    // calculate RMSD for an entire trajectory
    let reference = system.clone();
    for frame_data in system.xtc_iter("trajectory.xtc")?.calc_rmsd(&reference, "all")? {
        let (frame, rmsd) = frame_data?;

        println!("{}: {}", frame.get_simulation_time(), rmsd);
    }

    Ok(())
}

Writing trajectory files

You can not only read but also write trajectory files in XTC, TRR, or GRO format.

use groan_rs::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let mut system = System::from_file("system.gro")?;

    // open an XTC file as output trajectory file
    system.xtc_writer_init("trajectory.xtc")?;

    // read frames from a TRR trajectory and write them in an XTC format
    for frame in system.trr_iter("trajectory.trr")? {
        let frame = frame?;

        // write the frame into all open trajectory files associated with the system
        frame.traj_write_frame()?;
    }

    Ok(())
}

Selecting atoms using GSL

Groan selection language (GSL) is a query language for selecting atoms in the groan_rs library. In general, GSL is similar to the selection language used by VMD. To understand the capabilities (and limitations) of the language, read this guide.

Error handling

Proper error handling and propagation is at heart of the groan_rs library. The individual error types provided by the groan_rs are however not exported into the prelude module.

If you want to use specific error type from the groan_rs library, you will have to include it explicitly from the errors module. For instance, if you want to directly work with errors that can occur when writing a pdb file, use:

use groan_rs::errors::WritePdbError;

Note that groan_rs will still work correctly even if you do not explicitly include the error types.

Features

Default

  • molly: Blazingly Fast Reading of XTC Files
    • Enables the use of the molly crate for very fast reading of xtc files.
    • Enables the use of GroupXtcReader for partial reading of XTC frames.
    • This feature is enabled by default.
    • If disabled, xdrfile library will be used instead to read XTC files and partial reading of XTC frames will not be supported.

Additional

  • serde: Serialization Support

    • Enables the serialization and deserialization of groan_rs data structures through integration with the serde framework.
  • parallel: Concurrency

    • Expands the groan_rs library with functions designed for multi-threaded execution.
  • no-xdrfile: Pure Rust experience with no external C libraries

    • Removes the compilation and use of xdrfile library.
    • If enabled, you will lose the ability to write XTC files and both read and write TRR files.

Install the groan_rs crate with a specific feature using cargo add groan_rs --features [FEATURE].

Limitations

  • Currently, groan_rs library is not able to properly work with periodic simulation boxes that are not orthogonal. While it can read structures and trajectories with non-orthogonal boxes, calculated distances and similar properties may be incorrect! Tread very carefully!

  • While groan_rs can read double-precision trr and tpr files, it uses single-precision floating point numbers everywhere in its code. If you require double-precision for your analyses, look elsewhere.

License

This library is released under the MIT License.

Dependencies

~16–25MB
~412K SLoC