├── .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 | [![Release](https://img.shields.io/github/v/release/rcsb/mmtf-cpp)](https://github.com/rcsb/mmtf-cpp/releases) 3 | [![License](https://img.shields.io/github/license/rcsb/mmtf-cpp)](https://github.com/rcsb/mmtf-cpp/blob/master/LICENSE) 4 | [![Build Status (Travis)](https://img.shields.io/travis/com/rcsb/mmtf-cpp/master)](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 [