Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 47 additions & 5 deletions examples/traverse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// C-style libraries used here to keep it close to traverse.c
#include <stdio.h>
#include <string.h>
#include <assert.h>

// *************************************************************************
// JSON-style
Expand Down Expand Up @@ -121,6 +120,39 @@ void json_print_opt(const char* label, const std::vector<T>& v,
}
}

// for optional map-data (extra props)
template<typename T>
void json_print_opt(const char* label, const std::map<std::string, T>& m,
int indent, bool last = false) {
if (!mmtf::isDefaultValue(m)) {
printf("%s: {", label);
typename std::map<std::string, T>::const_iterator it;
for (it = m.begin(); it != m.end(); ++it) {
if (it != m.begin()) printf(",");
printf("\n%*s\"%s\": null", indent+1, " ", it->first.c_str());
}
printf("\n%*s%s\n", indent+1, "}", (last) ? "" : ",");
} else {
printf("%s: null%s\n", label, (last) ? "" : ",");
}
}

// define how to print vectors of chars (hard-coded)
// -> either list of numbers or converted to strings
void json_print_opt_chars(const char* label,
const std::vector<char>& vec, bool last = false) {
// v1: use numbers
// printopt(label, "%d", vec, last);
// v2: convert to string first
std::vector<std::string> tmp;
tmp.reserve(vec.size());
for (size_t i = 0; i < vec.size(); ++i) {
if (vec[i] == 0x00) tmp.push_back(std::string());
else tmp.push_back(std::string(1, vec[i]));
}
printopt(label, "\"%s\"", tmp, last);
}

