├── .gitignore
├── .gitmodules
├── .travis.yml
├── CHANGELOG.md
├── CMakeLists.txt
├── LICENSE
├── README.md
├── appveyor.yml
├── ci
├── build_and_run_tests.sh
├── setup-appveyor.ps1
├── setup-travis.sh
└── travis-test-example.sh
├── docs
└── Doxyfile
├── examples
├── CMakeLists.txt
├── compile_and_run.sh
├── compile_read_and_write.sh
├── compile_target.sh
├── mmtf_demo.cpp
├── print_as_pdb.cpp
├── read_and_write.cpp
├── tableexport.cpp
└── traverse.cpp
├── include
├── mmtf.hpp
└── mmtf
│ ├── binary_decoder.hpp
│ ├── binary_encoder.hpp
│ ├── decoder.hpp
│ ├── encoder.hpp
│ ├── errors.hpp
│ ├── export_helpers.hpp
│ ├── map_decoder.hpp
│ ├── msgpack_decoders.hpp
│ ├── msgpack_encoders.hpp
│ └── structure_data.hpp
├── temporary_test_data
├── 1PEF_with_resonance.mmtf
├── 3zqs.mmtf
└── all_canoncial.mmtf
└── tests
├── CMakeLists.txt
├── mmtf_tests.cpp
├── multi_cpp_test.cpp
├── multi_cpp_test_helper.cpp
└── multi_cpp_test_helper.hpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Object files
2 | *.o
3 | *.ko
4 | *.obj
5 | *.elf
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Libraries
12 | *.lib
13 | *.a
14 | *.la
15 | *.lo
16 |
17 | # Shared objects (inc. Windows DLLs)
18 | *.dll
19 | *.so
20 | *.so.*
21 | *.dylib
22 |
23 | # Executables
24 | *.exe
25 | *.out
26 | *.app
27 | *.i*86
28 | *.x86_64
29 | *.hex
30 |
31 | # Debug files
32 | *.dSYM/
33 | *.su
34 |
35 | # The build dir
36 | build/*
37 |
38 | # Generated folders
39 | docs/html/*
40 | examples/out/*
41 | examples/out_json_ref/*
42 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Catch2"]
2 | path = submodules/Catch2
3 | url = https://github.com/catchorg/Catch2
4 | [submodule "msgpack-c"]
5 | path = submodules/msgpack-c
6 | url = https://github.com/msgpack/msgpack-c
7 | [submodule "mmtf_spec"]
8 | path = submodules/mmtf_spec
9 | url = https://github.com/rcsb/mmtf
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | sudo: false
3 | dist: trusty
4 |
5 | linux64_addons:
6 | addons: &linux64
7 | apt:
8 | sources:
9 | - ubuntu-toolchain-r-test
10 | packages:
11 | - g++-4.8
12 |
13 | linux32_addons:
14 | addons: &linux32
15 | apt:
16 | sources:
17 | - ubuntu-toolchain-r-test
18 | packages:
19 | - g++-4.8
20 | - g++-4.8-multilib
21 | - linux-libc-dev:i386
22 | - libc6-dev-i386
23 |
24 | linux64_cpp17addons:
25 | addons: &linux64cpp17
26 | apt:
27 | sources:
28 | - ubuntu-toolchain-r-test
29 |
30 | # Set empty values for allow_failures to work
31 | env: TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
32 |
33 | matrix:
34 | fast_finish: true
35 | include:
36 | - os: linux
37 | env: EMSCRIPTEN=ON TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
38 | addons: *linux64
39 | - os: linux
40 | compiler: clang
41 | addons: *linux64
42 | - os: linux
43 | compiler: gcc
44 | env: ARCH=x86 CMAKE_EXTRA=-DHAVE_LIBM=/lib32/libm.so.6 TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
45 | addons: *linux32
46 | - os: osx
47 | compiler: clang
48 | - os: linux
49 | compiler: gcc
50 | env: CMAKE_EXTRA="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS='-march=native'" TEST_COMMAND=$TRAVIS_BUILD_DIR/ci/build_and_run_tests.sh
51 | addons: *linux64cpp17
52 | dist: bionic
53 | - os: linux
54 | compiler: gcc
55 | addons: *linux64cpp17
56 | dist: bionic
57 |
58 |
59 | before_install:
60 | # Setting environement
61 | - cd $TRAVIS_BUILD_DIR
62 | - source ci/setup-travis.sh
63 | - $CC --version
64 | - $CXX --version
65 |
66 | script:
67 | - echo $TEST_COMMAND
68 | - (eval "$TEST_COMMAND")
69 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/).
6 |
7 | ## [Unreleased]
8 |
9 | ## v1.1.0 - 2022-10-03
10 | ### Added
11 | - New mapDecoderFrom.. functions to decode only part of an MMTF file
12 | - Support for extra fields in MMTF files according to the
13 | [latest MMTF specification](https://github.com/rcsb/mmtf/pull/36).
14 | - Support for binary strategy 16 (Run-length encoded 8-bit array),
15 | bondResonanceList field and optional groupType.bondAtomList &
16 | groupType.bondOrderList according to the proposed version 1.1 of the
17 | [MMTF specification](https://github.com/rcsb/mmtf/pull/35).
18 | - New methods to find polymer chains and HETATM following discussions in
19 | [rcsb/mmtf#28](https://github.com/rcsb/mmtf/issues/28).
20 | - Altered submodule locations [rcsb/mmtf-cpp#37](https://github.com/rcsb/mmtf-cpp/pull/37)
21 | from the base directory to the new submodules directory.
22 |
23 | ## v1.0.0 - 2019-02-05
24 | ### Added
25 | - Initial release including decoder and encoder for the
26 | [MMTF specification 1.0](https://github.com/rcsb/mmtf/blob/v1.0/spec.md).
27 |
28 | [Unreleased]: https://github.com/rcsb/mmtf-cpp/compare/v1.1.0...HEAD
29 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
3 |
4 | project(mmtf-cpp VERSION 1.0.0 LANGUAGES CXX)
5 |
6 | option(mmtf_build_local "Use the submodule dependencies for building" OFF)
7 | option(mmtf_build_examples "Build the examples" OFF)
8 |
9 | add_library(MMTFcpp INTERFACE)
10 | target_compile_features(MMTFcpp INTERFACE cxx_auto_type)
11 |
12 | target_include_directories(MMTFcpp INTERFACE
13 | ${CMAKE_CURRENT_SOURCE_DIR}/include
14 | )
15 |
16 | if (mmtf_build_local)
17 | # use header only
18 | set(MSGPACKC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/submodules/msgpack-c/include)
19 | add_library(msgpackc INTERFACE)
20 | target_include_directories(msgpackc INTERFACE ${MSGPACKC_INCLUDE_DIR})
21 | if (BUILD_TESTS)
22 | set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/submodules/Catch2/single_include)
23 | add_library(Catch INTERFACE)
24 | target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
25 | endif()
26 | endif()
27 |
28 | if (NOT TARGET msgpackc)
29 | find_package(msgpack)
30 | endif()
31 |
32 | target_link_libraries(MMTFcpp INTERFACE msgpackc)
33 |
34 | if (BUILD_TESTS)
35 | enable_testing()
36 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
37 | endif()
38 |
39 | if (mmtf_build_examples)
40 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/examples)
41 | endif()
42 |
43 | install(
44 | DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
45 | DESTINATION "include"
46 | FILES_MATCHING PATTERN "*.hpp")
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | The MIT license applies to all files unless otherwise noted.
3 |
4 | Copyright 2017, University of California San Diego
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | [](https://github.com/rcsb/mmtf-cpp/releases)
3 | [](https://github.com/rcsb/mmtf-cpp/blob/master/LICENSE)
4 | [](https://app.travis-ci.com/github/rcsb/mmtf-cpp)
5 |
6 | The macromolecular transmission format
7 | ([MMTF](http://mmtf.rcsb.org)) is a binary encoding of biological structures.
8 |
9 | This repository holds the C++-03 compatible API, encoding and decoding
10 | libraries. The MMTF specification can be found
11 | [here](https://github.com/rcsb/mmtf/blob/HEAD/spec.md/).
12 |
13 | ## Prerequisites for using MMTF in C++
14 |
15 | You need the headers of the MessagePack C++ library (version 2.1.5 or newer).
16 | If you do not have them on your machine already, you can download the "include"
17 | directory from the
18 | [MessagePack GitHub repository](https://github.com/msgpack/msgpack-c).
19 |
20 | ## How to use MMTF
21 |
22 | You only need to include the mmtf.hpp header in your code to use MMTF.
23 | For instance a minimal example to load an MMTF file looks as follows:
24 |
25 | ```C
26 | #include
27 |
28 | int main(int argc, char** argv) {
29 | mmtf::StructureData data;
30 | mmtf::decodeFromFile(data, "test.mmtf");
31 | return 0;
32 | }
33 | ```
34 |
35 | The C++ MMTF library is header only so you do not need to compile it. If you
36 | have a source file named `demo.cpp` (e.g. including the code above), you can
37 | generate an executable `demo.exe` as follows:
38 |
39 | ```bash
40 | g++ -I -I demo.cpp -o demo.exe
41 | ```
42 |
43 | Here, `` and `` are the paths to the
44 | "include" directories of MessagePack and this library respectively.
45 |
46 | For your more complicated projects, a `CMakeLists.txt` is included for you.
47 |
48 | ## Installation
49 | You can also perform a system wide installation with `cmake` and `ninja` (or `make`).
50 | To do so:
51 | ```bash
52 | mkdir build
53 | cd build
54 | cmake -G Ninja ..
55 | sudo ninja install
56 | ```
57 |
58 | `cmake` automatically sets the installation directory to `/usr/local/include`, if you want to install it to another `*include/` directory
59 | run `cmake` with the command:
60 | ```bash
61 | cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/home/me/local ..
62 | ```
63 | 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/`).
64 |
65 |
66 | ## Examples and tests
67 |
68 | To build the tests + examples we recommend using the following lines:
69 |
70 | ```bash
71 | # download Catch2 testing framework, msgpack-c, and the mmtf-spec test-dataset
72 | git submodule update --init --recursive
73 | mkdir build
74 | cd build
75 | cmake -G Ninja -DBUILD_TESTS=ON -Dmmtf_build_local=ON -Dmmtf_build_examples=ON ..
76 | ninja
77 | chmod +x ./tests/mmtf_tests
78 | ./tests/mmtf_tests
79 | ```
80 |
81 | Example codes:
82 | - mmtf_demo.cpp: Loads an MMTF file and checks internal consistency using
83 | mmtf::StructureData::hasConsistentData.
84 | ```bash
85 | ./examples/mmtf_demo ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf
86 | ```
87 | - traverse.cpp: Loads an MMTF file and dumps it in human-readable forms.
88 | ```bash
89 | ./examples/traverse ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf
90 | ./examples/traverse ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf json
91 | ./examples/traverse ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf print
92 | ```
93 |
94 | - print_as_pdb.cpp: Loads an MMTF file and prints it in pdb format.
95 | ```bash
96 | ./examples/print_as_pdb ../submodules/mmtf_spec/test-suite/mmtf/173D.mmtf
97 | ```
98 |
99 | ## Benchmark
100 |
101 | Using the following simple code:
102 | ```cpp
103 | #include
104 |
105 |
106 | int main(int argc, char** argv)
107 | {
108 | for (int i=1; i only expected to work in Linux or Mac with CXX set to g++ or clang++
5 | # -> expects TRAVIS_BUILD_DIR, EMSCRIPTEN, CXX to be set
6 |
7 | # abort on error and exit with proper exit code
8 | set -e
9 | # test example
10 | cd $TRAVIS_BUILD_DIR/examples
11 | if [ -z "$EMSCRIPTEN" ]; then
12 | # Compile with C++03 forced
13 | $CXX -I"../submodules/msgpack-c/include" -I"../include" -std=c++03 -O2 \
14 | -o read_and_write read_and_write.cpp
15 | ./read_and_write ../submodules/mmtf_spec/test-suite/mmtf/3NJW.mmtf test.mmtf
16 | else
17 | # Cannot do C++03 here and need to embed input file for running it with node
18 | cp ../submodules/mmtf_spec/test-suite/mmtf/3NJW.mmtf .
19 | $CXX -I"../submodules/msgpack-c/include" -I"../include" -O2 \
20 | -o read_and_write.js read_and_write.cpp --embed-file 3NJW.mmtf
21 | node read_and_write.js 3NJW.mmtf test.mmtf
22 | fi
23 |
--------------------------------------------------------------------------------
/examples/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
3 |
4 | SET(executables mmtf_demo traverse print_as_pdb tableexport read_and_write)
5 |
6 | foreach(exe ${executables})
7 | add_executable(${exe} ${exe}.cpp)
8 | target_compile_features(${exe} PRIVATE cxx_auto_type)
9 | if(WIN32)
10 | target_link_libraries(${exe} MMTFcpp ws2_32)
11 | else()
12 | target_link_libraries(${exe} MMTFcpp)
13 | endif()
14 | endforeach(exe)
15 |
16 |
--------------------------------------------------------------------------------
/examples/compile_and_run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$3" == "" ]; then
4 | echo "USAGE: compile_and_run.sh "
5 | echo "-> for MAIN_FILE = test.cpp, we compile and run test.exe "
6 | exit 1
7 | fi
8 |
9 | MAIN_FILENAME="${2%.*}"
10 | ./compile_target.sh $1 $MAIN_FILENAME.cpp &&
11 | ./$MAIN_FILENAME.exe $3
12 |
--------------------------------------------------------------------------------
/examples/compile_read_and_write.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$3" == "" ]; then
4 | echo "USAGE: compile_read_and_write.sh "
5 | echo "-> read and write as "
6 | exit 1
7 | fi
8 |
9 | ./compile_target.sh $1 read_and_write.cpp &&
10 | ./read_and_write.exe $2 $3
11 |
--------------------------------------------------------------------------------
/examples/compile_target.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$2" == "" ]; then
4 | echo "USAGE: compile_target.sh "
5 | echo "-> for MAIN_FILE = test.cpp, this produces executable test.exe"
6 | exit 1
7 | fi
8 |
9 | MAIN_FILENAME="${2%.*}"
10 |
11 | g++ -I$1 -I"../include" -O2 -o $MAIN_FILENAME.exe $MAIN_FILENAME.cpp
12 |
--------------------------------------------------------------------------------
/examples/mmtf_demo.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #include
5 | #include
6 |
7 | int main(int argc, char** argv) {
8 | // check arguments
9 | if (argc < 2) {
10 | printf("USAGE: mmtf_demo \n");
11 | return 1;
12 | }
13 |
14 | // decode MMTF file
15 | std::string filename(argv[1]);
16 | mmtf::StructureData data;
17 | mmtf::decodeFromFile(data, filename);
18 |
19 | // check if the data is self-consistent
20 | if (data.hasConsistentData(true)) {
21 | std::cout << "Successfully read " << filename << ".\n";
22 | return 0;
23 | } else {
24 | std::cout << "Inconsistent data in " << filename << ".\n";
25 | return 1;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/examples/print_as_pdb.cpp:
--------------------------------------------------------------------------------
1 | // *************************************************************************
2 | //
3 | // Licensed under the MIT License (see accompanying LICENSE file).
4 | //
5 | // The authors of this code is Daniel Farrell
6 | //
7 | // NOTE: This wasn't made to be a well tested error-free executable... More
8 | // of an example of how you might iterate over an mmtf file in pdb style.
9 | // Please DO NOT USE THIS IN PRODUCTION.
10 | // *************************************************************************
11 |
12 | #include
13 |
14 | #include
15 | #include
16 |
17 | std::string print_sd_as_pdb(mmtf::StructureData const & sd, bool index_at_0) {
18 | std::ostringstream out;
19 | int modelIndex = 0;
20 | int chainIndex = 0;
21 | int groupIndex = 0;
22 | int atomIndex = 0;
23 |
24 | //# traverse models
25 | for (int i = 0; i < sd.numModels; i++, modelIndex++) {
26 | // # traverse chains
27 | for (int j = 0; j < sd.chainsPerModel[modelIndex]; j++, chainIndex++) {
28 | // # traverse groups
29 | for (int k = 0; k < sd.groupsPerChain[chainIndex]; k++, groupIndex++) {
30 | const mmtf::GroupType& group =
31 | sd.groupList[sd.groupTypeList[groupIndex]];
32 | int groupAtomCount = group.atomNameList.size();
33 |
34 | for (int l = 0; l < groupAtomCount; l++, atomIndex++) {
35 | // ATOM or HETATM
36 | if (mmtf::is_hetatm(chainIndex, sd.entityList, group))
37 | out << "HETATM";
38 | else
39 | out << "ATOM ";
40 | // Atom serial
41 | if (index_at_0 || mmtf::isDefaultValue(sd.atomIdList)) {
42 | out << std::setfill(' ') << std::internal << std::setw(5) <<
43 | std::right << atomIndex+1;
44 | } else {
45 | out << std::setfill(' ') << std::internal << std::setw(5) <<
46 | std::right << sd.atomIdList[atomIndex] << " ";
47 | }
48 | // Atom name
49 | out << std::left << std::setw(4) << std::setfill(' ') << group.atomNameList[l];
50 | // Group name
51 | out << group.groupName << " ";
52 | // Chain
53 | out << sd.chainIdList[chainIndex];
54 | // Group serial
55 | out << std::setfill(' ') << std::right << std::setw(4) << sd.groupIdList[groupIndex];
56 | out << " ";
57 | // x, y, z
58 | out << std::setfill(' ') << std::fixed << std::setprecision(3) << std::setw(8) << std::right;
59 | out << sd.xCoordList[atomIndex];
60 | out << std::setfill(' ') << std::fixed << std::setprecision(3) << std::setw(8) << std::right;
61 | out << sd.yCoordList[atomIndex];
62 | out << std::setfill(' ') << std::fixed << std::setprecision(3) << std::setw(8) << std::right;
63 | out << sd.zCoordList[atomIndex];
64 |
65 | // Occupancy
66 | out << std::setfill(' ') << std::fixed << std::setprecision(2) << std::setw(6) << std::right;
67 | if ( !mmtf::isDefaultValue(sd.occupancyList) ) {
68 | out << sd.occupancyList[atomIndex];
69 | } else out << " ";
70 | out << " ";
71 |
72 | // Element
73 | out << std::right << std::setw(2) << std::setfill(' ') << group.elementList[l] << " \n";
74 | }
75 | }
76 | }
77 | }
78 | out << "END";
79 | return out.str();
80 | }
81 |
82 |
83 | int main(int argc, char** argv) {
84 | // check arguments
85 | if (argc != 2) {
86 | std::cout << "USAGE: ./print_sd_as_pdb " << std::endl;
87 | return 1;
88 | }
89 |
90 | mmtf::StructureData d;
91 | mmtf::decodeFromFile(d, argv[1]);
92 | std::cout << print_sd_as_pdb(d, false) << std::endl;
93 | }
94 |
--------------------------------------------------------------------------------
/examples/read_and_write.cpp:
--------------------------------------------------------------------------------
1 | // *************************************************************************
2 | //
3 | // Licensed under the MIT License (see accompanying LICENSE file).
4 | //
5 | // The authors of this code is Daniel Farrell
6 | //
7 | // *************************************************************************
8 |
9 | #include
10 |
11 | int main(int argc, char** argv) {
12 | // check arguments
13 | if (argc != 3) {
14 | printf("USAGE: read_and_write \n");
15 | return 1;
16 | }
17 |
18 | // decode->encode->decode
19 | mmtf::StructureData d;
20 | mmtf::decodeFromFile(d, argv[1]);
21 | mmtf::StructureData example(d);
22 | mmtf::encodeToFile(example, argv[2]);
23 | mmtf::StructureData d2;
24 | mmtf::decodeFromFile(d2, argv[2]);
25 | if (d == d2) {
26 | std::cout << "Found read+write yielded equal mmtf files" << std::endl;
27 | return 0;
28 | }
29 | else {
30 | std::cout << "Found read+write yielded NON-equal mmtf files" << std::endl;
31 | return 1;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/tableexport.cpp:
--------------------------------------------------------------------------------
1 | // *************************************************************************
2 | //
3 | // Licensed under the MIT License (see accompanying LICENSE file).
4 | //
5 | // The authors of this code is Thomas Holder
6 | //
7 | // *************************************************************************
8 | //
9 | // This example demonstrates how to export molecular data which is given
10 | // as atom and bond tables.
11 | //
12 | // *************************************************************************
13 |
14 | #include
15 | #include
16 |
17 | #include
18 | #include
19 |
20 | #define ARRAYEND(a) ((a) + sizeof(a) / sizeof(a)[0])
21 |
22 | /*
23 | * Atom table of example "ALA-GLY-ALA" tripeptide
24 | */
25 | struct Atom {
26 | std::string chain;
27 | int residue_number;
28 | std::string residue_name;
29 | std::string atom_name;
30 | std::string element;
31 | int formal_charge;
32 | float x, y, z;
33 | } atomarray[] = {
34 | {"A", 1, "ALA", "N", "N", 0, -0.677, -1.230, -0.491},
35 | {"A", 1, "ALA", "CA", "C", 0, -0.001, 0.064, -0.491},
36 | {"A", 1, "ALA", "C", "C", 0, 1.499, -0.110, -0.491},
37 | {"A", 1, "ALA", "O", "O", 0, 2.030, -1.227, -0.502},
38 | {"A", 1, "ALA", "CB", "C", 0, -0.509, 0.856, 0.727},
39 | {"A", 2, "GLY", "N", "N", 0, 2.250, 0.939, -0.479},
40 | {"A", 2, "GLY", "CA", "C", 0, 3.700, 0.771, -0.479},
41 | {"A", 2, "GLY", "C", "C", 0, 4.400, 2.108, -0.463},
42 | {"A", 2, "GLY", "O", "O", 0, 3.775, 3.173, -0.453},
43 | {"A", 3, "ALA", "N", "N", 0, 5.689, 2.140, -0.462},
44 | {"A", 3, "ALA", "CA", "C", 0, 6.365, 3.434, -0.447},
45 | {"A", 3, "ALA", "C", "C", 0, 7.865, 3.260, -0.447},
46 | {"A", 3, "ALA", "O", "O", 0, 8.396, 2.144, -0.470},
47 | {"A", 3, "ALA", "CB", "C", 0, 5.855, 4.213, 0.778}
48 | };
49 |
50 | /*
51 | * Bond table for "ALA-GLY-ALA" tripeptide
52 | */
53 | struct Bond {
54 | size_t atom1;
55 | size_t atom2;
56 | int8_t order;
57 | } bondarray[] = {
58 | {0, 1, 1},
59 | {1, 2, 1},
60 | {1, 4, 1},
61 | {2, 3, 2},
62 | {2, 5, 1},
63 | {5, 6, 1},
64 | {6, 7, 1},
65 | {7, 8, 2},
66 | {7, 9, 1},
67 | {9, 10, 1},
68 | {10, 11, 1},
69 | {10, 13, 1},
70 | {11, 12, 2}
71 | };
72 |
73 | int main(int argc, char** argv)
74 | {
75 | mmtf::StructureData data;
76 | mmtf::GroupType* residue = NULL;
77 | const Atom* prevatom = NULL;
78 |
79 | // start new model
80 | data.chainsPerModel.push_back(0);
81 |
82 | // add atoms
83 | for (const Atom* atom = atomarray; atom != ARRAYEND(atomarray); ++atom) {
84 | data.xCoordList.push_back(atom->x);
85 | data.yCoordList.push_back(atom->y);
86 | data.zCoordList.push_back(atom->z);
87 |
88 | bool is_same_residue = false;
89 | bool is_same_chain = prevatom && prevatom->chain == atom->chain;
90 |
91 | if (!is_same_chain) {
92 | data.chainsPerModel.back() += 1;
93 | data.groupsPerChain.push_back(0); // increment with every group
94 | data.chainIdList.push_back(atom->chain);
95 | } else {
96 | is_same_residue = prevatom && prevatom->residue_number == atom->residue_number;
97 | }
98 |
99 | if (!is_same_residue) {
100 | data.groupsPerChain.back() += 1;
101 | data.groupTypeList.push_back(data.groupList.size());
102 | data.groupIdList.push_back(atom->residue_number);
103 | data.groupList.resize(data.groupList.size() + 1);
104 | residue = &data.groupList.back();
105 | residue->groupName = atom->residue_name;
106 | }
107 |
108 | residue->formalChargeList.push_back(atom->formal_charge);
109 | residue->atomNameList.push_back(atom->atom_name);
110 | residue->elementList.push_back(atom->element);
111 |
112 | prevatom = atom;
113 | }
114 |
115 | data.numAtoms = data.xCoordList.size();
116 | data.numGroups = data.groupIdList.size();
117 | data.numChains = data.chainIdList.size();
118 | data.numModels = data.chainsPerModel.size();
119 |
120 | // construct the BondAdder after adding atoms was completed
121 | mmtf::BondAdder bondadder(data);
122 |
123 | // add bonds
124 | for (const Bond* bond = bondarray; bond != ARRAYEND(bondarray); ++bond) {
125 | bondadder(bond->atom1, bond->atom2, bond->order);
126 | }
127 |
128 | std::cout << "INFO numBonds (total): " << data.numBonds << std::endl;
129 | std::cout << "INFO numBonds (inter-residue): " << (data.bondAtomList.size() / 2) << std::endl;
130 | std::cout << "INFO groupList.size() before compression: " << data.groupList.size() << std::endl;
131 |
132 | mmtf::compressGroupList(data);
133 |
134 | std::cout << "INFO groupList.size() after compression: " << data.groupList.size() << std::endl;
135 |
136 | // write to file if filename provided
137 | if (argc != 2) {
138 | printf("USAGE: export \n");
139 | } else {
140 | mmtf::encodeToFile(data, argv[1]);
141 | }
142 |
143 | return 0;
144 | }
145 |
146 | // vi:sw=2:expandtab
147 |
--------------------------------------------------------------------------------
/examples/traverse.cpp:
--------------------------------------------------------------------------------
1 | // *************************************************************************
2 | //
3 | // Licensed under the MIT License (see accompanying LICENSE file).
4 | //
5 | // The authors of this code are: Gerardo Tauriello
6 | //
7 | // The code is heavily based on traverse.c written by Julien Ferte from the
8 | // mmtf_c project
9 | //
10 | // *************************************************************************
11 |
12 | #include
13 |
14 | // C-style libraries used here to keep it close to traverse.c
15 | #include
16 | #include
17 | #include
18 |
19 | // *************************************************************************
20 | // JSON-style
21 | // *************************************************************************
22 |
23 | // printf for strings
24 | template
25 | void printval(const char* pff, const T& val) {
26 | printf(pff, val);
27 | }
28 | template<>
29 | void printval(const char* pff, const std::string& val) {
30 | printf(pff, val.c_str());
31 | }
32 |
33 | // print vector only
34 | template
35 | void printvec(const char* pff, const T* v, const size_t N) {
36 | printf("[");
37 | for (size_t i = 0; i < N; ++i) {
38 | if (i > 0) printf(", ");
39 | printval(pff, v[i]);
40 | }
41 | printf("]");
42 | }
43 |
44 | // writing with no check if it's set or not
45 | template
46 | void printreq(const char* label, const char* pff,
47 | const T* v, const size_t N, bool last = false) {
48 | printf("%s: ", label);
49 | printvec(pff, v, N);
50 | printf("%s\n", (last) ? "" : ",");
51 | }
52 |
53 | template
54 | void printreq(const char* label, const char* pff,
55 | const std::vector& v, bool last = false) {
56 | if (v.empty()) {
57 | printf("%s: []%s\n", label, (last) ? "" : ",");
58 | } else {
59 | printreq(label, pff, &v[0], v.size(), last);
60 | }
61 | }
62 |
63 | void printreq(const char* label, const std::string& s, bool last = false) {
64 | printf("%s: \"%s\"%s\n", label, s.c_str(), (last) ? "" : ",");
65 | }
66 |
67 | void printreq(const char* label, const float& f, bool last = false) {
68 | printf("%s: %g%s\n", label, f, (last) ? "" : ",");
69 | }
70 |
71 | // write with check if set
72 | template
73 | void printopt(const char* label, const T& val, bool last = false) {
74 | if (!mmtf::isDefaultValue(val)) {
75 | printreq(label, val, last);
76 | } else {
77 | printf("%s: null%s\n", label, (last) ? "" : ",");
78 | }
79 | }
80 |
81 | template
82 | void printopt(const char* label, const char* pff,
83 | const std::vector& vec, bool last = false) {
84 | if (!mmtf::isDefaultValue(vec)) {
85 | printreq(label, pff, vec, last);
86 | } else {
87 | printf("%s: null%s\n", label, (last) ? "" : ",");
88 | }
89 | }
90 |
91 | // JSON style printing of parts (not very elegant hack here)
92 | template
93 | void json_print(const T& t);
94 |
95 | template
96 | void json_print_list(const char* label, const T* v, const size_t N,
97 | int indent, bool last = false) {
98 | printf("%s: [", label);
99 | for (size_t i = 0; i < N; ++i) {
100 | if (i > 0) printf(",\n");
101 | else printf("\n");
102 | json_print(v[i]);
103 | }
104 | printf("\n%*s%s\n", indent+1, "]", (last) ? "" : ",");
105 | }
106 |
107 | template
108 | void json_print_list(const char* label, const std::vector& v,
109 | int indent, bool last = false) {
110 | json_print_list(label, &v[0], v.size(), indent, last);
111 | }
112 |
113 | // for optional vectors
114 | template
115 | void json_print_opt(const char* label, const std::vector& v,
116 | int indent, bool last = false) {
117 | if (!mmtf::isDefaultValue(v)) {
118 | json_print_list(label, &v[0], v.size(), indent, last);
119 | } else {
120 | printf("%s: null%s\n", label, (last) ? "" : ",");
121 | }
122 | }
123 |
124 | // just aimed for ncsOperatorList
125 | template<>
126 | void json_print(const std::vector& list) {
127 | printf(" ");
128 | printvec("%g", &list[0], list.size());
129 | }
130 |
131 | template<>
132 | void json_print(const mmtf::Transform& transform) {
133 | printf(" {\n");
134 | printreq(" \"chainIndexList\"", "%d", transform.chainIndexList);
135 | printreq(" \"matrix\"", "%g", transform.matrix, 16, true);
136 | printf(" }");
137 | }
138 |
139 | template<>
140 | void json_print(const mmtf::BioAssembly& ba) {
141 | printf(" {\n");
142 | printreq(" \"name\"", ba.name);
143 | json_print_list(" \"transformList\"", ba.transformList, 3, true);
144 | printf(" }");
145 | }
146 |
147 | template<>
148 | void json_print(const mmtf::Entity& ent) {
149 | printf(" {\n");
150 | printreq(" \"chainIndexList\"", "%d", ent.chainIndexList);
151 | printreq(" \"description\"", ent.description);
152 | printreq(" \"type\"", ent.type);
153 | printreq(" \"sequence\"", ent.sequence, true);
154 | printf(" }");
155 | }
156 |
157 | template<>
158 | void json_print(const mmtf::GroupType& group) {
159 | printf(" {\n");
160 | printreq(" \"formalChargeList\"", "%d", group.formalChargeList);
161 | printreq(" \"atomNameList\"", "\"%s\"", group.atomNameList);
162 | printopt(" \"bondAtomList\"", "%d", group.bondAtomList);
163 | printopt(" \"bondOrderList\"", "%d", group.bondOrderList);
164 | printopt(" \"bondResonanceList\"", "%d", group.bondResonanceList);
165 | printreq(" \"groupName\"", group.groupName);
166 | printf(" \"singleLetterCode\": \"%c\",\n", group.singleLetterCode);
167 | printreq(" \"chemCompType\"", group.chemCompType, true);
168 | printf(" }");
169 | }
170 |
171 | /**
172 | * @brief Raw output of the whole thing json style.
173 | */
174 | template<>
175 | void json_print(const mmtf::StructureData& example) {
176 | printf("{\n");
177 | // generic info
178 | printreq(" \"mmtfVersion\"", example.mmtfVersion);
179 | printreq(" \"mmtfProducer\"", example.mmtfProducer);
180 | printopt(" \"unitCell\"", "%g", example.unitCell);
181 | printopt(" \"spaceGroup\"", example.spaceGroup);
182 | printopt(" \"structureId\"", example.structureId);
183 | printopt(" \"title\"", example.title);
184 | printopt(" \"depositionDate\"", example.depositionDate);
185 | printopt(" \"releaseDate\"", example.releaseDate);
186 |
187 | // json_print_opt(" \"ncsOperatorList\"", example.ncsOperatorList, 1);
188 | json_print_opt(" \"bioAssemblyList\"", example.bioAssemblyList, 1);
189 | json_print_opt(" \"entityList\"", example.entityList, 1);
190 | printopt(" \"experimentalMethods\"", "\"%s\"", example.experimentalMethods);
191 |
192 | printopt(" \"resolution\"", example.resolution);
193 | printopt(" \"rFree\"", example.rFree);
194 | printopt(" \"rWork\"", example.rWork);
195 |
196 | printf(" \"numBonds\": %d,\n", example.numBonds);
197 | printf(" \"numAtoms\": %d,\n", example.numAtoms);
198 | printf(" \"numGroups\": %d,\n", example.numGroups);
199 | printf(" \"numChains\": %d,\n", example.numChains);
200 | printf(" \"numModels\": %d,\n", example.numModels);
201 |
202 | json_print_list(" \"groupList\"", example.groupList, 1);
203 |
204 | printopt(" \"bondAtomList\"", "%d", example.bondAtomList);
205 | printopt(" \"bondOrderList\"", "%d", example.bondOrderList);
206 | printopt(" \"bondResonanceList\"", "%d", example.bondResonanceList);
207 |
208 | printreq(" \"xCoordList\"", "%g", example.xCoordList);
209 | printreq(" \"yCoordList\"", "%g", example.yCoordList);
210 | printreq(" \"zCoordList\"", "%g", example.zCoordList);
211 | printopt(" \"bFactorList\"", "%g", example.bFactorList);
212 | printopt(" \"atomIdList\"", "%d", example.atomIdList);
213 | printopt(" \"altLocList\"", "%d", example.altLocList);
214 | printopt(" \"occupancyList\"", "%g", example.occupancyList);
215 |
216 | printreq(" \"groupIdList\"", "%d", example.groupIdList);
217 | printreq(" \"groupTypeList\"", "%d", example.groupTypeList);
218 | printopt(" \"secStructList\"", "%d", example.secStructList);
219 | printopt(" \"insCodeList\"", "%d", example.insCodeList);
220 | printopt(" \"sequenceIndexList\"", "%d", example.sequenceIndexList);
221 |
222 | printreq(" \"chainIdList\"", "\"%s\"", example.chainIdList);
223 | printopt(" \"chainNameList\"", "\"%s\"", example.chainNameList);
224 | printreq(" \"groupsPerChain\"", "%d", example.groupsPerChain);
225 | printreq(" \"chainsPerModel\"", "%d", example.chainsPerModel, true);
226 |
227 | printf("}\n");
228 | }
229 |
230 | // *************************************************************************
231 | // Verbose style
232 | // *************************************************************************
233 |
234 | /**
235 | * @brief If any value from
236 | * \link mmtf::StructureData::insCodeList insCodeList \endlink or
237 | * \link mmtf::StructureData::altLocList altLocList \endlink is empty,
238 | * it would would replace the character to a dot
239 | * @param c character which needs to be checked
240 | * @return The c character if it is not empty otherwise a dot
241 | */
242 | char safechar(char c) {
243 | return (c < ' ') ? '.' : c;
244 | }
245 |
246 | // helper for optional entries (printval(pff, vec[i]) only if vec given)
247 | template
248 | void printvalo(const char* pff, const std::vector& vec, size_t i) {
249 | if (!mmtf::isDefaultValue(vec)) printval(pff, vec[i]);
250 | }
251 | // helper for char entries (do safeprint of vec[i])
252 | template<>
253 | void printvalo(const char* pff, const std::vector& vec, size_t i) {
254 | if (!mmtf::isDefaultValue(vec)) printval(pff, safechar(vec[i]));
255 | }
256 |
257 | /**
258 | * @brief This is the main traversal function to read out all the contents of
259 | * mmtf::StructureData
260 | * @param example Any existing mmtf::StructureData which you want to read
261 | * @return void
262 | */
263 | void traverse_main(const mmtf::StructureData& example) {
264 | // generic info
265 | printreq("mmtfVersion", example.mmtfVersion, true);
266 | printreq("mmtfProducer", example.mmtfProducer, true);
267 | printopt("unitCell", "%g", example.unitCell, true);
268 | printopt("spaceGroup", example.spaceGroup, true);
269 | printopt("structureId", example.structureId, true);
270 | printopt("title", example.title, true);
271 | printopt("depositionDate", example.depositionDate, true);
272 | printopt("releaseDate", example.releaseDate, true);
273 |
274 | for (size_t i = 0; i < example.ncsOperatorList.size(); ++i) {
275 | printf("ncsOperatorList[%d]", int(i));
276 | printreq("", "%g", example.ncsOperatorList[i], true);
277 | }
278 |
279 | for (size_t i = 0; i < example.bioAssemblyList.size(); ++i) {
280 | printf("bioAssemblyIndex: %d\n", int(i));
281 | const mmtf::BioAssembly& ba = example.bioAssemblyList[i];
282 | printreq(" name", ba.name, true);
283 | for (size_t j = 0; j < ba.transformList.size(); ++j) {
284 | printf(" bioAssemblyTransformIndex: %d\n", int(j));
285 | const mmtf::Transform & transform = ba.transformList[j];
286 | printreq(" chainIndexList", "%d", transform.chainIndexList, true);
287 | printreq(" matrix", "%g", transform.matrix, 16, true);
288 | }
289 | }
290 |
291 | for (size_t i = 0; i < example.entityList.size(); ++i) {
292 | printf("entityIndex: %d\n", int(i));
293 | const mmtf::Entity& ent = example.entityList[i];
294 | printreq(" chainIndexList", "%d", ent.chainIndexList, true);
295 | printreq(" description", ent.description, true);
296 | printreq(" type", ent.type, true);
297 | printreq(" sequence", ent.sequence, true);
298 | }
299 |
300 | for (size_t i = 0; i < example.experimentalMethods.size(); ++i) {
301 | printf("experimentalMethod %d: %s\n", int(i),
302 | example.experimentalMethods[i].c_str());
303 | }
304 |
305 | printopt("resolution", example.resolution, true);
306 | printopt("rFree", example.rFree, true);
307 | printopt("rWork", example.rWork, true);
308 |
309 | printf("numBonds: %d\n", example.numBonds);
310 | printf("numAtoms: %d\n", example.numAtoms);
311 | printf("numGroups: %d\n", example.numGroups);
312 | printf("numChains: %d\n", example.numChains);
313 | printf("numModels: %d\n", example.numModels);
314 |
315 | // # initialize index counters
316 | int modelIndex = 0;
317 | int chainIndex = 0;
318 | int groupIndex = 0;
319 | int atomIndex = 0;
320 | //# traverse models
321 | int i;
322 | for (i = 0; i < example.numModels; i++) {
323 | int modelChainCount = example.chainsPerModel[i];
324 | printf("modelIndex: %d\n", modelIndex);
325 | // # traverse chains
326 | int j;
327 | for (j = 0; j < modelChainCount; j++) {
328 | printf(" chainIndex : %d\n", chainIndex);
329 | printval(" Chain id: %s\n", example.chainIdList[chainIndex]);
330 | printvalo(" Chain name: %s\n", example.chainNameList, chainIndex);
331 | int chainGroupCount = example.groupsPerChain[chainIndex];
332 | // # traverse groups
333 | int k;
334 | for (k = 0; k < chainGroupCount; k++) {
335 | printf(" groupIndex: %d\n", groupIndex);
336 | printf(" groupId: %d\n", example.groupIdList[groupIndex]);
337 | printvalo(" insCodeList: %c\n", example.insCodeList,
338 | groupIndex);
339 | printvalo(" secStruc: %d\n", example.secStructList,
340 | groupIndex);
341 | printvalo(" seqIndex: %i\n", example.sequenceIndexList,
342 | groupIndex);
343 | printf(" groupType: %d\n", example.groupTypeList[groupIndex]);
344 | const mmtf::GroupType& group =
345 | example.groupList[example.groupTypeList[groupIndex]];
346 | printval(" Group name: %s\n", group.groupName);
347 | printf(" Single letter code: %c\n", group.singleLetterCode);
348 | printval(" Chem comp type: %s\n", group.chemCompType);
349 | int atomOffset = atomIndex;
350 |
351 | int l;
352 | for (l = 0; l < group.bondAtomList.size(); l += 2) {
353 | printf(" Atom id One: %d\n",
354 | (atomOffset + group.bondAtomList[l]));
355 | printf(" Atom id Two: %d\n",
356 | (atomOffset + group.bondAtomList[l + 1]));
357 | printvalo(" Bond order: %d\n",
358 | group.bondOrderList, l / 2);
359 | printvalo(" Bond resonance: %d\n",
360 | group.bondResonanceList, l / 2);
361 | }
362 | int groupAtomCount = group.atomNameList.size();
363 | for (l = 0; l < groupAtomCount; l++) {
364 | printf(" atomIndex: %d\n", atomIndex);
365 | printf(" x coord: %.3f\n",
366 | example.xCoordList[atomIndex]);
367 | printf(" y coord: %.3f\n",
368 | example.yCoordList[atomIndex]);
369 | printf(" z coord: %.3f\n",
370 | example.zCoordList[atomIndex]);
371 | printvalo(" b factor: %.2f\n", example.bFactorList,
372 | atomIndex);
373 | printvalo(" atom id: %d\n", example.atomIdList,
374 | atomIndex);
375 | printvalo(" altLocList: %c\n", example.altLocList,
376 | atomIndex);
377 | printvalo(" occupancy: %.2f\n", example.occupancyList,
378 | atomIndex);
379 | printf(" charge: %d\n", group.formalChargeList[l]);
380 | printval(" atom name: %s\n", group.atomNameList[l]);
381 | printval(" element: %s\n", group.elementList[l]);
382 | atomIndex++;
383 | }
384 | groupIndex++;
385 | }
386 | chainIndex++;
387 | }
388 | modelIndex++;
389 | }
390 | printf("Number of inter group bonds: %d\n",
391 | (int) example.bondAtomList.size() / 2);
392 | for (i = 0; i < example.bondAtomList.size(); i += 2) {
393 | printf(" Atom One: %d\n", example.bondAtomList[i]);
394 | printf(" Atom Two: %d\n", example.bondAtomList[i + 1]);
395 | printvalo(" Bond order: %d\n", example.bondOrderList, i / 2);
396 | printvalo(" Bond resonance: %d\n", example.bondResonanceList, i / 2);
397 | }
398 | }
399 |
400 | // *************************************************************************
401 | // PDB style
402 | // *************************************************************************
403 |
404 | /**
405 | * @brief Read out the contents of mmtf::StructureData in a PDB-like fashion
406 | * Columns are in order:
407 | * ATOM/HETATM AtomId Element AtomName AltLoc GroupId GroupType
408 | * InsCode ChainName x y z B-factor Occupancy Charge
409 | * @param example Any existing mmtf::StructureData which you want to read
410 | */
411 | void traverse_pdb_like(const mmtf::StructureData& example) {
412 |
413 |
414 | int modelIndex = 0;
415 | int chainIndex = 0;
416 | int groupIndex = 0;
417 | int atomIndex = 0;
418 |
419 | //# traverse models
420 | for (int i = 0; i < example.numModels; i++, modelIndex++) {
421 | // # traverse chains
422 | for (int j = 0; j < example.chainsPerModel[modelIndex]; j++, chainIndex++) {
423 | // # traverse groups
424 | for (int k = 0; k < example.groupsPerChain[chainIndex]; k++, groupIndex++) {
425 | const mmtf::GroupType& group =
426 | example.groupList[example.groupTypeList[groupIndex]];
427 | int groupAtomCount = group.atomNameList.size();
428 |
429 | for (int l = 0; l < groupAtomCount; l++, atomIndex++) {
430 | // ATOM or HETATM
431 | if (mmtf::is_hetatm(chainIndex, example.entityList, group))
432 | printf("HETATM ");
433 | else
434 | printf("ATOM ");
435 | // Atom serial
436 | printvalo("%d ", example.atomIdList, atomIndex);
437 | // Atom name
438 | printval("%s ", group.atomNameList[l]);
439 | // Alternate location
440 | printvalo("%c ", example.altLocList, atomIndex);
441 | // Group name
442 | printval("%s ", group.groupName);
443 | // Chain
444 | printvalo("%s ", example.chainNameList, chainIndex);
445 | // Group serial
446 | printf("%d ", example.groupIdList[groupIndex]);
447 | // Insertion code
448 | printvalo("%c ", example.insCodeList, groupIndex);
449 | // x, y, z
450 | printf("%.3f ", example.xCoordList[atomIndex]);
451 | printf("%.3f ", example.yCoordList[atomIndex]);
452 | printf("%.3f ", example.zCoordList[atomIndex]);
453 | // B-factor
454 | printvalo("%.2f ", example.bFactorList, atomIndex);
455 | // Occupancy
456 | printvalo("%.2f ", example.occupancyList, atomIndex);
457 | // Element
458 | printval("%s ", group.elementList[l]);
459 | // Charge
460 | printf("%d \n", group.formalChargeList[l]);
461 | }
462 | }
463 | }
464 | }
465 | }
466 |
467 | int main(int argc, char** argv) {
468 | // check arguments
469 | if (argc < 2) {
470 | printf("USAGE: traverse [