Skip to content

Commit

Permalink
Add+test simple JSON to superposition_context code
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyelewis committed Aug 27, 2015
1 parent 3e8fdf0 commit 10303f0
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 10 deletions.
105 changes: 102 additions & 3 deletions source/superposition/superposition_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@

#include "superposition_context.h"

#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/log/trivial.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm_ext/for_each.hpp>

#include "alignment/alignment_context.h"
Expand All @@ -33,17 +36,22 @@
#include "file/pdb/pdb_atom.h"
#include "file/pdb/pdb_residue.h"
#include "options/options_block/data_dirs_options_block.h"
#include "structure/structure_type_aliases.h"
#include "superposition/io/superposition_io.h"

using namespace cath;
using namespace cath::align;
using namespace cath::common;
using namespace cath::file;
using namespace cath::geom;
using namespace cath::opts;
using namespace cath::sup;
using namespace cath::sup::detail;
using namespace std;

using boost::adaptors::map_values;
using boost::adaptors::transformed;
using boost::algorithm::any_of;
using boost::filesystem::path;
using boost::log::trivial::severity_level;
using boost::property_tree::json_parser::write_json;
Expand Down Expand Up @@ -115,6 +123,22 @@ void superposition_context::set_pdbs(const pdb_list &arg_pdbs ///< The PDBs to s
pdbs = arg_pdbs;
}

///// \brief TODOCUMENT
/////
///// \relates superposition_context
//bool cath::sup::operator==(const superposition_context &arg_sup_con_a, ///< TODOCUMENT
// const superposition_context &arg_sup_con_b ///< TODOCUMENT
// ) {
//}

///// \brief TODOCUMENT
/////
///// \relates superposition_context
//ostream & cath::sup::operator<<(ostream &arg_os, ///< TODOCUMENT
// const superposition_context &arg_sup_con ///< TODOCUMENT
// ) {
//}

/// \brief Get the number of entries in the specified superposition_context
///
/// \relates superposition_context
Expand Down Expand Up @@ -166,6 +190,71 @@ alignment_context cath::sup::make_alignment_context(const superposition_context
);
}

/// \brief Build a coord from a superposition_context-populated ptree
///
/// \relates superposition_context
superposition_context cath::sup::superposition_context_from_ptree(const ptree &arg_ptree ///< The ptree from which the superposition_context should be read
) {
// Define a lambda for checking whether an entry ptree is invalid
const auto entry_is_invalid = [] (const ptree &x) {
return ( x.size() != 2
|| x.count( superposition_io_consts::NAME_KEY ) != 1
|| x.count( superposition_io_consts::TRANSFORMATION_KEY ) != 1 );
};

// Define a lambda for returning an entry ptree's transformation ptree child
const auto get_transformation_child = [] (const ptree &x) {
return x.get_child( superposition_io_consts::TRANSFORMATION_KEY );
};

// Sanity check the ptree [ Step 1: check there's one key, which is entries ]
if ( arg_ptree.size() != 1 || arg_ptree.count( superposition_io_consts::ENTRIES_KEY ) != 1 ) {
BOOST_THROW_EXCEPTION(invalid_argument_exception(""));
}
const auto entries = arg_ptree.get_child( superposition_io_consts::ENTRIES_KEY );

// Sanity check the ptree [ Step 2: check that all entries have empty keys ]
if ( entries.size() != entries.count( "" ) ) {
BOOST_THROW_EXCEPTION(invalid_argument_exception(""));
}

// Sanity check the ptree [ Step 3: check that all values contain exactly two keys, name and transformation ]
if ( any_of( entries | map_values, entry_is_invalid ) ) {
BOOST_THROW_EXCEPTION(runtime_error_exception(""));
}

// Read the names
const auto names = transform_build<str_vec>(
entries | map_values,
[] (const ptree &x) {
return x.get<string>( superposition_io_consts::NAME_KEY );
}
);

// Read the translations
const auto translations = transform_build<coord_vec>(
entries | map_values | transformed( get_transformation_child ),
[] (const ptree &x) {
return coord_from_ptree( x.get_child( superposition_io_consts::TRANSLATION_KEY ) );
}
);

// Parse the rotations
const auto rotations = transform_build<rotation_vec>(
entries | map_values | transformed( get_transformation_child ),
[] (const ptree &x) {
return rotation_from_ptree( x.get_child( superposition_io_consts::ROTATION_KEY ) );
}
);

// Return a superposition_context built from the parsed data
return {
pdb_list{ pdb_vec{ names.size() } },
names,
superposition{ translations, rotations }
};
}

/// \brief TODOCUMENT
///
/// At present, this stores the names and the superposition but does nothing
Expand All @@ -182,9 +271,8 @@ void cath::sup::save_to_ptree(ptree &arg_ptree, ///<
const auto supn_ptree = make_ptree_of( arg_sup_context.get_superposition_cref() );
const auto trans_ptrees = supn_ptree.get_child( superposition_io_consts::TRANSFORMATIONS_KEY );

const auto entries_key = superposition_io_consts::ENTRIES_KEY;
arg_ptree.put_child( entries_key, ptree{} );
auto &entries_ptree = arg_ptree.get_child( entries_key );
arg_ptree.put_child( superposition_io_consts::ENTRIES_KEY, ptree{} );
auto &entries_ptree = arg_ptree.get_child( superposition_io_consts::ENTRIES_KEY );

for_each(
arg_sup_context.get_names_cref(),
Expand All @@ -211,6 +299,17 @@ ptree cath::sup::make_ptree_of(const superposition_context &arg_sup_context ///<
return new_ptree;
}

/// \brief Build a superposition_context from a JSON string (via a ptree)
///
/// \relates superposition_context
superposition_context cath::sup::superposition_context_from_json_string(const string &arg_json_string ///< The JSON string from which the superposition_context should be read
) {
ptree tree;
istringstream in_ss( arg_json_string );
read_json( in_ss, tree);
return superposition_context_from_ptree( tree );
}

/// \brief Create a JSON string to represent the specified superposition
///
/// At present, this stores the names and the superposition but does nothing
Expand Down
13 changes: 12 additions & 1 deletion source/superposition/superposition_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#ifndef SUPERPOSITION_CONTEXT_H_INCLUDED
#define SUPERPOSITION_CONTEXT_H_INCLUDED

#include <boost/operators.hpp>
#include <boost/optional.hpp>

#include "alignment/alignment.h"
Expand All @@ -38,7 +39,7 @@ namespace cath {
///
/// ATM, this is little more than a tuple<pdb_list, str_vec, superposition> with nice names and extra functionality
/// of optionally storing an alignment
class superposition_context final {
class superposition_context final : private boost::equality_comparable<superposition_context> {
private:
/// \brief The PDBs for the entries being superposed
file::pdb_list pdbs;
Expand Down Expand Up @@ -70,6 +71,12 @@ namespace cath {
void set_pdbs(const file::pdb_list &);
};

// bool operator==(const superposition_context &,
// const superposition_context &);

// std::ostream & operator<<(std::ostream &,
// const superposition_context &);

size_t get_num_entries(const superposition_context &);

void load_pdbs_from_names(superposition_context &,
Expand All @@ -80,11 +87,15 @@ namespace cath {

align::alignment_context make_alignment_context(const superposition_context &);

superposition_context superposition_context_from_ptree(const boost::property_tree::ptree &);

void save_to_ptree(boost::property_tree::ptree &,
const superposition_context &);

boost::property_tree::ptree make_ptree_of(const superposition_context &);

superposition_context superposition_context_from_json_string(const std::string &);

std::string to_json_string(const superposition_context &,
const bool &arg_pretty_print = true);
}
Expand Down
26 changes: 20 additions & 6 deletions source/superposition/superposition_context_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <boost/test/auto_unit_test.hpp>

#include "common/boost_addenda/test/boost_check_equal_ranges.h"
#include "file/pdb/pdb.h"
#include "file/pdb/pdb_atom.h"
#include "file/pdb/pdb_list.h"
Expand All @@ -29,6 +30,7 @@
#include "superposition/superposition_context.h"
#include "test/global_test_constants.h"

using namespace cath::common;
using namespace cath::file;
using namespace cath::geom;
using namespace cath::opts;
Expand All @@ -46,12 +48,10 @@ namespace cath {

const coord_list coord_list_1{ { coord{ 1.0, 0.0, 0.0 }, coord{ 2.0, 0.0, 0.0 } } };
const coord_list coord_list_2{ { coord{ 0.0, -1.0, 0.0 }, coord{ 0.0, -2.0, 0.0 } } };
const superposition the_sup = create_pairwise_superposition( coord_list_1, coord_list_2 );
const superposition_context the_sup_con {
pdb_list{ pdb_vec{ 2, pdb{} } },
str_vec { "1c0pA01", "1hdoA00" },
the_sup
};
const pdb_list pdbs{ pdb_vec{ 2, pdb{} } };
const str_vec names{ "1c0pA01", "1hdoA00" };
const superposition the_sup{ create_pairwise_superposition( coord_list_1, coord_list_2 ) };
const superposition_context the_sup_con{ pdbs, names, the_sup };
const string json_string = R"({"entries":[{"name":"1c0pA01","transformation":{"translation":)"
R"({"x":"0","y":"0","z":"0"},)"
R"("rotation":)"
Expand Down Expand Up @@ -95,6 +95,20 @@ BOOST_AUTO_TEST_CASE(to_json_string_works_for_example_sup_con) {
);
}

BOOST_AUTO_TEST_CASE(from_json_string_works) {
cerr << to_json_string( the_sup_con, true ) << "\n";
const auto from_json_string = superposition_context_from_json_string( json_string );
BOOST_REQUIRE_EQUAL ( from_json_string.get_pdbs_cref().size(), 2 );
BOOST_CHECK_EQUAL ( from_json_string.get_pdbs_cref()[ 0 ].get_num_residues(), 0 );
BOOST_CHECK_EQUAL ( from_json_string.get_pdbs_cref()[ 1 ].get_num_residues(), 0 );

BOOST_CHECK_EQUAL_RANGES( from_json_string.get_names_cref(), names );

BOOST_CHECK_EQUAL ( from_json_string.get_superposition_cref(), the_sup );

BOOST_CHECK_EQUAL ( from_json_string.has_alignment(), false );
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()
Expand Down

0 comments on commit 10303f0

Please sign in to comment.