// just aimed for ncsOperatorList
template<>
void json_print(const std::vector<float>& list) {
Expand Down Expand Up @@ -159,6 +191,7 @@ void json_print(const mmtf::GroupType& group) {
printf(" {\n");
printreq(" \"formalChargeList\"", "%d", group.formalChargeList);
printreq(" \"atomNameList\"", "\"%s\"", group.atomNameList);
printreq(" \"elementList\"", "\"%s\"", group.elementList);
printopt(" \"bondAtomList\"", "%d", group.bondAtomList);
printopt(" \"bondOrderList\"", "%d", group.bondOrderList);
printopt(" \"bondResonanceList\"", "%d", group.bondResonanceList);
Expand All @@ -184,7 +217,7 @@ void json_print(const mmtf::StructureData& example) {
printopt(" \"depositionDate\"", example.depositionDate);
printopt(" \"releaseDate\"", example.releaseDate);

// json_print_opt(" \"ncsOperatorList\"", example.ncsOperatorList, 1);
json_print_opt(" \"ncsOperatorList\"", example.ncsOperatorList, 1);
json_print_opt(" \"bioAssemblyList\"", example.bioAssemblyList, 1);
json_print_opt(" \"entityList\"", example.entityList, 1);
printopt(" \"experimentalMethods\"", "\"%s\"", example.experimentalMethods);
Expand All @@ -210,19 +243,26 @@ void json_print(const mmtf::StructureData& example) {
printreq(" \"zCoordList\"", "%g", example.zCoordList);
printopt(" \"bFactorList\"", "%g", example.bFactorList);
printopt(" \"atomIdList\"", "%d", example.atomIdList);
printopt(" \"altLocList\"", "%d", example.altLocList);
json_print_opt_chars(" \"altLocList\"", example.altLocList);
printopt(" \"occupancyList\"", "%g", example.occupancyList);

printreq(" \"groupIdList\"", "%d", example.groupIdList);
printreq(" \"groupTypeList\"", "%d", example.groupTypeList);
printopt(" \"secStructList\"", "%d", example.secStructList);
printopt(" \"insCodeList\"", "%d", example.insCodeList);
json_print_opt_chars(" \"insCodeList\"", example.insCodeList);
printopt(" \"sequenceIndexList\"", "%d", example.sequenceIndexList);

printreq(" \"chainIdList\"", "\"%s\"", example.chainIdList);
printopt(" \"chainNameList\"", "\"%s\"", example.chainNameList);
printreq(" \"groupsPerChain\"", "%d", example.groupsPerChain);
printreq(" \"chainsPerModel\"", "%d", example.chainsPerModel, true);
printreq(" \"chainsPerModel\"", "%d", example.chainsPerModel);

json_print_opt(" \"bondProperties\"", example.bondProperties, 1);
json_print_opt(" \"atomProperties\"", example.atomProperties, 1);
json_print_opt(" \"groupProperties\"", example.groupProperties, 1);
json_print_opt(" \"chainProperties\"", example.chainProperties, 1);
json_print_opt(" \"modelProperties\"", example.modelProperties, 1);
json_print_opt(" \"extraProperties\"", example.extraProperties, 1, true);

printf("}\n");
}
Expand Down Expand Up @@ -483,6 +523,8 @@ int main(int argc, char** argv) {
if (argc > 2) {
if (strcmp(argv[2], "json") == 0) {
json_print(example);
} else if (strcmp(argv[2], "sd_json") == 0) {
std::cout << example.to_json() << std::endl;
} else if (strcmp(argv[2], "print") == 0) {
std::cout << example.print() << std::endl;
} else {
Expand Down
91 changes: 91 additions & 0 deletions include/mmtf/structure_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ struct StructureData {
*/
std::string print(std::string delim="\t") const;

/**
* @brief Read out the contents of mmtf::StructureData to json (unencoded)
*/
std::string to_json() const;

/**
* @brief Compare two StructureData classes for equality
* @param c What to compare to
Expand Down Expand Up @@ -1104,6 +1109,92 @@ inline std::string StructureData::print(std::string delim) const {
return out.str();
}

inline std::string StructureData::to_json() const {
msgpack::zone zone;
std::map<std::string, msgpack::object> json_out;

json_out["mmtfVersion"] = msgpack::object(mmtfVersion, zone);
json_out["mmtfProducer"] = msgpack::object(mmtfProducer, zone);
json_out["unitCell"] = msgpack::object(unitCell, zone);
json_out["spaceGroup"] = msgpack::object(spaceGroup, zone);
json_out["structureId"] = msgpack::object(structureId, zone);
json_out["title"] = msgpack::object(title, zone);
json_out["depositionDate"] = msgpack::object(depositionDate, zone);
json_out["releaseDate"] = msgpack::object(releaseDate, zone);
json_out["ncsOperatorList"] = msgpack::object(ncsOperatorList, zone);
json_out["bioAssemblyList"] = msgpack::object(bioAssemblyList, zone);
json_out["entityList"] = msgpack::object(entityList, zone);
json_out["experimentalMethods"] = msgpack::object(experimentalMethods, zone);
json_out["resolution"] = msgpack::object(resolution, zone);
json_out["rFree"] = msgpack::object(rFree, zone);
json_out["rWork"] = msgpack::object(rWork, zone);
json_out["numBonds"] = msgpack::object(numBonds, zone);
json_out["numAtoms"] = msgpack::object(numAtoms, zone);
json_out["numGroups"] = msgpack::object(numGroups, zone);
json_out["numChains"] = msgpack::object(numChains, zone);
json_out["numModels"] = msgpack::object(numModels, zone);
json_out["groupList"] = msgpack::object(groupList, zone);
json_out["bondAtomList"] = msgpack::object(bondAtomList, zone);
{
std::vector<int32_t> tmp_bol(bondOrderList.begin(), bondOrderList.end());
json_out["bondOrderList"] = msgpack::object(tmp_bol, zone);
}
{
std::vector<int32_t> tmp_brl(bondResonanceList.begin(), bondResonanceList.end());
json_out["bondResonanceList"] = msgpack::object(bondResonanceList, zone);
}
json_out["xCoordList"] = msgpack::object(xCoordList, zone);
json_out["yCoordList"] = msgpack::object(yCoordList, zone);
json_out["zCoordList"] = msgpack::object(zCoordList, zone);
json_out["bFactorList"] = msgpack::object(bFactorList, zone);
json_out["atomIdList"] = msgpack::object(atomIdList, zone);
{
std::vector<std::string> tmp_all;
for (unsigned int i = 0; i < altLocList.size(); ++i) {
if (altLocList[i] == 0x00) {
tmp_all.push_back(std::string());
} else {
tmp_all.push_back(std::string(1, altLocList[i]));
}
}
json_out["altLocList"] = msgpack::object(tmp_all, zone);
}

json_out["occupancyList"] = msgpack::object(occupancyList, zone);
json_out["groupIdList"] = msgpack::object(groupIdList, zone);
json_out["groupTypeList"] = msgpack::object(groupTypeList, zone);
{
std::vector<int32_t> tmp_ssl(secStructList.begin(), secStructList.end());
json_out["secStructList"] = msgpack::object(tmp_ssl, zone);
}
{
std::vector<std::string> tmp_icl;
for (unsigned int i = 0; i < insCodeList.size(); ++i) {
if (insCodeList[i] == 0x00) {
tmp_icl.push_back(std::string());
} else {
tmp_icl.push_back(std::string(1, insCodeList[i]));
}
}
json_out["insCodeList"] = msgpack::object(tmp_icl, zone);
}
json_out["sequenceIndexList"] = msgpack::object(sequenceIndexList, zone);
json_out["chainIdList"] = msgpack::object(chainIdList, zone);
json_out["chainNameList"] = msgpack::object(chainNameList, zone);
json_out["groupsPerChain"] = msgpack::object(groupsPerChain, zone);
json_out["chainsPerModel"] = msgpack::object(chainsPerModel, zone);
json_out["bondProperties"] = msgpack::object(bondProperties, zone);
json_out["atomProperties"] = msgpack::object(atomProperties, zone);
json_out["groupProperties"] = msgpack::object(groupProperties, zone);
json_out["chainProperties"] = msgpack::object(chainProperties, zone);
json_out["modelProperties"] = msgpack::object(modelProperties, zone);
json_out["extraProperties"] = msgpack::object(extraProperties, zone);
std::stringstream ss;
msgpack::object f(json_out, zone);
ss << f;
return ss.str();
}

inline void StructureData::copyMapData_(
std::map<std::string, msgpack::object>& target,
const std::map<std::string, msgpack::object>& source) {
Expand Down
7 changes: 7 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ else()
target_link_libraries(multi_cpp_test MMTFcpp)
endif()

add_executable(to_json to_json.cpp)
if(WIN32)
target_link_libraries(to_json MMTFcpp ws2_32)
else()
target_link_libraries(to_json MMTFcpp)
endif()

set(TEST_RUNNER "none" CACHE STRING "External runner for the tests")

if (${TEST_RUNNER} STREQUAL "node")
Expand Down
55 changes: 55 additions & 0 deletions tests/mmtf_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,61 @@ TEST_CASE("Test is_hetatm (chain_index version)") {
}
}

// We dont have a json library, but we can check for basic stuff since
// we're mostly relying on the msgpack library to do this for us.
TEST_CASE("Test json") {
std::string working_mmtf = "../temporary_test_data/3zqs.mmtf";
mmtf::StructureData sd;
mmtf::decodeFromFile(sd, working_mmtf);
std::string const json_text(sd.to_json());
REQUIRE(json_text.find("mmtfVersion\":") != std::string::npos);
REQUIRE(json_text.find("mmtfProducer\":") != std::string::npos);
REQUIRE(json_text.find("unitCell\":") != std::string::npos);
REQUIRE(json_text.find("spaceGroup\":") != std::string::npos);
REQUIRE(json_text.find("structureId\":") != std::string::npos);
REQUIRE(json_text.find("title\":") != std::string::npos);
REQUIRE(json_text.find("depositionDate\":") != std::string::npos);
REQUIRE(json_text.find("releaseDate\":") != std::string::npos);
REQUIRE(json_text.find("ncsOperatorList\":") != std::string::npos);
REQUIRE(json_text.find("bioAssemblyList\":") != std::string::npos);
REQUIRE(json_text.find("entityList\":") != std::string::npos);
REQUIRE(json_text.find("experimentalMethods\":") != std::string::npos);
REQUIRE(json_text.find("resolution\":") != std::string::npos);
REQUIRE(json_text.find("rFree\":") != std::string::npos);
REQUIRE(json_text.find("rWork\":") != std::string::npos);
REQUIRE(json_text.find("numBonds\":") != std::string::npos);
REQUIRE(json_text.find("numAtoms\":") != std::string::npos);
REQUIRE(json_text.find("numGroups\":") != std::string::npos);
REQUIRE(json_text.find("numChains\":") != std::string::npos);
REQUIRE(json_text.find("numModels\":") != std::string::npos);
REQUIRE(json_text.find("groupList\":") != std::string::npos);
REQUIRE(json_text.find("bondAtomList\":") != std::string::npos);
REQUIRE(json_text.find("bondOrderList\":") != std::string::npos);
REQUIRE(json_text.find("bondResonanceList\":") != std::string::npos);
REQUIRE(json_text.find("xCoordList\":") != std::string::npos);
REQUIRE(json_text.find("yCoordList\":") != std::string::npos);
REQUIRE(json_text.find("zCoordList\":") != std::string::npos);
REQUIRE(json_text.find("bFactorList\":") != std::string::npos);
REQUIRE(json_text.find("atomIdList\":") != std::string::npos);
REQUIRE(json_text.find("altLocList\":") != std::string::npos);
REQUIRE(json_text.find("occupancyList\":") != std::string::npos);
REQUIRE(json_text.find("groupIdList\":") != std::string::npos);
REQUIRE(json_text.find("groupTypeList\":") != std::string::npos);
REQUIRE(json_text.find("secStructList\":") != std::string::npos);
REQUIRE(json_text.find("insCodeList\":") != std::string::npos);
REQUIRE(json_text.find("sequenceIndexList\":") != std::string::npos);
REQUIRE(json_text.find("chainIdList\":") != std::string::npos);
REQUIRE(json_text.find("chainNameList\":") != std::string::npos);
REQUIRE(json_text.find("groupsPerChain\":") != std::string::npos);
REQUIRE(json_text.find("chainsPerModel\":") != std::string::npos);
REQUIRE(json_text.find("bondProperties\":") != std::string::npos);
REQUIRE(json_text.find("atomProperties\":") != std::string::npos);
REQUIRE(json_text.find("groupProperties\":") != std::string::npos);
REQUIRE(json_text.find("chainProperties\":") != std::string::npos);
REQUIRE(json_text.find("modelProperties\":") != std::string::npos);
REQUIRE(json_text.find("extraProperties\":") != std::string::npos);
}


#ifdef __EMSCRIPTEN__
#include <emscripten.h>
Expand Down
17 changes: 17 additions & 0 deletions tests/to_json.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// *************************************************************************
//
// Simple test for compilation issues.
//
// *************************************************************************

#include <mmtf.hpp>

int main(int argc, char** argv) {
// decode MMTF file
std::string const filename(argv[1]);
mmtf::StructureData data;
mmtf::decodeFromFile(data, filename);
std::cout << data.to_json() << std::endl;

return 0;
}