Chemfiles

Read and write computational chemistry files

Chemfiles is a library providing a simple and format agnostic 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 many other formats using the same code.

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

Word cloud

Easy to use

Chemfiles focuses on simplicity, and has extensive documentation.

The API is built in an object-oriented fashion, with less than 10 classes publicly exposed.

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

  • Transparently read and write compressed files (.gz, .xz, and .bz2);
  • Powerfull atom selection language, including constrains on multiple atoms;
  • Automatic file type recognition;
  • Support non-constant number of atoms;
  • Orthorombic and tricliclinic periodic boundary conditions;
  • Use a custom unit cell or topology at runtime;
  • And many others ...

Open-source

Chemfiles is open-source under the 3 clauses BSD licence, hosted on Github, and open to your contributions!

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

Installation

conda-forge
Conda-forge logo
conda install -c conda-forge chemfiles
PyPi
PyPi logo
pip install chemfiles
Julia Pkg
Julia logo
Pkg.add("Chemfiles")
Cargo
Cargo logo
chemfiles = "0.9"
Linux distributions
Tux, the Linux penguin
See the documentation for the installation instruction with apt or yum.

Build from sources

latest release

Download and extract the latest release, and then run

cd chemfiles && mkdir build && cd build
cmake ..
cmake --build . --config Release --target install
master
git clone https://github.com/chemfiles/chemfiles
cd chemfiles && mkdir build && cd build
cmake ..
cmake --build . --config Release --target install

Usage examples

Here is how you can use chemfiles to get the position of atoms from a trajectory. 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.size() << " 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 <stdlib.h>
#include <chemfiles.h>

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

    chfl_trajectory_read(file, frame);

    uint64_t natoms = 0;
    chfl_vector3d* positions = 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) {
        chfl_vector3d* velocities = NULL;
        chfl_frame_velocities(frame, &velocities, &natoms);

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

    chfl_trajectory_close(file);
    chfl_free(frame);
    return EXIT_SUCCESS;
}
program example
    use chemfiles
    use iso_fortran_env, only: real64
    implicit none

    type(chfl_trajectory) :: file
    type(chfl_frame) :: frame
    real(real64), dimension(:, :), pointer :: positions, velocities

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

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

    positions => frame%positions()
    write(*, *) "There are", size(positions, 2), "atoms in the frame"

    ! Do awesome science here with the positions

    if (frame%has_velocities()) then
        velocities => frame%velocities()

        ! 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(len(frame.atoms)))
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.
use chemfiles::Trajectory;

fn main() -> Result<(), Box<std::error::Error>> {
    let file = Trajectory("filename.xyz", "r")?;

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

    // Do awesome science here with the positions

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

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

    return OK(());
}
using Chemfiles

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

println("There are $(size(frame)) 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