Commit 22e6d320 authored by Tauriello Gerardo's avatar Tauriello Gerardo

IO update and "extras/test_code" for low-level C++ testing.

- added check_io headers for torsion sampler binaries
- code in extras/test_code can be used to access low-level C++ features
parent 4d9a86fb
......@@ -3,7 +3,6 @@ stage/
\.AppleDouble
\.DS_Store
build*/
Makefile
*.cmake
CMakeFiles
CMakeCache*
......@@ -15,6 +15,7 @@
/// - type-sizes can be checked to be exactly as expected (or bigger if the
/// used stream allows for conversions)
/// - an example value for the used base-types can be checked
/// (see test_check_io.cc for simple example)
///
/// All write functions (when saving a binary) should be mirrored by the
/// corresponsing check (or get) function in the exact same order when loading.
......@@ -68,20 +69,24 @@ void ReadRaw(std::ifstream& stream, T& t) {
} // anon ns
/// \brief Write a base-type value to a stream
template <typename STREAM, typename T>
void WriteBaseType(STREAM& stream, const T t) {
/// By default the value "1" is converted to T and written.
/// Default is ok for integers, floating points, and most enums.
/// Value needs to be overridden for enums and any non-inte
template <typename T, typename STREAM>
void WriteBaseType(STREAM& stream, const T t = T(1)) {
WriteRaw(stream, t);
}
/// \brief Check that read base-type value has expected value
/// By default the value "1" is expected (needs to match WriteBaseType).
/// \throw Error if read-value doesn't match the expected value
template <typename STREAM, typename T>
void CheckBaseType(STREAM& stream, const T expected) {
template <typename T, typename STREAM>
void CheckBaseType(STREAM& stream, const T expected = T(1)) {
T value;
ReadRaw(stream, value);
if (value != expected) {
std::stringstream ss;
ss << "Failed to read " << value << " correctly, expected " << expected;
ss << "Failed to read " << expected << " correctly, got " << value;
throw promod3::Error(ss.str());
}
}
......
......@@ -24,46 +24,48 @@ BOOST_AUTO_TEST_CASE(test_check_io_fstream) {
WriteMagicNumber(out_stream);
// set version
WriteVersionNumber(out_stream, 1);
// check base types
WriteBaseType(out_stream, (char)1);
WriteBaseType(out_stream, (int)1);
WriteBaseType(out_stream, (Real)1);
// add sizes
WriteTypeSize<int>(out_stream);
WriteTypeSize<uint>(out_stream);
WriteTypeSize<float>(out_stream);
WriteTypeSize<MyStruct>(out_stream);
// check base types
WriteBaseType<char>(out_stream);
WriteBaseType<int>(out_stream);
WriteBaseType<Real>(out_stream);
WriteBaseType(out_stream, (Real)0.5); // ok for any IEEE floats
out_stream.close();
// check that checks work without exceptions
std::ifstream in_stream("mytest.dat", std::ios::binary);
BOOST_CHECK_NO_THROW(CheckMagicNumber(in_stream));
BOOST_CHECK_EQUAL(GetVersionNumber(in_stream), (uint32_t)1);
BOOST_CHECK_NO_THROW(CheckBaseType(in_stream, (char)1));
BOOST_CHECK_NO_THROW(CheckBaseType(in_stream, (int)1));
BOOST_CHECK_NO_THROW(CheckBaseType(in_stream, (Real)1));
BOOST_CHECK_NO_THROW(CheckTypeSize<int>(in_stream));
BOOST_CHECK_NO_THROW(CheckTypeSize<uint>(in_stream, true));
BOOST_CHECK_NO_THROW(CheckTypeSize<double>(in_stream, true));
BOOST_CHECK_NO_THROW(CheckTypeSize<MyStruct>(in_stream));
BOOST_CHECK_NO_THROW(CheckBaseType<char>(in_stream));
BOOST_CHECK_NO_THROW(CheckBaseType<int>(in_stream));
BOOST_CHECK_NO_THROW(CheckBaseType<Real>(in_stream));
BOOST_CHECK_NO_THROW(CheckBaseType(in_stream, (Real)0.5));
in_stream.close();
// check exceptions for check base type (also used by CheckMagicNumber)
in_stream.open("mytest.dat", std::ios::binary);
CheckMagicNumber(in_stream);
GetVersionNumber(in_stream);
BOOST_CHECK_THROW(CheckBaseType(in_stream, (char)3), promod3::Error);
BOOST_CHECK_THROW(CheckBaseType(in_stream, (int)4), promod3::Error);
BOOST_CHECK_THROW(CheckBaseType(in_stream, (Real)5), promod3::Error);
CheckTypeSize<int>(in_stream);
CheckTypeSize<uint>(in_stream);
BOOST_CHECK_THROW(CheckTypeSize<char>(in_stream, true), promod3::Error);
BOOST_CHECK_THROW(CheckTypeSize<char>(in_stream), promod3::Error);
BOOST_CHECK_THROW(CheckBaseType(in_stream, (char)3), promod3::Error);
BOOST_CHECK_THROW(CheckBaseType(in_stream, (int)4), promod3::Error);
BOOST_CHECK_THROW(CheckBaseType(in_stream, (Real)5), promod3::Error);
BOOST_CHECK_THROW(CheckBaseType<Real>(in_stream), promod3::Error);
in_stream.close();
// clean up
std::remove("mytest.dat");
}
BOOST_AUTO_TEST_SUITE_END();
......@@ -227,6 +227,32 @@ usual Unix file system filled with the build products of |project|. The
:file:`stage` directory tree can already be utilised. You may import Python
modules from there, use the binaries from :file:`stage/bin`, etc..
--------------------------------------------------------------------------------
Quick testing of |project| features
--------------------------------------------------------------------------------
High-level features of |project|, can be tested directly in an interactive
Python shell. First, you need to tell Python, where to find the modules by
defining the ``PYTHONPATH`` env. variable in your shell to include the
:file:`lib64/python2.7/site-packages` folders of the :file:`stage` folders of
|project| and |ost_s|. For convenience, you can place the export-command in
your :file:`.bashrc` (or so). Then, you can import modules from ``promod3``
and ``ost`` as in the example codes shown in this documentation.
To test low-level |C++| features, you can copy the :file:`extras/test_code`
folder and adapt it for your purposes. First, you will have to fix the paths
to |project| and |ost_s| in the :file:`Makefile` by changing the following
lines:
.. code-block:: make
# path to OST and ProMod3 stage
OST_ROOT = <DEFINEME>/ost/build/stage
PROMOD3_ROOT = <DEFINEME>/ProMod3/build/stage
Afterwards, you should be able to compile and run small sample codes that use
|project| and |ost_s| as in the :file:`test.cc` example. You can compile your
code by executing ``make`` and run it with ``make run``.
--------------------------------------------------------------------------------
Unit Tests
--------------------------------------------------------------------------------
......
########
# SETUP
########
# path to OST and ProMod3 stage
OST_ROOT = <DEFINEME>/ost/build/stage
PROMOD3_ROOT = <DEFINEME>/ProMod3/build/stage
# sources to compile
SOURCES = test.cc
# target filename
TARGET = test
# choose C++ compiler
CC = g++
LD = $(CC)
# set extra flags
CFLAGS =
LDFLAGS =
########
# set include paths
INCLUDES = -I$(OST_ROOT)/include -I$(PROMOD3_ROOT)/include
# collect libraries
LIB_DIRS = -L$(OST_ROOT)/lib64 -L$(PROMOD3_ROOT)/lib64
LIBS = -lpromod3_core -lpromod3_loop -lpromod3_modelling -lpromod3_sidechain
LIBS += -lost_io -lost_mol -lost_seq -lost_seq_alg -lost_mol_alg -lost_conop
LIBS += -lost_base -lost_geom -lost_mol_mm
# add rpath to find shared objects (req. gcc)
LDFLAGS += "-Wl,-rpath,$(PROMOD3_ROOT)/lib64:$(OST_ROOT)/lib64"
# setup compilation
OBJECTS := $(SOURCES:%.cc=%.o)
.DEFAULT: all;
# Default target is to compile everything
all: $(TARGET)
# run it
run: $(TARGET)
@echo "------ RUNNING $(TARGET) ------"
./$(TARGET)
# final linking
$(TARGET): $(OBJECTS)
@echo "PRODUCING $@"
@#echo "SOURCES = $(SOURCES)"
@#echo "OBJECTS = $(OBJECTS)"
@#echo "---------------------"
@$(LD) $(OBJECTS) -o $@ $(LIB_DIRS) $(LDFLAGS) $(LIBS)
@#echo "---------------------"
%.o: %.cc
@echo "PRODUCING $@"
@$(CC) ${INCLUDES} $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET)
rm -f $(OBJECTS)
// Test code for low-level ProMod3 features
#include <ost/base.hh>
#include <ost/io/pdb_writer.hh>
#include <promod3/loop/backbone.hh>
#include <iostream>
int main() {
std::cout << "Running ProMod3 testcode" << std::endl;
String sequence = "HELLYEAH";
promod3::loop::BackboneList bb_list(sequence);
ost::io::PDBWriter writer(String("test.pdb"), ost::io::IOProfile());
writer.Write(bb_list.ToEntity());
return 0;
}
// Equivalent Python code:
// -----------------------
// from ost import io
// from promod3 import loop
// # generate backbone with dihedrals of a helix and store it
// sequence = "HELLYEAH"
// bb_list = loop.BackboneList(sequence)
// io.SavePDB(bb_list.ToEntity(), "test.pdb")
\ No newline at end of file
set(LOOP_DATA_FILES
torsion_sampler.dat
torsion_sampler_coil.dat
torsion_sampler_extended.dat
torsion_sampler_helical.dat
frag_db.dat
structure_db.dat
backbone_loop_scorer.dat
)
add_module_data(NAME "loop"
DATALIST "${LOOP_DATA_FILES}"
DATASUBDIR "loop_data")
......@@ -70,22 +70,40 @@ The Torsion Sampler Class
Recalculates the probability distributions from the histograms.
.. method:: Load(filename)
.. method:: Load(filename, seed)
Loads raw version of the file (optimized for fast reading).This puts many
assumptions on the memory-layout of the target-machine and hence it is not
portable. A portable version is provided by :meth:`LoadPortable`.
:param filename: path to the file from which to load the sampler.
:param seed: seed for random number generator (not saved in file).
:type filename: :class:`str`
:type seed: :class:`int`
:returns: A torsion sampler
:rtype: :class:`TorsionSampler`
:raises: :class:`RuntimeError` if:
- file cannot be opened.
- version number stored in file is not supported.
- file assumes different memory-layout than is available on this
machine. Use :meth:`LoadPortable` to convert your file.
.. method:: Save(filename)
Saves raw version of the file (optimized for fast reading).This puts many
assumptions on the memory-layout of the target-machine and hence it is not
portable. A portable version is provided by :meth:`SavePortable`.
:param filename: path to the file where the sampler will be saved
:type filename: :class:`str`
:raises: :class:`RuntimeError` if file cannot be opened.
.. method:: GetHistogramIndex(before,central,after)
:param before: Name (3 letter code) of the residue before *central*
......
#include <promod3/loop/torsion_sampler.hh>
#include <promod3/core/check_io.hh>
namespace promod3{ namespace loop{
......@@ -96,13 +97,31 @@ TorsionSampler::TorsionSampler(const std::vector<String>& group_definitions,
}
}
TorsionSamplerPtr TorsionSampler::Load(const String& filename, uint seed){
TorsionSamplerPtr TorsionSampler::Load(const String& filename, uint seed,
bool skip_header) {
std::ifstream in_stream(filename.c_str(), std::ios::binary);
if (!in_stream){
if (!in_stream) {
std::stringstream ss;
ss << "the file '" << filename << "' does not exist.";
ss << "The file '" << filename << "' does not exist.";
throw promod3::Error(ss.str());
}
// header for consistency checks
if (!skip_header) {
promod3::core::CheckMagicNumber(in_stream);
uint32_t version = promod3::core::GetVersionNumber(in_stream);
if (version > 1) {
std::stringstream ss;
ss << "Unsupported file version '" << version << "' in '" << filename;
throw promod3::Error(ss.str());
}
// required types: int, uint, char
promod3::core::CheckTypeSize<int>(in_stream);
promod3::core::CheckTypeSize<uint>(in_stream);
promod3::core::CheckBaseType<int>(in_stream);
promod3::core::CheckBaseType<uint>(in_stream);
promod3::core::CheckBaseType<char>(in_stream);
}
// raw data
int bin_size;
uint num_groups;
std::vector<String> group_definitions;
......@@ -130,8 +149,25 @@ TorsionSamplerPtr TorsionSampler::Load(const String& filename, uint seed){
return sampler;
}
void TorsionSampler::Save(const String& filename){
void TorsionSampler::Save(const String& filename, bool skip_header) {
std::ofstream out_stream(filename.c_str(), std::ios::binary);
if (!out_stream) {
std::stringstream ss;
ss << "The file '" << filename << "' cannot be opened.";
throw promod3::Error(ss.str());
}
// header for consistency checks
if (!skip_header) {
promod3::core::WriteMagicNumber(out_stream);
promod3::core::WriteVersionNumber(out_stream, 1);
// required types: int, uint, char
promod3::core::WriteTypeSize<int>(out_stream);
promod3::core::WriteTypeSize<uint>(out_stream);
promod3::core::WriteBaseType<int>(out_stream);
promod3::core::WriteBaseType<uint>(out_stream);
promod3::core::WriteBaseType<char>(out_stream);
}
// raw data
out_stream.write(reinterpret_cast<char*>(&int_bin_size_), sizeof(int));
uint num_groups = distributions_.size();
out_stream.write(reinterpret_cast<char*>(&num_groups), sizeof(uint));
......
......@@ -27,9 +27,14 @@ class TorsionSampler{
public:
TorsionSampler(const std::vector<String>& group_definitions, int bin_size, uint seed);
static TorsionSamplerPtr Load(const String& filename, uint seed);
void Save(const String& filename);
// skip_header only used for conversion from ancient format
// (can safely be removed in the future)
static TorsionSamplerPtr Load(const String& filename, uint seed,
bool skip_header=false);
// include_header only used for conversion from ancient format
// (can safely be removed in the future)
void Save(const String& filename, bool skip_header=false);
void ExtractStatistics(ost::mol::EntityView& view);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment