Commit fd638cbd by root

init

parents
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
# The build dir
build/*
# Generated folders
docs/html/*
examples/out/*
examples/out_json_ref/*
[submodule "Catch2"]
path = submodules/Catch2
url = https://github.com/catchorg/Catch2
[submodule "msgpack-c"]
path = submodules/msgpack-c
url = https://github.com/msgpack/msgpack-c
[submodule "mmtf_spec"]
path = submodules/mmtf_spec
url = https://github.com/rcsb/mmtf
language: cpp
sudo: false
dist: trusty
linux64_addons:
addons: &linux64
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
linux32_addons:
addons: &linux32
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- g++-4.8-multilib
- linux-libc-dev:i386
- libc6-dev-i386
linux64_cpp17addons:
addons: &linux64cpp17
apt:
sources:
- ubuntu-toolchain-r-test
# Set empty values for allow_failures to work
env: TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
matrix:
fast_finish: true
include:
- os: linux
env: EMSCRIPTEN=ON TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
addons: *linux64
- os: linux
compiler: clang
addons: *linux64
- os: linux
compiler: gcc
env: ARCH=x86 CMAKE_EXTRA=-DHAVE_LIBM=/lib32/libm.so.6 TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
addons: *linux32
- os: osx
compiler: clang
- os: linux
compiler: gcc
env: CMAKE_EXTRA="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS='-march=native'" TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
addons: *linux64cpp17
dist: bionic
- os: linux
compiler: gcc
addons: *linux64cpp17
dist: bionic
before_install:
# Setting environement
- cd $TRAVIS_BUILD_DIR
- source ci/setup-travis.sh
- $CC --version
- $CXX --version
script:
- echo $TEST_COMMAND
- (eval "$TEST_COMMAND")
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
## v1.1.0 - 2022-10-03
### Added
- New mapDecoderFrom.. functions to decode only part of an MMTF file
- Support for extra fields in MMTF files according to the
[latest MMTF specification](https://github.com/rcsb/mmtf/pull/36).
- Support for binary strategy 16 (Run-length encoded 8-bit array),
bondResonanceList field and optional groupType.bondAtomList &
groupType.bondOrderList according to the proposed version 1.1 of the
[MMTF specification](https://github.com/rcsb/mmtf/pull/35).
- New methods to find polymer chains and HETATM following discussions in
[rcsb/mmtf#28](https://github.com/rcsb/mmtf/issues/28).
- Altered submodule locations [rcsb/mmtf-cpp#37](https://github.com/rcsb/mmtf-cpp/pull/37)
from the base directory to the new submodules directory.
## v1.0.0 - 2019-02-05
### Added
- Initial release including decoder and encoder for the
[MMTF specification 1.0](https://github.com/rcsb/mmtf/blob/v1.0/spec.md).
[Unreleased]: https://github.com/rcsb/mmtf-cpp/compare/v1.1.0...HEAD
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(mmtf-cpp VERSION 1.0.0 LANGUAGES CXX)
option(mmtf_build_local "Use the submodule dependencies for building" OFF)
option(mmtf_build_examples "Build the examples" OFF)
add_library(MMTFcpp INTERFACE)
target_compile_features(MMTFcpp INTERFACE cxx_auto_type)
target_include_directories(MMTFcpp INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
if (mmtf_build_local)
# use header only
set(MSGPACKC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/submodules/msgpack-c/include)
add_library(msgpackc INTERFACE)
target_include_directories(msgpackc INTERFACE ${MSGPACKC_INCLUDE_DIR})
if (BUILD_TESTS)
set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/submodules/Catch2/single_include)
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
endif()
endif()
if (NOT TARGET msgpackc)
find_package(msgpack)
endif()
target_link_libraries(MMTFcpp INTERFACE msgpackc)
if (BUILD_TESTS)
enable_testing()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
endif()
if (mmtf_build_examples)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/examples)
endif()
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION "include"
FILES_MATCHING PATTERN "*.hpp")
The MIT license applies to all files unless otherwise noted.
Copyright 2017, University of California San Diego
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<!--- Batch image URLs generated at https://shields.io -->
[![Release](https://img.shields.io/github/v/release/rcsb/mmtf-cpp)](https://github.com/rcsb/mmtf-cpp/releases)
[![License](https://img.shields.io/github/license/rcsb/mmtf-cpp)](https://github.com/rcsb/mmtf-cpp/blob/master/LICENSE)
[![Build Status (Travis)](https://img.shields.io/travis/com/rcsb/mmtf-cpp/master)](https://app.travis-ci.com/github/rcsb/mmtf-cpp)
The <b>m</b>acro<b>m</b>olecular <b>t</b>ransmission <b>f</b>ormat
([MMTF](http://mmtf.rcsb.org)) is a binary encoding of biological structures.
This repository holds the C++-03 compatible API, encoding and decoding
libraries. The MMTF specification can be found
[here](https://github.com/rcsb/mmtf/blob/HEAD/spec.md/).
## Prerequisites for using MMTF in C++
You need the headers of the MessagePack C++ library (version 2.1.5 or newer).
If you do not have them on your machine already, you can download the "include"
directory from the
[MessagePack GitHub repository](https://github.com/msgpack/msgpack-c).
## How to use MMTF
You only need to include the mmtf.hpp header in your code to use MMTF.
For instance a minimal example to load an MMTF file looks as follows:
```C
#include <mmtf.hpp>
int main(int argc, char** argv) {
mmtf::StructureData data;
mmtf::decodeFromFile(data, "test.mmtf");
return 0;
}
```
The C++ MMTF library is header only so you do not need to compile it. If you
have a source file named `demo.cpp` (e.g. including the code above), you can
generate an executable `demo.exe` as follows:
```bash
g++ -I<MSGPACK_INCLUDE_PATH> -I<MMTF_INCLUDE_PATH> demo.cpp -o demo.exe
```
Here, `<MSGPACK_INCLUDE_PATH>` and `<MMTF_INCLUDE_PATH>` are the paths to the
"include" directories of MessagePack and this library respectively.
For your more complicated projects, a `CMakeLists.txt` is included for you.
## Installation
You can also perform a system wide installation with `cmake` and `ninja` (or `make`).
To do so:
```bash
mkdir build
cd build
cmake -G Ninja ..
sudo ninja install
```
`cmake` automatically sets the installation directory to `/usr/local/include`, if you want to install it to another `*include/` directory
run `cmake` with the command:
```bash
cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/home/me/local ..
```
Be aware that `/include` is added to the end of `DCMAKE_INSTALL_PREFIX` and that is where your files are installed (i.e. the above would install at `/home/me/local/include/`).
## Examples and tests
To build the tests + examples we recommend using the following lines:
```bash
# download Catch2 testing framework, msgpack-c, and the mmtf-spec test-dataset
git submodule update --init --recursive
mkdir build
cd build
cmake -G Ninja -DBUILD_TESTS=ON -Dmmtf_build_local=ON -Dmmtf_build_examples=ON ..
ninja
chmod +x ./tests/mmtf_tests
./tests/mmtf_tests
```
Example codes:
- mmtf_demo.cpp: Loads an MMTF file and checks internal consistency using
mmtf::StructureData::hasConsistentData.
```bash
./examples/mmtf_demo ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf
```
- traverse.cpp: Loads an MMTF file and dumps it in human-readable forms.
```bash
./examples/traverse ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf
./examples/traverse ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf json
./examples/traverse ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf print
```
- print_as_pdb.cpp: Loads an MMTF file and prints it in pdb format.
```bash
./examples/print_as_pdb ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf
```
## Benchmark
Using the following simple code:
```cpp
#include <mmtf.hpp>
int main(int argc, char** argv)
{
for (int i=1; i<argc; ++i) {
mmtf::StructureData sd;
mmtf::decodeFromFile(sd, argv[i]);
}
}
```
compiled via:
```
g++ -Ofast -Immtf/include -Imsgpack/include decode_all_mmtf.cpp
```
We are able to load 153,987 mmtf files (current size of the pdb) or 14.3GB from an SSD in 211.3 seconds (averaged over 4 runs with minimal differences between the runs).
## Code documentation
You can generate a [doxygen](http://www.doxygen.org) based documentation of the
library by calling `doxygen` in the docs folder. You will need doxygen 1.8.11 or
later for that. Open `docs/html/index.html` to see the generated documentation.
version: "{build}"
os: Visual Studio 2015
environment:
matrix:
- generator: MinGW Makefiles
CXX_PATH: 'C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin'
ARCH: x64
- generator: MinGW Makefiles
CXX_PATH: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin'
ARCH: x86
- generator: Visual Studio 14 2015 Win64
ARCH: x64
- generator: Visual Studio 14 2015
ARCH: x86
clone_folder: c:\mmtf-cpp
# Uncomment the following lines to enable remote desktop access to Appveyor
# after a failed build.
# init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
# on_failure:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
install:
- git submodule update --init --recursive
- ps: . .\ci\setup-appveyor.ps1
build_script:
- cd C:\mmtf-cpp
- mkdir build
- cd build
- ps: echo $env:CMAKE_ARGUMENTS
- cmake %CMAKE_ARGUMENTS% ..
- cmake --build . --config Debug -- %BUILD_ARGUMENTS%
test_script:
- ctest --build-config Debug --timeout 300 --output-on-failure
set -e
cd $TRAVIS_BUILD_DIR
mkdir build && cd build
$CMAKE_CONFIGURE cmake $CMAKE_ARGS $CMAKE_EXTRA ..
make -j2
ctest -j2 --output-on-failure
bash $TRAVIS_BUILD_DIR/ci/travis-test-example.sh
cd $TRAVIS_BUILD_DIR
if ("$env:CXX_PATH" -ne "") {
$env:PATH += ";$env:CXX_PATH"
}
$env:CMAKE_ARGUMENTS = "-G `"$env:generator`""
$env:CMAKE_ARGUMENTS += " -Dmmtf_build_local=ON"
$env:CMAKE_ARGUMENTS += " -DBUILD_TESTS=ON"
if ($env:generator -Match "Visual Studio") {
$env:BUILD_ARGUMENTS="/verbosity:minimal /m:2"
} else {
$env:BUILD_ARGUMENTS="-j2"
}
if ($env:generator -eq "MinGW Makefiles") {
# Remove sh.exe from git in the PATH for MinGW to work
$env:PATH = ($env:PATH.Split(';') | Where-Object { $_ -ne 'C:\Program Files\Git\usr\bin' }) -join ';'
}
#!/bin/bash
export CMAKE_ARGS="-DCMAKE_BUILD_TYPE=debug -DBUILD_TESTS=ON -Dmmtf_build_local=ON"
if [[ "$EMSCRIPTEN" == "ON" ]]; then
# Install a Travis compatible emscripten SDK
wget https://github.com/chemfiles/emscripten-sdk/archive/master.tar.gz
tar xf master.tar.gz
./emscripten-sdk-master/emsdk activate
source ./emscripten-sdk-master/emsdk_env.sh
export CMAKE_CONFIGURE='emcmake'
export CMAKE_ARGS="$CMAKE_ARGS -DTEST_RUNNER=node -DCMAKE_BUILD_TYPE=release"
# Install a modern cmake
cd $HOME
wget https://cmake.org/files/v3.9/cmake-3.9.3-Linux-x86_64.tar.gz
tar xf cmake-3.9.3-Linux-x86_64.tar.gz
export PATH=$HOME/cmake-3.9.3-Linux-x86_64/bin:$PATH
export CC=emcc
export CXX=em++
return
fi
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
if [[ "$TRAVIS_DIST" == "trusty" ]]; then
if [[ "$CC" == "gcc" ]]; then
export CC=gcc-4.8
export CXX=g++-4.8
fi
fi
if [[ "$TRAVIS_DIST" == "bionic" ]]; then
if [[ "$CC" == "gcc" ]]; then
export CC=gcc-7
export CXX=g++-7
fi
fi
fi
if [[ "$ARCH" == "x86" ]]; then
export CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_C_FLAGS=-m32"
fi
#!/bin/bash
# Test compilation of example code using C++03 if possible
# -> only expected to work in Linux or Mac with CXX set to g++ or clang++
# -> expects TRAVIS_BUILD_DIR, EMSCRIPTEN, CXX to be set
# abort on error and exit with proper exit code
set -e
# test example
cd $TRAVIS_BUILD_DIR/examples
if [ -z "$EMSCRIPTEN" ]; then
# Compile with C++03 forced
$CXX -I"../submodules/msgpack-c/include" -I"../include" -std=c++03 -O2 \
-o read_and_write read_and_write.cpp
./read_and_write ../submodules/mmtf_spec/test-suite/mmtf/3NJW.mmtf test.mmtf
else
# Cannot do C++03 here and need to embed input file for running it with node
cp ../submodules/mmtf_spec/test-suite/mmtf/3NJW.mmtf .
$CXX -I"../submodules/msgpack-c/include" -I"../include" -O2 \
-o read_and_write.js read_and_write.cpp --embed-file 3NJW.mmtf
node read_and_write.js 3NJW.mmtf test.mmtf
fi
This source diff could not be displayed because it is too large. You can view the blob instead.
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
SET(executables mmtf_demo traverse print_as_pdb tableexport read_and_write)
foreach(exe ${executables})
add_executable(${exe} ${exe}.cpp)
target_compile_features(${exe} PRIVATE cxx_auto_type)
if(WIN32)
target_link_libraries(${exe} MMTFcpp ws2_32)
else()
target_link_libraries(${exe} MMTFcpp)
endif()
endforeach(exe)
#!/bin/bash
if [ "$3" == "" ]; then
echo "USAGE: compile_and_run.sh <MSGPACK_INCLUDE_PATH> <MAIN_FILE> <MMTF_FILE>"
echo "-> for MAIN_FILE = test.cpp, we compile and run test.exe <MMTF_FILE>"
exit 1
fi
MAIN_FILENAME="${2%.*}"
./compile_target.sh $1 $MAIN_FILENAME.cpp &&
./$MAIN_FILENAME.exe $3
#!/bin/bash
if [ "$3" == "" ]; then
echo "USAGE: compile_read_and_write.sh <MSGPACK_INCLUDE_PATH> <MMTF_FILE_IN> <MMTF_FILE_OUT>"
echo "-> read <MMTF_FILE_IN> and write as <MMTF_FILE_OUT>"
exit 1
fi
./compile_target.sh $1 read_and_write.cpp &&
./read_and_write.exe $2 $3
#!/bin/bash
if [ "$2" == "" ]; then
echo "USAGE: compile_target.sh <MSGPACK_INCLUDE_PATH> <MAIN_FILE>"
echo "-> for MAIN_FILE = test.cpp, this produces executable test.exe"
exit 1
fi
MAIN_FILENAME="${2%.*}"
g++ -I$1 -I"../include" -O2 -o $MAIN_FILENAME.exe $MAIN_FILENAME.cpp
#include <mmtf.hpp>
#include <iostream>
#include <string>
int main(int argc, char** argv) {
// check arguments
if (argc < 2) {
printf("USAGE: mmtf_demo <mmtffile>\n");
return 1;
}
// decode MMTF file
std::string filename(argv[1]);
mmtf::StructureData data;
mmtf::decodeFromFile(data, filename);
// check if the data is self-consistent
if (data.hasConsistentData(true)) {
std::cout << "Successfully read " << filename << ".\n";
return 0;
} else {
std::cout << "Inconsistent data in " << filename << ".\n";
return 1;
}
}
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code is Daniel Farrell
//
// NOTE: This wasn't made to be a well tested error-free executable... More
// of an example of how you might iterate over an mmtf file in pdb style.
// Please DO NOT USE THIS IN PRODUCTION.
// *************************************************************************
#include <mmtf.hpp>
#include <iostream>
#include <string>
std::string print_sd_as_pdb(mmtf::StructureData const & sd, bool index_at_0) {
std::ostringstream out;
int modelIndex = 0;
int chainIndex = 0;
int groupIndex = 0;
int atomIndex = 0;
//# traverse models
for (int i = 0; i < sd.numModels; i++, modelIndex++) {
// # traverse chains
for (int j = 0; j < sd.chainsPerModel[modelIndex]; j++, chainIndex++) {
// # traverse groups
for (int k = 0; k < sd.groupsPerChain[chainIndex]; k++, groupIndex++) {
const mmtf::GroupType& group =
sd.groupList[sd.groupTypeList[groupIndex]];
int groupAtomCount = group.atomNameList.size();
for (int l = 0; l < groupAtomCount; l++, atomIndex++) {
// ATOM or HETATM
if (mmtf::is_hetatm(chainIndex, sd.entityList, group))
out << "HETATM";
else
out << "ATOM ";
// Atom serial
if (index_at_0 || mmtf::isDefaultValue(sd.atomIdList)) {
out << std::setfill(' ') << std::internal << std::setw(5) <<
std::right << atomIndex+1;
} else {
out << std::setfill(' ') << std::internal << std::setw(5) <<
std::right << sd.atomIdList[atomIndex] << " ";
}
// Atom name
out << std::left << std::setw(4) << std::setfill(' ') << group.atomNameList[l];
// Group name
out << group.groupName << " ";
// Chain
out << sd.chainIdList[chainIndex];
// Group serial
out << std::setfill(' ') << std::right << std::setw(4) << sd.groupIdList[groupIndex];
out << " ";
// x, y, z
out << std::setfill(' ') << std::fixed << std::setprecision(3) << std::setw(8) << std::right;
out << sd.xCoordList[atomIndex];
out << std::setfill(' ') << std::fixed << std::setprecision(3) << std::setw(8) << std::right;
out << sd.yCoordList[atomIndex];
out << std::setfill(' ') << std::fixed << std::setprecision(3) << std::setw(8) << std::right;
out << sd.zCoordList[atomIndex];
// Occupancy
out << std::setfill(' ') << std::fixed << std::setprecision(2) << std::setw(6) << std::right;
if ( !mmtf::isDefaultValue(sd.occupancyList) ) {
out << sd.occupancyList[atomIndex];
} else out << " ";
out << " ";
// Element
out << std::right << std::setw(2) << std::setfill(' ') << group.elementList[l] << " \n";
}
}
}
}
out << "END";
return out.str();
}
int main(int argc, char** argv) {
// check arguments
if (argc != 2) {
std::cout << "USAGE: ./print_sd_as_pdb <in mmtf file>" << std::endl;
return 1;
}
mmtf::StructureData d;
mmtf::decodeFromFile(d, argv[1]);
std::cout << print_sd_as_pdb(d, false) << std::endl;
}
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code is Daniel Farrell
//
// *************************************************************************
#include <mmtf.hpp>
int main(int argc, char** argv) {
// check arguments
if (argc != 3) {
printf("USAGE: read_and_write <in mmtf file> <out mmtf file>\n");
return 1;
}
// decode->encode->decode
mmtf::StructureData d;
mmtf::decodeFromFile(d, argv[1]);
mmtf::StructureData example(d);
mmtf::encodeToFile(example, argv[2]);
mmtf::StructureData d2;
mmtf::decodeFromFile(d2, argv[2]);
if (d == d2) {
std::cout << "Found read+write yielded equal mmtf files" << std::endl;
return 0;
}
else {
std::cout << "Found read+write yielded NON-equal mmtf files" << std::endl;
return 1;
}
}
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code is Thomas Holder
//
// *************************************************************************
//
// This example demonstrates how to export molecular data which is given
// as atom and bond tables.
//
// *************************************************************************
#include <mmtf.hpp>
#include <mmtf/export_helpers.hpp>
#include <iostream>
#include <string>
#define ARRAYEND(a) ((a) + sizeof(a) / sizeof(a)[0])
/*
* Atom table of example "ALA-GLY-ALA" tripeptide
*/
struct Atom {
std::string chain;
int residue_number;
std::string residue_name;
std::string atom_name;
std::string element;
int formal_charge;
float x, y, z;
} atomarray[] = {
{"A", 1, "ALA", "N", "N", 0, -0.677, -1.230, -0.491},
{"A", 1, "ALA", "CA", "C", 0, -0.001, 0.064, -0.491},
{"A", 1, "ALA", "C", "C", 0, 1.499, -0.110, -0.491},
{"A", 1, "ALA", "O", "O", 0, 2.030, -1.227, -0.502},
{"A", 1, "ALA", "CB", "C", 0, -0.509, 0.856, 0.727},
{"A", 2, "GLY", "N", "N", 0, 2.250, 0.939, -0.479},
{"A", 2, "GLY", "CA", "C", 0, 3.700, 0.771, -0.479},
{"A", 2, "GLY", "C", "C", 0, 4.400, 2.108, -0.463},
{"A", 2, "GLY", "O", "O", 0, 3.775, 3.173, -0.453},
{"A", 3, "ALA", "N", "N", 0, 5.689, 2.140, -0.462},
{"A", 3, "ALA", "CA", "C", 0, 6.365, 3.434, -0.447},
{"A", 3, "ALA", "C", "C", 0, 7.865, 3.260, -0.447},
{"A", 3, "ALA", "O", "O", 0, 8.396, 2.144, -0.470},
{"A", 3, "ALA", "CB", "C", 0, 5.855, 4.213, 0.778}
};
/*
* Bond table for "ALA-GLY-ALA" tripeptide
*/
struct Bond {
size_t atom1;
size_t atom2;
int8_t order;
} bondarray[] = {
{0, 1, 1},
{1, 2, 1},
{1, 4, 1},
{2, 3, 2},
{2, 5, 1},
{5, 6, 1},
{6, 7, 1},
{7, 8, 2},
{7, 9, 1},
{9, 10, 1},
{10, 11, 1},
{10, 13, 1},
{11, 12, 2}
};
int main(int argc, char** argv)
{
mmtf::StructureData data;
mmtf::GroupType* residue = NULL;
const Atom* prevatom = NULL;
// start new model
data.chainsPerModel.push_back(0);
// add atoms
for (const Atom* atom = atomarray; atom != ARRAYEND(atomarray); ++atom) {
data.xCoordList.push_back(atom->x);
data.yCoordList.push_back(atom->y);
data.zCoordList.push_back(atom->z);
bool is_same_residue = false;
bool is_same_chain = prevatom && prevatom->chain == atom->chain;
if (!is_same_chain) {
data.chainsPerModel.back() += 1;
data.groupsPerChain.push_back(0); // increment with every group
data.chainIdList.push_back(atom->chain);
} else {
is_same_residue = prevatom && prevatom->residue_number == atom->residue_number;
}
if (!is_same_residue) {
data.groupsPerChain.back() += 1;
data.groupTypeList.push_back(data.groupList.size());
data.groupIdList.push_back(atom->residue_number);
data.groupList.resize(data.groupList.size() + 1);
residue = &data.groupList.back();
residue->groupName = atom->residue_name;
}
residue->formalChargeList.push_back(atom->formal_charge);
residue->atomNameList.push_back(atom->atom_name);
residue->elementList.push_back(atom->element);
prevatom = atom;
}
data.numAtoms = data.xCoordList.size();
data.numGroups = data.groupIdList.size();
data.numChains = data.chainIdList.size();
data.numModels = data.chainsPerModel.size();
// construct the BondAdder after adding atoms was completed
mmtf::BondAdder bondadder(data);
// add bonds
for (const Bond* bond = bondarray; bond != ARRAYEND(bondarray); ++bond) {
bondadder(bond->atom1, bond->atom2, bond->order);
}
std::cout << "INFO numBonds (total): " << data.numBonds << std::endl;
std::cout << "INFO numBonds (inter-residue): " << (data.bondAtomList.size() / 2) << std::endl;
std::cout << "INFO groupList.size() before compression: " << data.groupList.size() << std::endl;
mmtf::compressGroupList(data);
std::cout << "INFO groupList.size() after compression: " << data.groupList.size() << std::endl;
// write to file if filename provided
if (argc != 2) {
printf("USAGE: export <out mmtf file>\n");
} else {
mmtf::encodeToFile(data, argv[1]);
}
return 0;
}
// vi:sw=2:expandtab
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code are: Gerardo Tauriello
//
// Based on mmtf_c developed by Julien Ferte (http://www.julienferte.com/),
// Anthony Bradley, Thomas Holder with contributions from Yana Valasatava,
// Gazal Kalyan, Alexander Rose.
//
// *************************************************************************
// single include for all MMTF needs
#include "mmtf/decoder.hpp"
#include "mmtf/encoder.hpp"
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code are: Gabriel Studer, Gerardo Tauriello
//
// Based on mmtf_c developed by Julien Ferte (http://www.julienferte.com/),
// Anthony Bradley, Thomas Holder with contributions from Yana Valasatava,
// Gazal Kalyan, Alexander Rose.
//
// *************************************************************************
#ifndef MMTF_DECODER_H
#define MMTF_DECODER_H
#include "structure_data.hpp"
#include "errors.hpp"
#include "msgpack_decoders.hpp"
#include "map_decoder.hpp"
#include <msgpack.hpp>
#include <fstream>
#include <sstream>
#include <string>
namespace mmtf {
/**
* @brief Decode an MMTF data structure from a mapDecoder.
* @param[out] data MMTF data structure to be filled
* @param[in] mapDecoder MapDecoder holding raw mmtf data
* @throw mmtf::DecodeError if an error occured
*/
inline void decodeFromMapDecoder(StructureData& data, MapDecoder& mapDecoder);
/**
* @brief Decode an MMTF data structure from a byte buffer.
* @param[out] data MMTF data structure to be filled
* @param[in] buffer File contents
* @param[in] size Size of buffer
* @throw mmtf::DecodeError if an error occured
*/
inline void decodeFromBuffer(StructureData& data, const char* buffer,
size_t size);
/**
* @brief Decode an MMTF data structure from a stream.
*
* Note that the full stream is read from start to end before decoding it!
* Use ::decodeFromBuffer if you wish to use just part of the stream.
*
* @param[out] data MMTF data structure to be filled
* @param[in] stream Stream that holds mmtf data
* @tparam Stream Any stream type compatible to std::istream
* @throw mmtf::DecodeError if an error occured
*/
template <typename Stream>
inline void decodeFromStream(StructureData& data, Stream& stream);
/**
* @brief Decode an MMTF data structure from an existing file.
* @param[out] data MMTF data structure to be filled
* @param[in] filename Path to file to load
* @throw mmtf::DecodeError if an error occured
*/
inline void decodeFromFile(StructureData& data, const std::string& filename);
/**
* @brief Get a mapDecoder for un-decoded MMTF data
* @param[out] mapDecoder MapDecoder to hold raw mmtf data
*
* Other parameters and behavior are as in ::decodeFromBuffer, but this doesn't
* decode the MMTF content.
*/
inline void mapDecoderFromBuffer(MapDecoder& mapDecoder, const char* buffer,
std::size_t size);
/**
* @brief Get a mapDecoder into an un-decoded MMTF data
* @param[out] mapDecoder MapDecoder to hold raw mmtf data
*
* Other parameters and behavior are as in ::decodeFromStream, but this doesn't
* decode the MMTF content.
*/
template <typename Stream>
inline void mapDecoderFromStream(MapDecoder& mapDecoder, Stream& stream);
/**
* @brief Get a mapDecoder into an un-decoded MMTF data
* @param[out] mapDecoder MapDecoder to hold raw mmtf data
*
* Other parameters and behavior are as in ::decodeFromFile, but this doesn't
* decode the MMTF content.
*/
inline void mapDecoderFromFile(MapDecoder& mapDecoder,
const std::string& filename);
// *************************************************************************
// IMPLEMENTATION
// *************************************************************************
inline void decodeFromMapDecoder(StructureData& data, MapDecoder& md) {
mmtf::impl::decodeFromMapDecoder(data, md);
}
inline void decodeFromBuffer(StructureData& data, const char* buffer,
size_t size) {
MapDecoder md;
mapDecoderFromBuffer(md, buffer, size);
decodeFromMapDecoder(data, md);
}
template <typename Stream>
inline void decodeFromStream(StructureData& data, Stream& stream) {
MapDecoder md;
mapDecoderFromStream(md, stream);
decodeFromMapDecoder(data, md);
}
inline void decodeFromFile(StructureData& data, const std::string& filename) {
MapDecoder md;
mapDecoderFromFile(md, filename);
decodeFromMapDecoder(data, md);
}
inline void mapDecoderFromBuffer(MapDecoder& mapDecoder, const char* buffer,
std::size_t size) {
mapDecoder.initFromBuffer(buffer, size);
}
template <typename Stream>
inline void mapDecoderFromStream(MapDecoder& mapDecoder, Stream& stream) {
// parse straight into string buffer
std::string buffer;
stream.seekg(0, std::ios::end);
buffer.resize(stream.tellg());
stream.seekg(0, std::ios::beg);
if (!buffer.empty()) stream.read(&buffer[0], buffer.size());
mapDecoderFromBuffer(mapDecoder, buffer.data(), buffer.size());
}
inline void mapDecoderFromFile(MapDecoder& mapDecoder,
const std::string& filename) {
// read file as binary
std::ifstream ifs(filename.c_str(), std::ifstream::in | std::ios::binary);
if (!ifs.is_open()) {
throw DecodeError("Could not open file: " + filename);
}
mapDecoderFromStream(mapDecoder, ifs);
}
} // mmtf namespace
#endif
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code are: Gerardo Tauriello
//
// Based on mmtf_c developed by Julien Ferte (http://www.julienferte.com/),
// Anthony Bradley, Thomas Holder with contributions from Yana Valasatava,
// Gazal Kalyan, Alexander Rose. Updated 2018 by Daniel Farrell.
//
// *************************************************************************
#ifndef MMTF_ERRORS_H
#define MMTF_ERRORS_H
#include <stdexcept>
namespace mmtf {
/**
* @brief Exception thrown when failing during decoding.
*/
class DecodeError: public std::runtime_error {
public:
DecodeError(const std::string& m): std::runtime_error(m) { }
};
/**
* @brief Exception thrown when failing during encoding.
*/
class EncodeError: public std::runtime_error {
public:
EncodeError(const std::string& m): std::runtime_error(m) { }
};
} // mmtf namespace
#endif
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code are: Thomas Holder
//
// *************************************************************************
//
// Helper functions and classes for exporting MMTF data.
// See "examples/tableexport.cpp" for example usage.
//
// *************************************************************************
#ifndef MMTF_EXPORT_HELPERS_H
#define MMTF_EXPORT_HELPERS_H
#include "errors.hpp"
#include "structure_data.hpp"
#include <vector>
namespace mmtf
{
/**
* @brief Helper class for adding bonds to a group-redundant system
*
* @pre Atoms already exist in the system
*
* @pre groupTypeList has no duplicates (otherwise adding an inter-residue
* bond will add it to all residues with the same group type)
*/
class BondAdder {
StructureData* m_data;
std::vector<int32_t> m_atom2groupType;
std::vector<int32_t> m_atomOffsets;
public:
/**
* @param[in,out] data Consistent system with atoms
*
* @throw mmtf::EncodeError if groupTypeList has duplicates
*/
BondAdder(StructureData& data)
: m_data(&data), m_atomOffsets(data.groupTypeList.size(), -1)
{
m_atom2groupType.reserve(data.numAtoms);
for (size_t i = 0; i < data.groupTypeList.size(); ++i) {
int32_t groupType = data.groupTypeList[i];
// sanity check
if (m_atomOffsets[groupType] != -1) {
throw EncodeError("groupTypeList has duplicates");
}
size_t atomOffset = m_atom2groupType.size();
size_t groupSize = data.groupList[groupType].atomNameList.size();
m_atomOffsets[groupType] = atomOffset;
m_atom2groupType.resize(atomOffset + groupSize, groupType);
}
}
/**
* @brief Add one bond
*
* @param[in] atom1 Atom index 1 (zero-based)
* @param[in] atom2 Atom index 2 (zero-based)
* @param[in] order Bond order
*
* @return False if atom indices out of bounds
*/
bool operator()(int32_t atom1, int32_t atom2, int8_t order)
{
if (atom1 >= m_atom2groupType.size() ||
atom2 >= m_atom2groupType.size())
return false;
if (m_atom2groupType[atom1] == m_atom2groupType[atom2]) {
int32_t groupType = m_atom2groupType[atom1];
GroupType& group = m_data->groupList[groupType];
group.bondAtomList.push_back(atom1 - m_atomOffsets[groupType]);
group.bondAtomList.push_back(atom2 - m_atomOffsets[groupType]);
group.bondOrderList.push_back(order);
} else {
m_data->bondAtomList.push_back(atom1);
m_data->bondAtomList.push_back(atom2);
m_data->bondOrderList.push_back(order);
}
++m_data->numBonds;
return true;
}
};
/**
* @brief Eliminate redundant groups from groupList
*
* Modifies groupList and groupTypeList
*
* @param[in,out] data Consistent system
*/
inline void compressGroupList(StructureData& data)
{
size_t n_old = data.groupList.size();
size_t i_free = 0;
std::vector<size_t> idremap(n_old, 0);
for (size_t i = 1; i < n_old; ++i) {
size_t i_found = 0;
while (i_found < i && !(data.groupList[i] == data.groupList[i_found])) {
++i_found;
}
if (i_found == i) {
if (i_free != 0) {
data.groupList[i_free] = data.groupList[i]; // std::move possible with C++11
i_found = i_free;
++i_free;
}
} else if (i_free == 0) {
i_free = i;
}
idremap[i] = i_found;
}
if (i_free != 0) {
data.groupList.resize(i_free);
for (size_t i = 0; i < data.groupTypeList.size(); ++i) {
data.groupTypeList[i] = idremap[data.groupTypeList[i]];
}
}
}
} // namespace mmtf
#endif
// vi:sw=2:expandtab
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The authors of this code are: Gabriel Studer, Gerardo Tauriello, and
// Daniel Farrell.
//
// Based on mmtf_c developed by Julien Ferte (http://www.julienferte.com/),
// Anthony Bradley, Thomas Holder with contributions from Yana Valasatava,
// Gazal Kalyan, Alexander Rose.
//
// *************************************************************************
#ifndef MMTF_MSGPACK_DECODERS_H
#define MMTF_MSGPACK_DECODERS_H
#include "structure_data.hpp"
#include "map_decoder.hpp"
#include "errors.hpp"
#include <msgpack.hpp>
// custom global function used here and in decoder.hpp
namespace mmtf {
namespace impl {
inline void decodeFromMapDecoder(StructureData& data, MapDecoder& md) {
md.decode("mmtfVersion", true, data.mmtfVersion);
// check if version is compatible before continuing
if (!mmtf::isVersionSupported(data.mmtfVersion)) {
throw mmtf::DecodeError("Unsupported MMTF version "
+ data.mmtfVersion);
}
md.decode("mmtfProducer", true, data.mmtfProducer);
md.decode("unitCell", false, data.unitCell);
md.decode("spaceGroup", false, data.spaceGroup);
md.decode("structureId", false, data.structureId);
md.decode("title", false, data.title);
md.decode("depositionDate", false, data.depositionDate);
md.decode("releaseDate", false, data.releaseDate);
md.decode("ncsOperatorList", false, data.ncsOperatorList);
md.decode("bioAssemblyList", false, data.bioAssemblyList);
md.decode("entityList", false, data.entityList);
md.decode("experimentalMethods", false, data.experimentalMethods);
md.decode("resolution", false, data.resolution);
md.decode("rFree", false, data.rFree);
md.decode("rWork", false, data.rWork);
md.decode("numBonds", true, data.numBonds);
md.decode("numAtoms", true, data.numAtoms);
md.decode("numGroups", true, data.numGroups);
md.decode("numChains", true, data.numChains);
md.decode("numModels", true, data.numModels);
md.decode("groupList", true, data.groupList);
md.decode("bondAtomList", false, data.bondAtomList);
md.decode("bondOrderList", false, data.bondOrderList);
md.decode("bondResonanceList", false, data.bondResonanceList);
md.decode("xCoordList", true, data.xCoordList);
md.decode("yCoordList", true, data.yCoordList);
md.decode("zCoordList", true, data.zCoordList);
md.decode("bFactorList", false, data.bFactorList);
md.decode("atomIdList", false, data.atomIdList);
md.decode("altLocList", false, data.altLocList);
md.decode("occupancyList", false, data.occupancyList);
md.decode("groupIdList", true, data.groupIdList);
md.decode("groupTypeList", true, data.groupTypeList);
md.decode("secStructList", false, data.secStructList);
md.decode("insCodeList", false, data.insCodeList);
md.decode("sequenceIndexList", false, data.sequenceIndexList);
md.decode("chainIdList", true, data.chainIdList);
md.decode("chainNameList", false, data.chainNameList);
md.decode("groupsPerChain", true, data.groupsPerChain);
md.decode("chainsPerModel", true, data.chainsPerModel);
// extraProperties (application specific stuff)
// Perform expensive copy if exists.
// Implement outside accessor if speed is necessary
md.copy_decode("bondProperties", false, data.bondProperties,
data.msgpack_zone);
md.copy_decode("atomProperties", false, data.atomProperties,
data.msgpack_zone);
md.copy_decode("groupProperties", false, data.groupProperties,
data.msgpack_zone);
md.copy_decode("chainProperties", false, data.chainProperties,
data.msgpack_zone);
md.copy_decode("modelProperties", false, data.modelProperties,
data.msgpack_zone);
md.copy_decode("extraProperties", false, data.extraProperties,
data.msgpack_zone);
md.checkExtraKeys();
}
}
}
// here we specialize msgpack-c functionality so we can use obj.convert(..)
namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
// custom specialization for chars stored as strings
template <>
struct convert<char> {
const msgpack::object& operator()(const msgpack::object& obj,
char& c) const {
// extract string
std::string temp;
obj.convert(temp);
// ensure length
if (temp.size() != 1) {
throw mmtf::DecodeError("Observed single letter string not being "
"of length one!");
}
c = temp[0];
return obj;
}
};
template <>
struct convert<mmtf::GroupType> {
const msgpack::object& operator()(const msgpack::object& obj,
mmtf::GroupType& group) const {
mmtf::MapDecoder md(obj);
md.decode("formalChargeList", true, group.formalChargeList);
md.decode("atomNameList", true, group.atomNameList);
md.decode("elementList", true, group.elementList);
md.decode("bondAtomList", false, group.bondAtomList);
md.decode("bondOrderList", false, group.bondOrderList);
md.decode("bondResonanceList", false, group.bondResonanceList);
md.decode("groupName", true, group.groupName);
md.decode("singleLetterCode", true, group.singleLetterCode);
md.decode("chemCompType", true, group.chemCompType);
md.checkExtraKeys();
return obj;
}
};
template <>
struct convert<mmtf::Entity> {
const msgpack::object& operator()(const msgpack::object& obj,
mmtf::Entity& entity) const {
mmtf::MapDecoder md(obj);
md.decode("chainIndexList", true, entity.chainIndexList);
md.decode("description", true, entity.description);
md.decode("type", true, entity.type);
md.decode("sequence", true, entity.sequence);
md.checkExtraKeys();
return obj;
}
};
template <>
struct convert<mmtf::Transform> {
const msgpack::object& operator()(const msgpack::object& obj,
mmtf::Transform& transform) const {
mmtf::MapDecoder md(obj);
md.decode("chainIndexList", true, transform.chainIndexList);
md.decode("matrix", true, transform.matrix);
md.checkExtraKeys();
return obj;
}
};
template <>
struct convert<mmtf::BioAssembly> {
const msgpack::object& operator()(const msgpack::object& obj,
mmtf::BioAssembly& assembly) const {
mmtf::MapDecoder md(obj);
md.decode("transformList", true, assembly.transformList);
md.decode("name", true, assembly.name);
md.checkExtraKeys();
return obj;
}
};
template <>
struct convert<mmtf::StructureData> {
const msgpack::object& operator()(const msgpack::object& obj,
mmtf::StructureData& data) const {
mmtf::MapDecoder md(obj);
mmtf::impl::decodeFromMapDecoder(data, md);
return obj;
}
};
}}} // msgpack::VERSION::adaptor namespace
#endif
// *************************************************************************
//
// Licensed under the MIT License (see accompanying LICENSE file).
//
// The author of this code is: Daniel Farrell
//
// Based on mmtf_python, adapted to c++ standards 2018
//
// *************************************************************************
//
#ifndef MMTF_MSGPACK_ENCODERS_H
#define MMTF_MSGPACK_ENCODERS_H
#include "structure_data.hpp"
#include <msgpack.hpp>
namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
/* *
* @brief encode a mmtf::GroupType to a msgpack map type.
*
* We must use this method for packing because 'char' is treated as an int
* by msgpack. We cannot use the prepackaged intrusive method.
*
* Also we use this because 3 fields are optional!
*/
template <>
struct object_with_zone<mmtf::GroupType> {
void operator()(msgpack::object::with_zone& o, mmtf::GroupType const& v) const {
int this_size = 9;
bool use_bondAtom = true, use_bondOrder = true, use_bondResonance = true;
if (mmtf::isDefaultValue(v.bondAtomList)) {
use_bondAtom = false;
--this_size;
}
if (mmtf::isDefaultValue(v.bondOrderList)) {
use_bondOrder = false;
--this_size;
}
if (mmtf::isDefaultValue(v.bondResonanceList)) {
use_bondResonance = false;
--this_size;
}
o.type = type::MAP;
o.via.map.size = this_size;
o.via.map.ptr = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*this_size, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv)));
int current_size = 0;
o.via.map.ptr[current_size].key = msgpack::object("formalChargeList", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.formalChargeList, o.zone);
++current_size;
o.via.map.ptr[current_size].key = msgpack::object("atomNameList", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.atomNameList, o.zone);
++current_size;
o.via.map.ptr[current_size].key = msgpack::object("elementList", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.elementList, o.zone);
++current_size;
o.via.map.ptr[current_size].key = msgpack::object("groupName", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.groupName, o.zone);
++current_size;
o.via.map.ptr[current_size].key = msgpack::object("singleLetterCode", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(std::string(1,v.singleLetterCode), o.zone);
++current_size;
o.via.map.ptr[current_size].key = msgpack::object("chemCompType", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.chemCompType, o.zone);
++current_size;
if (use_bondAtom) {
o.via.map.ptr[current_size].key = msgpack::object("bondAtomList", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.bondAtomList, o.zone);
++current_size;
}
if (use_bondOrder) {
o.via.map.ptr[current_size].key = msgpack::object("bondOrderList", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.bondOrderList, o.zone);
++current_size;
}
if (use_bondResonance) {
o.via.map.ptr[current_size].key = msgpack::object("bondResonanceList", o.zone);
o.via.map.ptr[current_size].val = msgpack::object(v.bondResonanceList, o.zone);
++current_size;
}
}
};
} // namespace adaptor
} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // namespace msgpack
#endif
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
if(EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s TOTAL_MEMORY=150994944 -s DISABLE_EXCEPTION_CATCHING=0")
endif()
add_executable(mmtf_tests mmtf_tests.cpp)
target_compile_features(mmtf_tests PRIVATE cxx_auto_type)
if(WIN32)
target_link_libraries(mmtf_tests Catch msgpackc MMTFcpp ws2_32)
else()
target_link_libraries(mmtf_tests Catch msgpackc MMTFcpp)
endif()
# test for multi-linking
add_executable(multi_cpp_test multi_cpp_test.cpp multi_cpp_test_helper.cpp)
target_compile_features(multi_cpp_test PRIVATE cxx_auto_type)
if(WIN32)
target_link_libraries(multi_cpp_test MMTFcpp ws2_32)
else()
target_link_libraries(multi_cpp_test MMTFcpp)
endif()
set(TEST_RUNNER "none" CACHE STRING "External runner for the tests")
if (${TEST_RUNNER} STREQUAL "node")
add_test( NAME mmtf_tests COMMAND node mmtf_tests)
else()
add_test( NAME mmtf_tests WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND mmtf_tests)
endif()
// *************************************************************************
//
// Simple test for compilation issues.
//
// *************************************************************************
#include <mmtf.hpp>
#include "multi_cpp_test_helper.hpp"
int main(int argc, char** argv) {
// decode MMTF file
std::string filename = "../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf";
mmtf::StructureData data;
read_check_file(data, filename);
return 0;
}
// *************************************************************************
//
// Simple test for compilation issues.
//
// *************************************************************************
#include "multi_cpp_test_helper.hpp"
#include <iostream>
void read_check_file(mmtf::StructureData& data, const std::string& filename) {
// decode MMTF file
mmtf::decodeFromFile(data, filename);
// check if the data is self-consistent
if (data.hasConsistentData()) {
std::cout << "Successfully read " << filename << ".\n";
} else {
std::cout << "Inconsistent data in " << filename << ".\n";
}
}
// *************************************************************************
//
// Simple test for compilation issues.
//
// *************************************************************************
#include <mmtf.hpp>
#include <string>
void read_check_file(mmtf::StructureData& data, const std::string& filename);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment