Chemfiles

A library for reading and writing trajectory files

Chemfiles provides a simple and unified interface for reading and writing computational chemistry files: trajectories, configurations, and topologies.

Format agnostic

Chemfiles provides a unique interface for all supported file formats. Read XYZ, PDB, NetCDF, TRJ and other formats with the exact same code.

Chemfiles supports both text (XYZ, PDB, …) and binary (GROMACS, NetCDF, …) formats.

Word cloud

Easy to use

Chemfiles is built in an object-oriented fashion, and the public interface consists of 5 classes only.

The interface focuses on simplicity, and has extensive documentation.

Multiple languages

Chemfiles is written in C++, but you can use it with all the major scientific languages:

C++ logo

C++

C logo

C

Fortran logo

Fortran

Python logo

Python 2 & 3

Rust logo

Rust

Julia logo

Julia

Principal features

  • VMD style atom selection language;
  • Automatic file type recognition;
  • Support a varying number of atoms;
  • Orthorombic and tricliclinic periodic boundary conditions;
  • Use a custom unit cell or topology at runtime;
  • And others ...

Open-source

Chemfiles is open-source under the MPL-v2 licence, hosted on Github, and open to your contributions!

Please report any bug or feature request as a Github issue.

Usage examples

Here is a small usage example for Chemfiles. More examples can be found in the documentation for each language.

#include <iostream>
#include <chemfiles.hpp>

int main() {
    chemfiles::Trajectory file("filename.xyz");

    auto frame = file.read();
    std::cout << "There are " << frame.natoms() << " atoms in the frame" << std::endl;
    auto positions = frame.positions();

    // Do awesome science here with the positions

    if (frame.velocities()) {
        auto velocities = *frame.velocities();

        // If the file contains information about the
        // velocities, you will find them here.
    }

    return 0;
}
#include <stdio.h>
#include <chemfiles.h>

int main() {
    CHFL_TRAJECTORY* file = chfl_open("filename.xyz", "r");
    CHFL_FRAME* frame = chfl_frame(0);

    if (file == NULL) {
        // Handle error
    }

    if (chfl_trajectory_read(file, frame)) {
        // Handle error
    }

    size_t natoms = 0;
    float (*positions)[3] = NULL;
    chfl_frame_positions(frame, &positions, &natoms);

    printf("There are %d atoms in the frame", natoms);

    // Do awesome science here with the positions

    bool has_velocities = false;
    chfl_frame_has_velocities(frame, &has_velocities);

    if (has_velocities) {
        float (*velocities)[3] = NULL;
        chfl_frame_velocities(frame, &velocities, &natoms);

        // If the file contains information about the
        // velocities, you will find them here.
    }
    return EXIT_SUCCESS;
}
program example
    use chemfiles
    use iso_fortran_env, only: real32, int64
    implicit none

    type(chfl_trajectory) :: file
    type(chfl_frame) :: frame
    real(real32), dimension(:, :), pointer :: positions, velocities
    integer(int64) :: natoms = 0
    logical :: has_velocities = .false.

    call file%open("filename.xyz", "r", status=status)
    if (status /= 0) stop

    call frame%init(0)
    call file%read(frame, status=status)
    if (status /= 0) stop

    call frame%positions(positions, natoms)
    write(*, *) "There are", natoms, "atoms in the frame"

    ! Do awesome science here with the positions

    call frame%has_velocities(has_velocities)
    if (has_velocities) then
        call frame%velocities(velocities, natoms)

        ! If the file contains information about the
        ! velocities, you will find them here.
    end if
end program
from chemfiles import Trajectory

file = Trajectory("filename.xyz")
frame = file.read()

print("There are {} atoms in the frame".format(frame.natoms()))
positions = frame.positions()

# Do awesome science here with the positions

if frame.has_velocities():
    velocities = frame.velocities()
    # If the file contains information about the
    # velocities, you will find them here.
extern crate chemfiles;
use self::chemfiles::Trajectory;

fn main() {
    let file = Trajectory("filename.xyz", "r").unwrap();

    let frame = file.read().unwrap();
    println!("There are {} atoms in the frame",  frame.natoms().unwrap());
    let positions = frame.positions().unwrap();

    // Do awesome science here with the positions

    if frame.has_velocities().unwrap() {
        let velocities = frame.velocities().unwrap();

        // If the file contains information about the
        // velocities, you will find them here.
    }
}
using Chemfiles

file = Trajectory("filename.xyz")
frame = read(file)

println("There are $(frame.natoms()) atoms in the frame")
pos = positions(frame);

# Do awesome science here with the positions

if has_velocities(frame)
    vel = velocities(frame)

    # If the file contains information about the
    # velocities, you will find them here.
end