From cd9628df0ac26d9e6ce43b578e82ac6007516885 Mon Sep 17 00:00:00 2001 From: Adrien Devresse Date: Thu, 18 Feb 2016 14:14:08 +0100 Subject: [PATCH 1/5] - Add MVD3 support to Brain::circuit - Add mvd-tool as a subroject for MVD3 parsing - Change brain::getTransforms logic from euler angles to rotation with quaternions - Add switch in BlueConfig to load or not MVD3 - Add tests for MVD3 parsing - Add Nix support - Switch MVDTool dependency to github repository --- .gitsubprojects | 1 + brain/CMakeLists.txt | 6 +- brain/circuit.cpp | 330 +++++++++++++++++++++++++++++++++++++++++---------- brain/circuit.h | 1 + brain/types.h | 2 + brion/blueConfig.cpp | 17 ++- brion/blueConfig.h | 12 +- brion/circuit.cpp | 3 + brion/constants.h | 1 + brion/enums.h | 7 ++ brion/types.h | 3 + default.nix | 30 +++++ tests/circuit.cpp | 77 ++++++++++++ 13 files changed, 425 insertions(+), 65 deletions(-) create mode 100644 default.nix diff --git a/.gitsubprojects b/.gitsubprojects index c6957b6..a1edba0 100644 --- a/.gitsubprojects +++ b/.gitsubprojects @@ -2,3 +2,4 @@ git_subproject(Servus https://github.com/HBPVIS/Servus.git 567f038) git_subproject(Lunchbox https://github.com/Eyescale/Lunchbox.git b41edcf) git_subproject(vmmlib https://github.com/Eyescale/vmmlib.git b41e1a5) +git_subproject(MVDTool https://github.com/BlueBrain/MVDTool.git d700fa9) diff --git a/brain/CMakeLists.txt b/brain/CMakeLists.txt index 848a701..620a594 100644 --- a/brain/CMakeLists.txt +++ b/brain/CMakeLists.txt @@ -6,6 +6,9 @@ source_group(\\ FILES CMakeLists.txt) +## force inclue directory for cmake 2 compat +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../MVDTool/include ${CMAKE_CURRENT_SOURCE_DIR}/../MVDTool/deps/highfive/include) + set(BRAIN_PUBLIC_HEADERS circuit.h types.h @@ -27,7 +30,8 @@ set(BRAIN_SOURCES ) set(BRAIN_PUBLIC_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) -set(BRAIN_LINK_LIBRARIES PUBLIC Brion vmmlib) +set(BRAIN_LINK_LIBRARIES PUBLIC Brion vmmlib + PRIVATE ${HDF5_LIBRARIES}) set(BRAIN_INCLUDE_NAME brain) set(BRAIN_NAMESPACE brain) diff --git a/brain/circuit.cpp b/brain/circuit.cpp index fa75ab0..753595f 100644 --- a/brain/circuit.cpp +++ b/brain/circuit.cpp @@ -20,27 +20,62 @@ #include "circuit.h" #include "neuron/morphology.h" +#include +#include +#include + +#include +#include +#include + #include #include #include #include +#include +#include + #include -#include + namespace brain { + +Vector3fs getPositionsMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids); +Vector3fs getPositionsMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids); + +std::vector getMorphologiesNameMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids); +std::vector getMorphologiesNameMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids); + +Quaternionfs getQuatRotationsMVD2(const brion::Circuit& circuit_mvd2, const GIDSet& gids ); +Quaternionfs getQuatRotationsMVD3(MVD3::MVD3File& circuit_mvd3, const GIDSet& gids ); + class Circuit::Impl { public: + Impl( const brion::BlueConfig& config ) - : _circuit( config.getCircuitSource( )) + : _circuit_mvd2() + , _circuit_mvd3() , _morphologySource( config.getMorphologySource( )) , _circuitTarget( config.getCircuitTarget( )) , _targetParsers( config.getTargets( )) { + using namespace MVD; + const std::string circuit_path = config.getCircuitSource().getPath(); + switch(is_mvd_file(circuit_path)) + { + case MVDType::MVD2: + _circuit_mvd2.reset(new brion::Circuit(circuit_path)); + break; + case MVDType::MVD3: + default: + _circuit_mvd3.reset(new MVD3::MVD3File(circuit_path)); + break; + } } GIDSet getGIDs( const std::string& target ) const @@ -49,9 +84,23 @@ class Circuit::Impl _targetParsers, target.empty() ? _circuitTarget : target ); } - const brion::Circuit& getCircuit() const - { - return _circuit; + Vector3fs getPositions(const GIDSet& gids) const{ + if(_circuit_mvd2) + return getPositionsMVD2(*_circuit_mvd2, gids); + return getPositionsMVD3(*_circuit_mvd3, gids); + + } + + Quaternionfs getQuatRot(const GIDSet & gids) const{ + if(_circuit_mvd2) + return getQuatRotationsMVD2(*_circuit_mvd2, gids); + return getQuatRotationsMVD3(*_circuit_mvd3, gids); + } + + std::vector getMorphologiesName(const GIDSet& gids){ + if(_circuit_mvd2) + return getMorphologiesNameMVD2(*_circuit_mvd2, gids); + return getMorphologiesNameMVD3(*_circuit_mvd3, gids); } URI getMorphologyURI( const std::string& name ) const @@ -63,13 +112,208 @@ class Circuit::Impl } private: - const brion::Circuit _circuit; + + boost::scoped_ptr _circuit_mvd2; + mutable boost::scoped_ptr _circuit_mvd3; + const brion::URI _morphologySource; const std::string _circuitTarget; const brion::Targets _targetParsers; }; + +MVD3::Range range_from_gidset(const GIDSet& gids) +{ + if(gids.size() > 0) + { + assert(*gids.begin() > 0); // gids in Brion start at 1 + const size_t offset = (*gids.begin()) -1; + const size_t range_count = *gids.rbegin() - offset; + return MVD3::Range(offset, range_count); + } + return MVD3::Range(0,0); // full range +} + + + +template +inline void array_range_to_index(const MVD3::Range& range, + const GIDSet& gids, + SrcArray& src, + DstArray& dst, + const AssignOps& assign_ops) +{ + size_t s_source = std::distance(src.begin(), src.end()); (void) s_source; + size_t s_dest = std::distance(dst.begin(), dst.end()); (void) s_dest; + + if(gids.empty() == true) // we work on full range, no translation needed + { + assert(s_source == s_dest); + std::transform(src.begin(), src.end(), dst.begin(), assign_ops); + } + else + { + assert(s_dest == gids.size()); + typename DstArray::iterator dst_it = dst.begin(); + for(GIDSet::const_iterator it = gids.begin(); it != gids.end(); ++it) + { + assert( *it > range.offset && *it < (range.offset + range.count +1)); + typename SrcArray::iterator src_it = src.begin(); + std::advance(src_it, *it - range.offset -1 ); + *dst_it = assign_ops(*src_it); + ++dst_it; + } + } +} + +template +inline VMMLVector boost_mul_array_to_vmml_vector(const MVD3::Positions::subarray<1>::type& subarray) +{ + VMMLVector res; + res.iter_set(subarray.begin(), subarray.end()); + return res; +} + +inline brion::Quaternionf boost_mul_array_to_quaternion(const MVD3::Positions::subarray<1>::type& subarray) +{ + return brion::Quaternionf(subarray[1], subarray[2], subarray[3], subarray[0]); +} + +inline std::string swap_string(std::string& in) +{ + using namespace std; + std::string res; + swap(res, in); + return res; +} + + + + + +Vector3fs getPositionsMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids) +{ + const brion::NeuronMatrix& data = circuit_mvd2.get( + gids, brion::NEURON_POSITION_X | brion::NEURON_POSITION_Y | + brion::NEURON_POSITION_Z ); + + brion::GIDSet::const_iterator gid = gids.begin(); + Vector3fs positions( gids.size( )); + #pragma omp parallel for + for( size_t i = 0; i < gids.size(); ++i ) + { + try + { + positions[i] = + brion::Vector3f( boost::lexical_cast< float >( data[i][0] ), + boost::lexical_cast< float >( data[i][1] ), + boost::lexical_cast< float >( data[i][2] )); + } + catch( const boost::bad_lexical_cast& ) + { + LBWARN << "Error parsing circuit position or orientation for gid " + << *gid << ". Morphology not transformed." << std::endl; + positions[i] = Vector3f::ZERO; + } + #pragma omp critical (brain_circuit_getPositions) + ++gid; + } + return positions; +} + + +Vector3fs getPositionsMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids) +{ + const size_t n_elems = ((gids.size()>0)?gids.size():circuit_mvd3.getNbNeuron()); + Vector3fs results(n_elems); + MVD3::Range range = range_from_gidset(gids); + MVD3::Positions positions = circuit_mvd3.getPositions(range); + + assert(positions.shape()[1] ==3); + array_range_to_index(range, gids, positions, results, boost_mul_array_to_vmml_vector); + return results; + +} + +std::vector getMorphologiesNameMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids) +{ + brion::NeuronMatrix matrix = + circuit_mvd2.get( gids, brion::NEURON_MORPHOLOGY_NAME ); + std::vector res(matrix.shape()[0]); + + brion::NeuronMatrix::array_view<1>::type morpho_view = matrix[ boost::indices[brion::NeuronMatrix::index_range()][0]]; + std::transform(morpho_view.begin(), morpho_view.end(), res.begin(), swap_string); + return res; +} + + +std::vector getMorphologiesNameMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids) +{ + const size_t n_elems = ((gids.size()>0)?gids.size():circuit_mvd3.getNbNeuron()); + std::vector results(n_elems); + MVD3::Range range = range_from_gidset(gids); + std::vector morphos = circuit_mvd3.getMorphologies(range); + + assert(morphos.size() == n_elems); + array_range_to_index(range, gids, morphos, results, swap_string); + return results; + +} + + +Quaternionfs getQuatRotationsMVD2(const brion::Circuit& circuit_mvd2, const GIDSet& gids ) +{ + const double deg_rad = boost::math::constants::pi() / 180.0; + const size_t n_elems = (gids.size()>0)?gids.size():circuit_mvd2.getNumNeurons(); + const brion::NeuronMatrix& data = circuit_mvd2.get( + gids, brion::NEURON_ROTATION ); + Quaternionfs rotations(n_elems); + + assert(data.shape()[0] == n_elems); + assert(data.shape()[1] == 1); + + #pragma omp parallel for + for( size_t i = 0; i < n_elems; i++ ) + { + try + { + // transform rotation Y angle in degree into rotation quaternion + const double angle_y = boost::lexical_cast( data[i][0] )*deg_rad; + rotations[i] = + Quaternionf( 0, // x + std::sin(angle_y/2), // y + 0, // z + std::cos(angle_y/2)); // w + } + catch( const boost::bad_lexical_cast& ) + { + GIDSet::const_iterator it_gid = gids.begin(); + std::advance(it_gid, i); + LBWARN << "Error parsing circuit position or orientation for gid " + << *(it_gid) << ". Morphology not transformed." << std::endl; + rotations[i] = Quaternionf(0,0,0,0); + } + } + return rotations; + } + +Quaternionfs getQuatRotationsMVD3(MVD3::MVD3File& circuit_mvd3, const GIDSet& gids ) +{ + const size_t n_elems = ((gids.size() >0)?gids.size():circuit_mvd3.getNbNeuron()); + Quaternionfs results(n_elems); + + MVD3::Range range = range_from_gidset(gids); + MVD3::Rotations rotations = circuit_mvd3.getRotations(range); + assert(rotations.shape()[1] ==4); + array_range_to_index(range, gids, rotations, results, boost_mul_array_to_quaternion); + return results; + + } + + + + Circuit::Circuit( const URI& source ) : _impl( new Impl( brion::BlueConfig( source.getPath( )))) { @@ -92,13 +336,12 @@ GIDSet Circuit::getGIDs( const std::string& target ) const URIs Circuit::getMorphologyURIs( const GIDSet& gids ) const { - const brion::NeuronMatrix& matrix = - _impl->getCircuit().get( gids, brion::NEURON_MORPHOLOGY_NAME ); + const std::vector names = _impl->getMorphologiesName(gids); URIs uris; - uris.reserve( gids.size( )); - for( size_t index = 0; index != gids.size(); ++index ) - uris.push_back( _impl->getMorphologyURI( matrix[index][0] )); + uris.reserve( names.size()); + for(std::vector::const_iterator it = names.begin(); it < names.end(); ++it ) + uris.push_back( _impl->getMorphologyURI( *it )); return uris; } @@ -139,67 +382,34 @@ neuron::Morphologies Circuit::loadMorphologies( const GIDSet& gids, return result; } + + + Vector3fs Circuit::getPositions( const GIDSet& gids ) const { - const brion::NeuronMatrix& data = _impl->getCircuit().get( - gids, brion::NEURON_POSITION_X | brion::NEURON_POSITION_Y | - brion::NEURON_POSITION_Z ); - - brion::GIDSet::const_iterator gid = gids.begin(); - Vector3fs positions( gids.size( )); - #pragma omp parallel for - for( size_t i = 0; i < gids.size(); ++i ) - { - try - { - positions[i] = - brion::Vector3f( boost::lexical_cast< float >( data[i][0] ), - boost::lexical_cast< float >( data[i][1] ), - boost::lexical_cast< float >( data[i][2] )); - } - catch( const boost::bad_lexical_cast& ) - { - LBWARN << "Error parsing circuit position or orientation for gid " - << *gid << ". Morphology not transformed." << std::endl; - positions[i] = Vector3f::ZERO; - } - #pragma omp critical (brain_circuit_getPositions) - ++gid; - } - return positions; + return _impl->getPositions(gids); } + Matrix4fs Circuit::getTransforms( const GIDSet& gids ) const { - const brion::NeuronMatrix& data = _impl->getCircuit().get( - gids, brion::NEURON_POSITION_X | brion::NEURON_POSITION_Y | - brion::NEURON_POSITION_Z | brion::NEURON_ROTATION ); + const Vector3fs positions = _impl->getPositions(gids); + const Quaternionfs rotations = _impl->getQuatRot(gids); + assert(positions.size() == rotations.size()); + + Matrix4fs transforms( positions.size(), Matrix4f::IDENTITY ); - brion::GIDSet::const_iterator gid = gids.begin(); - Matrix4fs transforms( gids.size(), Matrix4f::IDENTITY ); #pragma omp parallel for - for( size_t i = 0; i < gids.size(); ++i ) + for( size_t i = 0; i < positions.size(); ++i ) { Matrix4f& matrix = transforms[i]; - try - { - matrix.rotate_y( - boost::lexical_cast< float >( data[i][3] ) * ( M_PI/180.0f )); - matrix.set_translation( - Vector3f( boost::lexical_cast< float >( data[i][0] ), - boost::lexical_cast< float >( data[i][1] ), - boost::lexical_cast< float >( data[i][2] ))); - } - catch( const boost::bad_lexical_cast& ) - { - LBWARN << "Error parsing circuit position or orientation for gid " - << *gid << ". Morphology not transformed." << std::endl; - matrix = Matrix4f::IDENTITY; - } - #pragma omp critical (brain_circuit_getTransforms) - ++gid; + + rotations[i].get_rotation_matrix(matrix); + matrix.set_translation(positions[i]); } return transforms; + } + } diff --git a/brain/circuit.h b/brain/circuit.h index 97f682f..873ebac 100644 --- a/brain/circuit.h +++ b/brain/circuit.h @@ -88,5 +88,6 @@ class Circuit : public boost::noncopyable Impl* _impl; }; + } #endif diff --git a/brain/types.h b/brain/types.h index 63b2740..7c83b3d 100644 --- a/brain/types.h +++ b/brain/types.h @@ -34,6 +34,7 @@ using vmml::Vector2i; using vmml::Vector3f; using vmml::Vector4f; using vmml::Matrix4f; +using brion::Quaternionf; using brion::Vector2is; using brion::Vector3fs; @@ -41,6 +42,7 @@ using brion::Vector4fs; typedef std::vector< Matrix4f > Matrix4fs; using brion::uint32_ts; using brion::floats; +using brion::Quaternionfs; using brion::SectionTypes; using brion::GIDSet; diff --git a/brion/blueConfig.cpp b/brion/blueConfig.cpp index 718c410..afca11a 100644 --- a/brion/blueConfig.cpp +++ b/brion/blueConfig.cpp @@ -82,7 +82,10 @@ namespace detail class BlueConfig { public: - explicit BlueConfig( const std::string& source ) + explicit BlueConfig( const std::string& source) : + names(), + table(), + mvd_type(CircuitMVD2) { std::ifstream file( source.c_str( )); if( !file.is_open( )) @@ -208,6 +211,8 @@ class BlueConfig Strings names[CONFIGSECTION_ALL]; ValueTable table[CONFIGSECTION_ALL]; + CircuitType mvd_type; + }; } @@ -249,13 +254,15 @@ brion::Targets BlueConfig::getTargets() const URI BlueConfig::getCircuitSource() const { URI uri; + const std::string circuit_filename = + ((_impl->mvd_type == CircuitMVD2)?(CIRCUIT_FILE):(CIRCUIT_FILE_MVD3)); + uri.setScheme("file"); uri.setPath( get( CONFIGSECTION_RUN, _impl->getRun(), - BLUECONFIG_CIRCUIT_PATH_KEY ) + CIRCUIT_FILE ); + BLUECONFIG_CIRCUIT_PATH_KEY ) + circuit_filename ); return uri; } - URI BlueConfig::getSynapseSource() const { URI uri; @@ -340,6 +347,10 @@ float BlueConfig::getTimestep() const return timestep; } +void BlueConfig::setCircuitType(CircuitType circuit_type){ + _impl->mvd_type = circuit_type; +} + std::ostream& operator << ( std::ostream& os, const BlueConfig& config ) { for( size_t i = 0; i < CONFIGSECTION_ALL; ++i ) diff --git a/brion/blueConfig.h b/brion/blueConfig.h index febbf34..697b3dc 100644 --- a/brion/blueConfig.h +++ b/brion/blueConfig.h @@ -102,11 +102,13 @@ class BlueConfig : public boost::noncopyable /** @name Semantic read API */ //@{ /** - * @return the URI to the circuit information. @sa Circuit + * @return the URI to the circuit information. @sa Circuit. + * * @version 1.7 */ BRION_API URI getCircuitSource() const; + /* * @return the URI to the location of synapse nrn files. * @version 1.7 @@ -148,8 +150,16 @@ class BlueConfig : public boost::noncopyable * @version 1.7 */ BRION_API float getTimestep() const; + + /** @brief define the circuit type to use ( e.g MVD2/MVD3 ). + * default is MVD2 + */ + BRION_API void setCircuitType(CircuitType circuit_type); + //@} + + private: friend std::ostream& operator << ( std::ostream&, const BlueConfig& ); diff --git a/brion/circuit.cpp b/brion/circuit.cpp index 6601ae1..f21f039 100644 --- a/brion/circuit.cpp +++ b/brion/circuit.cpp @@ -45,6 +45,7 @@ enum Section class Circuit::Impl { public: + explicit Impl( const std::string& source ) { namespace fs = boost::filesystem; @@ -86,6 +87,7 @@ class Circuit::Impl } } + NeuronMatrix get( const GIDSet& gids, const uint32_t attributes ) const { const std::bitset< NEURON_ALL > bits( attributes ); @@ -200,6 +202,7 @@ class Circuit::Impl typedef stde::hash_map< uint32_t, Strings > CircuitTable; CircuitTable _table; + }; Circuit::Circuit( const std::string& source ) diff --git a/brion/constants.h b/brion/constants.h index 2f42d35..2fdecc2 100644 --- a/brion/constants.h +++ b/brion/constants.h @@ -25,6 +25,7 @@ namespace brion const char* const SPIKE_FILE = "/out.dat"; const char* const CIRCUIT_FILE = "/circuit.mvd2"; +const char* const CIRCUIT_FILE_MVD3 = "/circuit.mvd3"; const char* const CIRCUIT_TARGET_FILE = "/start.target"; const char* const MORPHOLOGY_HDF5_FILES_SUBDIRECTORY = "h5"; diff --git a/brion/enums.h b/brion/enums.h index 033df5c..554ea19 100644 --- a/brion/enums.h +++ b/brion/enums.h @@ -44,6 +44,13 @@ enum BlueConfigSection CONFIGSECTION_ALL //!< @internal must be last }; +/** The supported MVD circuit file format */ +enum CircuitType{ + CircuitMVD2=20, + CircuitMVD3=30 +}; + + /** * The supported formats for compartment reports. * @deprecated since version 1.4, kept until removed from BBPSDK and replaced by diff --git a/brion/types.h b/brion/types.h index d32ef1b..faf2733 100644 --- a/brion/types.h +++ b/brion/types.h @@ -64,6 +64,8 @@ using vmml::Vector4f; using vmml::Vector3d; using vmml::Vector4d; +typedef vmml::quaternionf Quaternionf; + typedef std::vector< size_t > size_ts; typedef std::vector< int32_t > int32_ts; typedef std::vector< uint16_t > uint16_ts; @@ -75,6 +77,7 @@ typedef std::vector< Vector3f > Vector3fs; typedef std::vector< Vector4f > Vector4fs; typedef std::vector< Vector3d > Vector3ds; typedef std::vector< Vector4d > Vector4ds; +typedef std::vector< Quaternionf > Quaternionfs; typedef std::vector< SectionType > SectionTypes; typedef std::vector< Target > Targets; typedef boost::shared_ptr< int32_ts > int32_tsPtr; diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..135f318 --- /dev/null +++ b/default.nix @@ -0,0 +1,30 @@ +# Nix development environment +# +# build: +# nix-build -I "BBPpkgs=https://github.com/BlueBrain/bbp-nixpkgs/archive/master.tar.gz" default.nix +# +# build and test: +# nix-build -I "BBPpkgs=https://github.com/BlueBrain/bbp-nixpkgs/archive/master.tar.gz" --arg testExec true default.nix -j 4 +# +# dev shell: +# nix-shell -I "BBPpkgs=https://github.com/BlueBrain/bbp-nixpkgs/archive/master.tar.gz" default.nix +# +with import { }; + + +stdenv.mkDerivation rec { + name = "Brion-DEV"; + src = ./.; + buildInputs = [stdenv pkgconfig boost zlib cmake cmake-external hdf5-cpp servus lunchbox vmmlib mvdtool bbptestdata ]; + + + doCheck= true; + + checkPhase= '' + export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH; + ctest -E perf -V; + ''; + + +} + diff --git a/tests/circuit.cpp b/tests/circuit.cpp index 584ebfc..3d815f0 100644 --- a/tests/circuit.cpp +++ b/tests/circuit.cpp @@ -150,6 +150,9 @@ BOOST_AUTO_TEST_CASE(test_types) BOOST_CHECK_EQUAL( etypes[7], "cST" ); } + + + BOOST_AUTO_TEST_CASE( brain_circuit_constructor ) { brain::Circuit circuit( (brion::URI( bbp::test::getBlueconfig( )))); @@ -158,6 +161,8 @@ BOOST_AUTO_TEST_CASE( brain_circuit_constructor ) std::runtime_error ); } + + BOOST_AUTO_TEST_CASE( brain_circuit_target ) { const brain::Circuit circuit( (brion::URI( bbp::test::getBlueconfig( )))); @@ -179,6 +184,7 @@ BOOST_AUTO_TEST_CASE( brain_circuit_target ) second.begin(), second.end( )); } + BOOST_AUTO_TEST_CASE( brain_circuit_positions ) { const brain::Circuit circuit( (brion::URI( bbp::test::getBlueconfig( )))); @@ -219,6 +225,11 @@ void _checkMorphology( const brain::neuron::Morphology& morphology, transform ); const brain::Vector4fs& p = morphology.getPoints(); const brain::Vector4fs& q = reference.getPoints(); + + BOOST_CHECK( reference.getTransformation().equals(transform, 0.001)); + + + BOOST_REQUIRE( p.size() == q.size( )); for( size_t i = 0; i != p.size(); ++i ) BOOST_CHECK_SMALL(( p[i] - q[i] ).length( ), 0.0001f); @@ -283,3 +294,69 @@ BOOST_AUTO_TEST_CASE( load_global_morphologies ) _checkMorphology( *morphologies[0], "R-C010306G.h5", matrix ); } + +void _check_transform(const brain::Matrix4f & trans, const brain::Quaternionf & quat, + const brain::Vector3f & pos) +{ + brain::Matrix4f mat; + quat.get_rotation_matrix(mat); + mat.set_translation(pos); + mat[3][3] =1; + BOOST_CHECK( mat.equals( trans, 0.001f)); + +// std::cout << trans << "\n" << mat << std::endl; + +} + +BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) +{ + brion::BlueConfig config(BBP_TEST_BLUECONFIG); + config.setCircuitType(brion::CircuitMVD3); + + brain::Circuit circuit(config); + + brain::Vector3fs positions = circuit.getPositions(brion::GIDSet()); + brain::Matrix4fs transforms = circuit.getTransforms(brion::GIDSet()); + BOOST_CHECK_EQUAL( positions.size(), 1000 ); + BOOST_CHECK_EQUAL( transforms.size(), 1000 ); + + BOOST_CHECK_SMALL( + ( positions[20] - brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )).length(), + 0.000001f ); + BOOST_CHECK_SMALL( + ( positions[100] - brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )).length(), + 0.000001f ); + + _check_transform(transforms[20], brain::Quaternionf (0, 0.923706, 0, 0.383102), brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )); + _check_transform(transforms[100], brain::Quaternionf (0, -0.992667, 0, 0.120884), brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )); +} + +BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) +{ + brion::BlueConfig config(BBP_TEST_BLUECONFIG); + config.setCircuitType(brion::CircuitMVD3); + + brain::Circuit circuit(config); + + brion::GIDSet set; + set.insert(6); + set.insert(21); + set.insert(101); + set.insert(501); + + brain::Vector3fs positions = circuit.getPositions(set); + brain::Matrix4fs transforms = circuit.getTransforms(set); + BOOST_CHECK_EQUAL( positions.size(), 4 ); + BOOST_CHECK_EQUAL( transforms.size(), 4 ); + + BOOST_CHECK_SMALL( + ( positions[1] - brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )).length(), + 0.000001f ); + BOOST_CHECK_SMALL( + ( positions[2] - brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )).length(), + 0.000001f ); + + _check_transform(transforms[1], brain::Quaternionf (0, 0.923706, 0, 0.383102), brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )); + _check_transform(transforms[2], brain::Quaternionf (0, -0.992667, 0, 0.120884), brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )); +} + From fb874a5b1f4708d7a27a4b3657925999f80b4041 Mon Sep 17 00:00:00 2001 From: Stefan Eilemann Date: Wed, 24 Feb 2016 08:43:05 +0100 Subject: [PATCH 2/5] Partial CR #41 --- brain/CMakeLists.txt | 7 +- brain/circuit.cpp | 427 +++++++++++++++++++++------------------------------ brain/circuit.h | 12 +- brain/types.h | 20 +-- brion/blueConfig.cpp | 25 ++- brion/blueConfig.h | 11 +- brion/circuit.cpp | 3 - brion/constants.h | 2 +- brion/enums.h | 7 - brion/types.h | 3 - tests/circuit.cpp | 64 ++++---- 11 files changed, 234 insertions(+), 347 deletions(-) diff --git a/brain/CMakeLists.txt b/brain/CMakeLists.txt index 620a594..58c9afd 100644 --- a/brain/CMakeLists.txt +++ b/brain/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2015, EPFL/Blue Brain Project +# Copyright (c) 2013-2016, EPFL/Blue Brain Project # Juan Hernando # # This file is part of Brion @@ -6,9 +6,6 @@ source_group(\\ FILES CMakeLists.txt) -## force inclue directory for cmake 2 compat -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../MVDTool/include ${CMAKE_CURRENT_SOURCE_DIR}/../MVDTool/deps/highfive/include) - set(BRAIN_PUBLIC_HEADERS circuit.h types.h @@ -31,7 +28,7 @@ set(BRAIN_SOURCES set(BRAIN_PUBLIC_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) set(BRAIN_LINK_LIBRARIES PUBLIC Brion vmmlib - PRIVATE ${HDF5_LIBRARIES}) + PRIVATE MVDTool ${HDF5_LIBRARIES}) set(BRAIN_INCLUDE_NAME brain) set(BRAIN_NAMESPACE brain) diff --git a/brain/circuit.cpp b/brain/circuit.cpp index 753595f..81d79ba 100644 --- a/brain/circuit.cpp +++ b/brain/circuit.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando * * This file is part of Brion @@ -20,63 +20,84 @@ #include "circuit.h" #include "neuron/morphology.h" -#include -#include -#include - -#include -#include -#include - #include #include #include #include +#include + #include #include -#include +#include +#include +#include +#include +#include +#include +using boost::lexical_cast; namespace brain { +namespace +{ +bool isSequence( const GIDSet& gids ) +{ + return ( *gids.rbegin() - *gids.begin() + 1 ) == gids.size(); +} +::MVD3::Range getRange( const GIDSet& gids ) +{ + const size_t offset = ( *gids.begin( )); + const size_t count = *gids.rbegin() - offset + 1; + return ::MVD3::Range( offset - 1, count ); +} -Vector3fs getPositionsMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids); -Vector3fs getPositionsMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids); +template< typename SrcArray, typename DstArray, typename AssignOp > +void assign( const ::MVD3::Range& range, const GIDSet& gids, + SrcArray& src, DstArray& dst, const AssignOp& assignOp ) +{ + if( isSequence( gids )) // OPT: no holes, no translation needed + { + std::transform( src.begin(), src.end(), dst.begin(), assignOp ); + return; + } + + typename DstArray::iterator dst_it = dst.begin(); + for( GIDSet::const_iterator i = gids.begin(); i != gids.end(); ++i ) + { + typename SrcArray::const_iterator src_it = src.begin(); + std::advance( src_it, *i - range.offset - 1 ); + *dst_it = assignOp( *src_it ); + ++dst_it; + } +} + +Vector3f toVector3f( const ::MVD3::Positions::const_subarray< 1 >::type& subarray ) +{ + return Vector3f( subarray[0], subarray[1], subarray[2] ); +} -std::vector getMorphologiesNameMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids); -std::vector getMorphologiesNameMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids); +Quaternionf toQuaternion( const ::MVD3::Rotations::const_subarray< 1 >::type& subarray ) +{ + return Quaternionf( subarray[0], subarray[1], subarray[2], subarray[3] ); +} -Quaternionfs getQuatRotationsMVD2(const brion::Circuit& circuit_mvd2, const GIDSet& gids ); -Quaternionfs getQuatRotationsMVD3(MVD3::MVD3File& circuit_mvd3, const GIDSet& gids ); +std::string toString( const std::string& in ) { return in; } +} class Circuit::Impl { public: - Impl( const brion::BlueConfig& config ) - : _circuit_mvd2() - , _circuit_mvd3() - , _morphologySource( config.getMorphologySource( )) + : _morphologySource( config.getMorphologySource( )) , _circuitTarget( config.getCircuitTarget( )) , _targetParsers( config.getTargets( )) - { - using namespace MVD; - const std::string circuit_path = config.getCircuitSource().getPath(); - switch(is_mvd_file(circuit_path)) - { - case MVDType::MVD2: - _circuit_mvd2.reset(new brion::Circuit(circuit_path)); - break; - case MVDType::MVD3: - default: - _circuit_mvd3.reset(new MVD3::MVD3File(circuit_path)); - break; - } - } + {} + virtual ~Impl() {} GIDSet getGIDs( const std::string& target ) const { @@ -84,24 +105,9 @@ class Circuit::Impl _targetParsers, target.empty() ? _circuitTarget : target ); } - Vector3fs getPositions(const GIDSet& gids) const{ - if(_circuit_mvd2) - return getPositionsMVD2(*_circuit_mvd2, gids); - return getPositionsMVD3(*_circuit_mvd3, gids); - - } - - Quaternionfs getQuatRot(const GIDSet & gids) const{ - if(_circuit_mvd2) - return getQuatRotationsMVD2(*_circuit_mvd2, gids); - return getQuatRotationsMVD3(*_circuit_mvd3, gids); - } - - std::vector getMorphologiesName(const GIDSet& gids){ - if(_circuit_mvd2) - return getMorphologiesNameMVD2(*_circuit_mvd2, gids); - return getMorphologiesNameMVD3(*_circuit_mvd3, gids); - } + virtual Vector3fs getPositions( const GIDSet& gids ) const = 0; + virtual Quaternionfs getRotations( const GIDSet& gids ) const = 0; + virtual Strings getMorphologyNames( const GIDSet& gids ) const = 0; URI getMorphologyURI( const std::string& name ) const { @@ -112,215 +118,145 @@ class Circuit::Impl } private: - - boost::scoped_ptr _circuit_mvd2; - mutable boost::scoped_ptr _circuit_mvd3; - const brion::URI _morphologySource; const std::string _circuitTarget; const brion::Targets _targetParsers; - }; - -MVD3::Range range_from_gidset(const GIDSet& gids) +class MVD2 : public Circuit::Impl { - if(gids.size() > 0) - { - assert(*gids.begin() > 0); // gids in Brion start at 1 - const size_t offset = (*gids.begin()) -1; - const size_t range_count = *gids.rbegin() - offset; - return MVD3::Range(offset, range_count); - } - return MVD3::Range(0,0); // full range -} - - - -template -inline void array_range_to_index(const MVD3::Range& range, - const GIDSet& gids, - SrcArray& src, - DstArray& dst, - const AssignOps& assign_ops) -{ - size_t s_source = std::distance(src.begin(), src.end()); (void) s_source; - size_t s_dest = std::distance(dst.begin(), dst.end()); (void) s_dest; +public: + MVD2( const brion::BlueConfig& config ) + : Impl( config ) + , _circuit( config.getCircuitSource().getPath( )) + {} - if(gids.empty() == true) // we work on full range, no translation needed + Vector3fs getPositions( const GIDSet& gids ) const final { - assert(s_source == s_dest); - std::transform(src.begin(), src.end(), dst.begin(), assign_ops); - } - else - { - assert(s_dest == gids.size()); - typename DstArray::iterator dst_it = dst.begin(); - for(GIDSet::const_iterator it = gids.begin(); it != gids.end(); ++it) + const brion::NeuronMatrix& data = _circuit.get( gids, + brion::NEURON_POSITION_X | brion::NEURON_POSITION_Y | + brion::NEURON_POSITION_Z ); + + Vector3fs positions( gids.size( )); +#pragma omp parallel for + for( size_t i = 0; i < gids.size(); ++i ) { - assert( *it > range.offset && *it < (range.offset + range.count +1)); - typename SrcArray::iterator src_it = src.begin(); - std::advance(src_it, *it - range.offset -1 ); - *dst_it = assign_ops(*src_it); - ++dst_it; + try + { + positions[i] = + brion::Vector3f( lexical_cast< float >( data[i][0] ), + lexical_cast< float >( data[i][1] ), + lexical_cast< float >( data[i][2] )); + } + catch( const boost::bad_lexical_cast& ) + { + GIDSet::const_iterator gid = gids.begin(); + std::advance( gid, i ); + LBWARN << "Error parsing circuit position for gid " + << *gid << std::endl; + } } + return positions; } -} -template -inline VMMLVector boost_mul_array_to_vmml_vector(const MVD3::Positions::subarray<1>::type& subarray) -{ - VMMLVector res; - res.iter_set(subarray.begin(), subarray.end()); - return res; -} - -inline brion::Quaternionf boost_mul_array_to_quaternion(const MVD3::Positions::subarray<1>::type& subarray) -{ - return brion::Quaternionf(subarray[1], subarray[2], subarray[3], subarray[0]); -} - -inline std::string swap_string(std::string& in) -{ - using namespace std; - std::string res; - swap(res, in); - return res; -} - - - - - -Vector3fs getPositionsMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids) -{ - const brion::NeuronMatrix& data = circuit_mvd2.get( - gids, brion::NEURON_POSITION_X | brion::NEURON_POSITION_Y | - brion::NEURON_POSITION_Z ); - - brion::GIDSet::const_iterator gid = gids.begin(); - Vector3fs positions( gids.size( )); - #pragma omp parallel for - for( size_t i = 0; i < gids.size(); ++i ) + Quaternionfs getRotations( const GIDSet& gids ) const final { - try - { - positions[i] = - brion::Vector3f( boost::lexical_cast< float >( data[i][0] ), - boost::lexical_cast< float >( data[i][1] ), - boost::lexical_cast< float >( data[i][2] )); - } - catch( const boost::bad_lexical_cast& ) + const float deg_rad2 = float( M_PI ) / 360.f; + const brion::NeuronMatrix& data = + _circuit.get( gids, brion::NEURON_ROTATION ); + Quaternionfs rotations( gids.size( )); + +#pragma omp parallel for + for( size_t i = 0; i < gids.size(); ++i ) { - LBWARN << "Error parsing circuit position or orientation for gid " - << *gid << ". Morphology not transformed." << std::endl; - positions[i] = Vector3f::ZERO; + try + { + // transform rotation Y angle in degree into rotation quaternion + const float angle2 = lexical_cast( data[i][0] )*deg_rad2; + rotations[i] = Quaternionf( 0.f, std::sin( angle2 ), + 0.f, std::cos( angle2 )); + } + catch( const boost::bad_lexical_cast& ) + { + GIDSet::const_iterator gid = gids.begin(); + std::advance( gid, i ); + LBWARN << "Error parsing circuit orientation for gid " + << *gid << std::endl; + } } - #pragma omp critical (brain_circuit_getPositions) - ++gid; + return rotations; } - return positions; -} - - -Vector3fs getPositionsMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids) -{ - const size_t n_elems = ((gids.size()>0)?gids.size():circuit_mvd3.getNbNeuron()); - Vector3fs results(n_elems); - MVD3::Range range = range_from_gidset(gids); - MVD3::Positions positions = circuit_mvd3.getPositions(range); - - assert(positions.shape()[1] ==3); - array_range_to_index(range, gids, positions, results, boost_mul_array_to_vmml_vector); - return results; - -} - -std::vector getMorphologiesNameMVD2(const brion::Circuit& circuit_mvd2, const brion::GIDSet & gids) -{ - brion::NeuronMatrix matrix = - circuit_mvd2.get( gids, brion::NEURON_MORPHOLOGY_NAME ); - std::vector res(matrix.shape()[0]); - - brion::NeuronMatrix::array_view<1>::type morpho_view = matrix[ boost::indices[brion::NeuronMatrix::index_range()][0]]; - std::transform(morpho_view.begin(), morpho_view.end(), res.begin(), swap_string); - return res; -} - - -std::vector getMorphologiesNameMVD3(MVD3::MVD3File& circuit_mvd3, const brion::GIDSet & gids) -{ - const size_t n_elems = ((gids.size()>0)?gids.size():circuit_mvd3.getNbNeuron()); - std::vector results(n_elems); - MVD3::Range range = range_from_gidset(gids); - std::vector morphos = circuit_mvd3.getMorphologies(range); - assert(morphos.size() == n_elems); - array_range_to_index(range, gids, morphos, results, swap_string); - return results; - -} + Strings getMorphologyNames( const GIDSet& gids ) const final + { + brion::NeuronMatrix matrix = + _circuit.get( gids, brion::NEURON_MORPHOLOGY_NAME ); + Strings res( matrix.shape()[ 0 ]); + + brion::NeuronMatrix::array_view<1>::type view = + matrix[ boost::indices[brion::NeuronMatrix::index_range( )][ 0 ]]; + std::transform( view.begin(), view.end(), res.begin(), toString ); + return res; + } +private: + brion::Circuit _circuit; +}; -Quaternionfs getQuatRotationsMVD2(const brion::Circuit& circuit_mvd2, const GIDSet& gids ) +class MVD3 : public Circuit::Impl { - const double deg_rad = boost::math::constants::pi() / 180.0; - const size_t n_elems = (gids.size()>0)?gids.size():circuit_mvd2.getNumNeurons(); - const brion::NeuronMatrix& data = circuit_mvd2.get( - gids, brion::NEURON_ROTATION ); - Quaternionfs rotations(n_elems); - - assert(data.shape()[0] == n_elems); - assert(data.shape()[1] == 1); +public: + MVD3( const brion::BlueConfig& config ) + : Impl( config ) + , _circuit( config.getCircuitSource().getPath( )) + {} - #pragma omp parallel for - for( size_t i = 0; i < n_elems; i++ ) + Vector3fs getPositions( const GIDSet& gids ) const final { - try - { - // transform rotation Y angle in degree into rotation quaternion - const double angle_y = boost::lexical_cast( data[i][0] )*deg_rad; - rotations[i] = - Quaternionf( 0, // x - std::sin(angle_y/2), // y - 0, // z - std::cos(angle_y/2)); // w - } - catch( const boost::bad_lexical_cast& ) - { - GIDSet::const_iterator it_gid = gids.begin(); - std::advance(it_gid, i); - LBWARN << "Error parsing circuit position or orientation for gid " - << *(it_gid) << ". Morphology not transformed." << std::endl; - rotations[i] = Quaternionf(0,0,0,0); - } + Vector3fs results( gids.size( )); + const ::MVD3::Range& range = getRange( gids ); + const ::MVD3::Positions& positions = _circuit.getPositions( range ); + assign( range, gids, positions, results, toVector3f ); + return results; } - return rotations; - } - -Quaternionfs getQuatRotationsMVD3(MVD3::MVD3File& circuit_mvd3, const GIDSet& gids ) -{ - const size_t n_elems = ((gids.size() >0)?gids.size():circuit_mvd3.getNbNeuron()); - Quaternionfs results(n_elems); - - MVD3::Range range = range_from_gidset(gids); - MVD3::Rotations rotations = circuit_mvd3.getRotations(range); - assert(rotations.shape()[1] ==4); - array_range_to_index(range, gids, rotations, results, boost_mul_array_to_quaternion); - return results; - } + Quaternionfs getRotations( const GIDSet& gids ) const final + { + Quaternionfs results( gids.size( )); + const ::MVD3::Range& range = getRange( gids ); + const ::MVD3::Rotations& rotations = _circuit.getRotations( range ); + assign( range, gids, rotations, results, toQuaternion ); + return results; + } + Strings getMorphologyNames( const GIDSet& gids ) const final + { + Strings results( gids.size( )); + const ::MVD3::Range& range = getRange( gids ); + const Strings& morphos = _circuit.getMorphologies( range ); + assign( range, gids, morphos, results, toString ); + return results; + } +private: + ::MVD3::MVD3File _circuit; +}; +Circuit::Impl* newImpl( const brion::BlueConfig& config ) +{ + const std::string circuit = config.getCircuitSource().getPath(); + if( boost::algorithm::ends_with( circuit, ".mvd2" )) + return new MVD2( config ); + return new MVD3( config ); +} Circuit::Circuit( const URI& source ) - : _impl( new Impl( brion::BlueConfig( source.getPath( )))) + : _impl( newImpl( brion::BlueConfig( source.getPath( )))) { } Circuit::Circuit( const brion::BlueConfig& config ) - : _impl( new Impl( config )) + : _impl( newImpl( config )) { } @@ -336,17 +272,17 @@ GIDSet Circuit::getGIDs( const std::string& target ) const URIs Circuit::getMorphologyURIs( const GIDSet& gids ) const { - const std::vector names = _impl->getMorphologiesName(gids); + const Strings& names = _impl->getMorphologyNames( gids ); URIs uris; - uris.reserve( names.size()); - for(std::vector::const_iterator it = names.begin(); it < names.end(); ++it ) - uris.push_back( _impl->getMorphologyURI( *it )); + uris.reserve( names.size( )); + for( Strings::const_iterator i = names.begin(); i < names.end(); ++i ) + uris.push_back( _impl->getMorphologyURI( *i )); return uris; } neuron::Morphologies Circuit::loadMorphologies( const GIDSet& gids, - const Coordinates coords ) const + const Coordinates coords ) const { const URIs& uris = getMorphologyURIs( gids ); neuron::Morphologies result; @@ -382,31 +318,24 @@ neuron::Morphologies Circuit::loadMorphologies( const GIDSet& gids, return result; } - - - Vector3fs Circuit::getPositions( const GIDSet& gids ) const { - return _impl->getPositions(gids); + return _impl->getPositions( gids ); } - Matrix4fs Circuit::getTransforms( const GIDSet& gids ) const { - const Vector3fs positions = _impl->getPositions(gids); - const Quaternionfs rotations = _impl->getQuatRot(gids); - assert(positions.size() == rotations.size()); + const Vector3fs& positions = _impl->getPositions( gids ); + const Quaternionfs& rotations = _impl->getRotations( gids ); + if( positions.size() != rotations.size( )) + throw std::runtime_error( + "Positions not equal rotations for given GIDs" ); - Matrix4fs transforms( positions.size(), Matrix4f::IDENTITY ); + Matrix4fs transforms( positions.size( )); - #pragma omp parallel for +#pragma omp parallel for for( size_t i = 0; i < positions.size(); ++i ) - { - Matrix4f& matrix = transforms[i]; - - rotations[i].get_rotation_matrix(matrix); - matrix.set_translation(positions[i]); - } + transforms[i] = Matrix4f( rotations[i], positions[i] ); return transforms; } diff --git a/brain/circuit.h b/brain/circuit.h index 873ebac..437e543 100644 --- a/brain/circuit.h +++ b/brain/circuit.h @@ -59,10 +59,10 @@ class Circuit : public boost::noncopyable /** * @return The set of GIDs for the given target name. If empty it will - * return the circuit target specified on the - * BlueConfig/CircuitConfig file. - * If the target cannot be found or an empty string was given and - * there is no circuit target, the return value is an empty set. + * return the circuit target specified on the BlueConfig or + * CircuitConfig file. If the target cannot be found or an empty + * string was given and there is no circuit target, the return value + * is an empty set. */ BRAIN_API GIDSet getGIDs( const std::string& target = "" ) const; @@ -83,11 +83,11 @@ class Circuit : public boost::noncopyable /** @return The local to world transformations of the given cells. */ BRAIN_API Matrix4fs getTransforms( const GIDSet& gids ) const; + class Impl; //!< @internal + private: - class Impl; Impl* _impl; }; - } #endif diff --git a/brain/types.h b/brain/types.h index 7c83b3d..4722275 100644 --- a/brain/types.h +++ b/brain/types.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando * * This file is part of Brion @@ -30,23 +30,24 @@ using namespace brion::enums; class Circuit; +using vmml::Matrix4f; +using vmml::Quaternionf; using vmml::Vector2i; using vmml::Vector3f; using vmml::Vector4f; -using vmml::Matrix4f; -using brion::Quaternionf; +using brion::GIDSet; +using brion::SectionTypes; +using brion::Strings; +using brion::URI; using brion::Vector2is; using brion::Vector3fs; using brion::Vector4fs; -typedef std::vector< Matrix4f > Matrix4fs; -using brion::uint32_ts; using brion::floats; -using brion::Quaternionfs; +using brion::uint32_ts; -using brion::SectionTypes; -using brion::GIDSet; -using brion::URI; +typedef std::vector< Matrix4f > Matrix4fs; +typedef std::vector< Quaternionf > Quaternionfs; typedef std::vector< URI > URIs; namespace neuron @@ -62,4 +63,3 @@ namespace neuron } #endif - diff --git a/brion/blueConfig.cpp b/brion/blueConfig.cpp index afca11a..a83858f 100644 --- a/brion/blueConfig.cpp +++ b/brion/blueConfig.cpp @@ -82,10 +82,7 @@ namespace detail class BlueConfig { public: - explicit BlueConfig( const std::string& source) : - names(), - table(), - mvd_type(CircuitMVD2) + explicit BlueConfig( const std::string& source ) { std::ifstream file( source.c_str( )); if( !file.is_open( )) @@ -211,8 +208,6 @@ class BlueConfig Strings names[CONFIGSECTION_ALL]; ValueTable table[CONFIGSECTION_ALL]; - CircuitType mvd_type; - }; } @@ -253,13 +248,15 @@ brion::Targets BlueConfig::getTargets() const URI BlueConfig::getCircuitSource() const { - URI uri; - const std::string circuit_filename = - ((_impl->mvd_type == CircuitMVD2)?(CIRCUIT_FILE):(CIRCUIT_FILE_MVD3)); + const std::string& path = get( CONFIGSECTION_RUN, _impl->getRun(), + BLUECONFIG_CIRCUIT_PATH_KEY ); + const std::string filename = path + + ( fs::exists( fs::path( path ) / CIRCUIT_FILE_MVD3 ) ? + CIRCUIT_FILE_MVD3 : CIRCUIT_FILE_MVD2 ); - uri.setScheme("file"); - uri.setPath( get( CONFIGSECTION_RUN, _impl->getRun(), - BLUECONFIG_CIRCUIT_PATH_KEY ) + circuit_filename ); + URI uri; + uri.setScheme( "file" ); + uri.setPath( filename ); return uri; } @@ -347,10 +344,6 @@ float BlueConfig::getTimestep() const return timestep; } -void BlueConfig::setCircuitType(CircuitType circuit_type){ - _impl->mvd_type = circuit_type; -} - std::ostream& operator << ( std::ostream& os, const BlueConfig& config ) { for( size_t i = 0; i < CONFIGSECTION_ALL; ++i ) diff --git a/brion/blueConfig.h b/brion/blueConfig.h index 697b3dc..f1e7dbf 100644 --- a/brion/blueConfig.h +++ b/brion/blueConfig.h @@ -102,13 +102,12 @@ class BlueConfig : public boost::noncopyable /** @name Semantic read API */ //@{ /** - * @return the URI to the circuit information. @sa Circuit. - * + * @return the URI to the circuit information. + * @sa Circuit * @version 1.7 */ BRION_API URI getCircuitSource() const; - /* * @return the URI to the location of synapse nrn files. * @version 1.7 @@ -150,12 +149,6 @@ class BlueConfig : public boost::noncopyable * @version 1.7 */ BRION_API float getTimestep() const; - - /** @brief define the circuit type to use ( e.g MVD2/MVD3 ). - * default is MVD2 - */ - BRION_API void setCircuitType(CircuitType circuit_type); - //@} diff --git a/brion/circuit.cpp b/brion/circuit.cpp index f21f039..6601ae1 100644 --- a/brion/circuit.cpp +++ b/brion/circuit.cpp @@ -45,7 +45,6 @@ enum Section class Circuit::Impl { public: - explicit Impl( const std::string& source ) { namespace fs = boost::filesystem; @@ -87,7 +86,6 @@ class Circuit::Impl } } - NeuronMatrix get( const GIDSet& gids, const uint32_t attributes ) const { const std::bitset< NEURON_ALL > bits( attributes ); @@ -202,7 +200,6 @@ class Circuit::Impl typedef stde::hash_map< uint32_t, Strings > CircuitTable; CircuitTable _table; - }; Circuit::Circuit( const std::string& source ) diff --git a/brion/constants.h b/brion/constants.h index 2fdecc2..c26c259 100644 --- a/brion/constants.h +++ b/brion/constants.h @@ -24,7 +24,7 @@ namespace brion { const char* const SPIKE_FILE = "/out.dat"; -const char* const CIRCUIT_FILE = "/circuit.mvd2"; +const char* const CIRCUIT_FILE_MVD2 = "/circuit.mvd2"; const char* const CIRCUIT_FILE_MVD3 = "/circuit.mvd3"; const char* const CIRCUIT_TARGET_FILE = "/start.target"; diff --git a/brion/enums.h b/brion/enums.h index 554ea19..033df5c 100644 --- a/brion/enums.h +++ b/brion/enums.h @@ -44,13 +44,6 @@ enum BlueConfigSection CONFIGSECTION_ALL //!< @internal must be last }; -/** The supported MVD circuit file format */ -enum CircuitType{ - CircuitMVD2=20, - CircuitMVD3=30 -}; - - /** * The supported formats for compartment reports. * @deprecated since version 1.4, kept until removed from BBPSDK and replaced by diff --git a/brion/types.h b/brion/types.h index faf2733..d32ef1b 100644 --- a/brion/types.h +++ b/brion/types.h @@ -64,8 +64,6 @@ using vmml::Vector4f; using vmml::Vector3d; using vmml::Vector4d; -typedef vmml::quaternionf Quaternionf; - typedef std::vector< size_t > size_ts; typedef std::vector< int32_t > int32_ts; typedef std::vector< uint16_t > uint16_ts; @@ -77,7 +75,6 @@ typedef std::vector< Vector3f > Vector3fs; typedef std::vector< Vector4f > Vector4fs; typedef std::vector< Vector3d > Vector3ds; typedef std::vector< Vector4d > Vector4ds; -typedef std::vector< Quaternionf > Quaternionfs; typedef std::vector< SectionType > SectionTypes; typedef std::vector< Target > Targets; typedef boost::shared_ptr< int32_ts > int32_tsPtr; diff --git a/tests/circuit.cpp b/tests/circuit.cpp index 3d815f0..bb87da0 100644 --- a/tests/circuit.cpp +++ b/tests/circuit.cpp @@ -70,7 +70,6 @@ BOOST_AUTO_TEST_CASE(test_all_attributes) const brion::NeuronMatrix& data = circuit.get( brion::GIDSet(), brion::NEURON_ALL_ATTRIBUTES ); - std::cout << data << std::endl; BOOST_CHECK_EQUAL( data.shape()[0], 10 ); // 10 neurons BOOST_CHECK_EQUAL( data.shape()[1], brion::NEURON_ALL ); @@ -95,7 +94,6 @@ BOOST_AUTO_TEST_CASE(test_some_attributes) gids.insert( 6 ); const brion::NeuronMatrix& data = circuit.get( gids, brion::NEURON_ETYPE | brion::NEURON_MORPHOLOGY_NAME ); - std::cout << data << std::endl; BOOST_CHECK_EQUAL( data.shape()[0], 2 ); // 2 neurons BOOST_CHECK_EQUAL( data.shape()[1], 2 ); // 2 attributes @@ -150,9 +148,6 @@ BOOST_AUTO_TEST_CASE(test_types) BOOST_CHECK_EQUAL( etypes[7], "cST" ); } - - - BOOST_AUTO_TEST_CASE( brain_circuit_constructor ) { brain::Circuit circuit( (brion::URI( bbp::test::getBlueconfig( )))); @@ -161,8 +156,6 @@ BOOST_AUTO_TEST_CASE( brain_circuit_constructor ) std::runtime_error ); } - - BOOST_AUTO_TEST_CASE( brain_circuit_target ) { const brain::Circuit circuit( (brion::URI( bbp::test::getBlueconfig( )))); @@ -184,7 +177,6 @@ BOOST_AUTO_TEST_CASE( brain_circuit_target ) second.begin(), second.end( )); } - BOOST_AUTO_TEST_CASE( brain_circuit_positions ) { const brain::Circuit circuit( (brion::URI( bbp::test::getBlueconfig( )))); @@ -225,10 +217,7 @@ void _checkMorphology( const brain::neuron::Morphology& morphology, transform ); const brain::Vector4fs& p = morphology.getPoints(); const brain::Vector4fs& q = reference.getPoints(); - - BOOST_CHECK( reference.getTransformation().equals(transform, 0.001)); - - + BOOST_CHECK( reference.getTransformation().equals( transform )); BOOST_REQUIRE( p.size() == q.size( )); for( size_t i = 0; i != p.size(); ++i ) @@ -295,28 +284,14 @@ BOOST_AUTO_TEST_CASE( load_global_morphologies ) _checkMorphology( *morphologies[0], "R-C010306G.h5", matrix ); } -void _check_transform(const brain::Matrix4f & trans, const brain::Quaternionf & quat, - const brain::Vector3f & pos) -{ - brain::Matrix4f mat; - quat.get_rotation_matrix(mat); - mat.set_translation(pos); - mat[3][3] =1; - BOOST_CHECK( mat.equals( trans, 0.001f)); - -// std::cout << trans << "\n" << mat << std::endl; - -} - BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) { brion::BlueConfig config(BBP_TEST_BLUECONFIG); - config.setCircuitType(brion::CircuitMVD3); - brain::Circuit circuit(config); + BOOST_CHECK_EQUAL( circuit.getGIDs().size(), 1000 ); - brain::Vector3fs positions = circuit.getPositions(brion::GIDSet()); - brain::Matrix4fs transforms = circuit.getTransforms(brion::GIDSet()); + brain::Vector3fs positions = circuit.getPositions( circuit.getGIDs( )); + brain::Matrix4fs transforms = circuit.getTransforms( circuit.getGIDs( )); BOOST_CHECK_EQUAL( positions.size(), 1000 ); BOOST_CHECK_EQUAL( transforms.size(), 1000 ); @@ -327,15 +302,21 @@ BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) ( positions[100] - brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )).length(), 0.000001f ); - _check_transform(transforms[20], brain::Quaternionf (0, 0.923706, 0, 0.383102), brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )); - _check_transform(transforms[100], brain::Quaternionf (0, -0.992667, 0, 0.120884), brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )); + BOOST_CHECK( transforms[20].equals( + brain::Matrix4f( + brain::Quaternionf( 0.383102, 0, 0.923706, 0 ), + brain::Vector3f( 30.12771, 1794.125911, 19.860587 )), + 0.00001f )); + BOOST_CHECK( transforms[100].equals( + brain::Matrix4f( + brain::Quaternionf ( 0.120884, 0, -0.992667, 0 ), + brain::Vector3f( 48.757924, 1824.458993, 15.302584 )), + 0.00001f )); } BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) { brion::BlueConfig config(BBP_TEST_BLUECONFIG); - config.setCircuitType(brion::CircuitMVD3); - brain::Circuit circuit(config); brion::GIDSet set; @@ -344,8 +325,8 @@ BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) set.insert(101); set.insert(501); - brain::Vector3fs positions = circuit.getPositions(set); - brain::Matrix4fs transforms = circuit.getTransforms(set); + const brain::Vector3fs& positions = circuit.getPositions( set ); + const brain::Matrix4fs& transforms = circuit.getTransforms( set ); BOOST_CHECK_EQUAL( positions.size(), 4 ); BOOST_CHECK_EQUAL( transforms.size(), 4 ); @@ -356,7 +337,14 @@ BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) ( positions[2] - brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )).length(), 0.000001f ); - _check_transform(transforms[1], brain::Quaternionf (0, 0.923706, 0, 0.383102), brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )); - _check_transform(transforms[2], brain::Quaternionf (0, -0.992667, 0, 0.120884), brion::Vector3f( 48.7579240000, 1824.4589930000, 15.3025840000 )); + BOOST_CHECK( transforms[1].equals( + brain::Matrix4f( + brain::Quaternionf( 0.383102, 0, 0.923706, 0 ), + brain::Vector3f( 30.12771, 1794.125911, 19.860587 )), + 0.00001f )); + BOOST_CHECK( transforms[2].equals( + brain::Matrix4f( + brain::Quaternionf( 0.120884, 0, -0.992667, 0 ), + brain::Vector3f( 48.757924, 1824.458993, 15.302584 )), + 0.00001f )); } - From 7fe7a3591cae8ebc771f3d87e2fa81e3014c807c Mon Sep 17 00:00:00 2001 From: Stefan Eilemann Date: Mon, 29 Feb 2016 08:27:41 +0100 Subject: [PATCH 3/5] Header hygiene --- brain/circuit.h | 3 ++- brain/neuron/morphologyImpl.h | 3 ++- brion/blueConfig.cpp | 3 ++- brion/circuit.cpp | 3 ++- brion/detail/meshBinary.h | 5 +++-- brion/morphology.h | 1 + brion/plugin/morphologySWC.cpp | 6 +++--- brion/plugin/spikeReportFile.cpp | 10 +++++----- brion/target.cpp | 7 ++++--- brion/types.h | 8 +------- 10 files changed, 25 insertions(+), 24 deletions(-) diff --git a/brain/circuit.h b/brain/circuit.h index 437e543..ceaf15a 100644 --- a/brain/circuit.h +++ b/brain/circuit.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando * * This file is part of Brion @@ -23,6 +23,7 @@ #include #include +#include // return value #include namespace brain diff --git a/brain/neuron/morphologyImpl.h b/brain/neuron/morphologyImpl.h index 3a7fd38..fa558a5 100644 --- a/brain/neuron/morphologyImpl.h +++ b/brain/neuron/morphologyImpl.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando * * This file is part of Brion @@ -25,6 +25,7 @@ #include #include +#include namespace brain { diff --git a/brion/blueConfig.cpp b/brion/blueConfig.cpp index a83858f..a977230 100644 --- a/brion/blueConfig.cpp +++ b/brion/blueConfig.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Daniel Nachbaur * * This file is part of Brion @@ -28,6 +28,7 @@ #include #include #include +#include namespace fs = boost::filesystem; namespace boost diff --git a/brion/circuit.cpp b/brion/circuit.cpp index 6601ae1..da7e63a 100644 --- a/brion/circuit.cpp +++ b/brion/circuit.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Daniel Nachbaur * Juan Hernando * @@ -25,6 +25,7 @@ #include #include #include +#include namespace brion { diff --git a/brion/detail/meshBinary.h b/brion/detail/meshBinary.h index e4d8bae..a28ac64 100644 --- a/brion/detail/meshBinary.h +++ b/brion/detail/meshBinary.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Daniel Nachbaur * * This file is part of Brion @@ -25,7 +25,8 @@ #include #include #include - +#include +#include namespace brion { diff --git a/brion/morphology.h b/brion/morphology.h index eaa7836..32d43e1 100644 --- a/brion/morphology.h +++ b/brion/morphology.h @@ -22,6 +22,7 @@ #include #include +#include // return value #include namespace brion diff --git a/brion/plugin/morphologySWC.cpp b/brion/plugin/morphologySWC.cpp index 27bb82d..e4844dc 100644 --- a/brion/plugin/morphologySWC.cpp +++ b/brion/plugin/morphologySWC.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando * * This file is part of Brion @@ -23,9 +23,9 @@ #include #include - -#include #include +#include +#include namespace brion { diff --git a/brion/plugin/spikeReportFile.cpp b/brion/plugin/spikeReportFile.cpp index e581c28..2f15cbf 100644 --- a/brion/plugin/spikeReportFile.cpp +++ b/brion/plugin/spikeReportFile.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Raphael Dumusc * * This file is part of Brion @@ -20,14 +20,14 @@ #include "spikeReportFile.h" #include "../detail/skipWhiteSpace.h" -#include -#include -#include #include #include - #include +#include +#include +#include #include +#include namespace brion { diff --git a/brion/target.cpp b/brion/target.cpp index 61c1ac6..1f4cbf3 100644 --- a/brion/target.cpp +++ b/brion/target.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Daniel Nachbaur * * This file is part of Brion @@ -19,11 +19,12 @@ #include "target.h" +#include +#include #include #include #include -#include -#include +#include namespace boost { diff --git a/brion/types.h b/brion/types.h index d32ef1b..4f6d30b 100644 --- a/brion/types.h +++ b/brion/types.h @@ -30,15 +30,9 @@ #include #include -#define VMMLIB_CUSTOM_CONFIG -#ifndef NDEBUG -# define VMMLIB_SAFE_ACCESSORS -#endif -#undef VMMLIB_ALIGN -#define VMMLIB_ALIGN( var ) var #pragma warning(push) #pragma warning(disable : 4996) -# include +# include #pragma warning(pop) /** @namespace brion Blue Brain File IO classes */ From c2c94fbcf579e77400d090410681d6f405412c4d Mon Sep 17 00:00:00 2001 From: Stefan Eilemann Date: Wed, 24 Feb 2016 08:43:05 +0100 Subject: [PATCH 4/5] Partial CR #41 --- tests/circuit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/circuit.cpp b/tests/circuit.cpp index bb87da0..7742775 100644 --- a/tests/circuit.cpp +++ b/tests/circuit.cpp @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE( load_global_morphologies ) BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) { - brion::BlueConfig config(BBP_TEST_BLUECONFIG); + brion::BlueConfig config(BBP_TEST_BLUECONFIG3); brain::Circuit circuit(config); BOOST_CHECK_EQUAL( circuit.getGIDs().size(), 1000 ); @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) { - brion::BlueConfig config(BBP_TEST_BLUECONFIG); + brion::BlueConfig config(BBP_TEST_BLUECONFIG3); brain::Circuit circuit(config); brion::GIDSet set; From 2da8b316ba0d94bb44912f28569925e63577a9d8 Mon Sep 17 00:00:00 2001 From: Stefan Eilemann Date: Wed, 24 Feb 2016 08:43:05 +0100 Subject: [PATCH 5/5] CR #41 --- .gitsubprojects | 4 ++-- brain/CMakeLists.txt | 9 +++++++-- brain/circuit.cpp | 37 +++++++++++++++++++++++-------------- brain/circuit.h | 1 + brion/blueConfig.h | 4 +--- tests/circuit.cpp | 39 ++++++++++++++++++++++++++++++--------- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/.gitsubprojects b/.gitsubprojects index a1edba0..9bcd6c2 100644 --- a/.gitsubprojects +++ b/.gitsubprojects @@ -1,5 +1,5 @@ # -*- mode: cmake -*- git_subproject(Servus https://github.com/HBPVIS/Servus.git 567f038) git_subproject(Lunchbox https://github.com/Eyescale/Lunchbox.git b41edcf) -git_subproject(vmmlib https://github.com/Eyescale/vmmlib.git b41e1a5) -git_subproject(MVDTool https://github.com/BlueBrain/MVDTool.git d700fa9) +git_subproject(vmmlib https://github.com/Eyescale/vmmlib.git 891fce2) +git_subproject(MVDTool https://github.com/BlueBrain/MVDTool.git 7801ae2) diff --git a/brain/CMakeLists.txt b/brain/CMakeLists.txt index 58c9afd..839b900 100644 --- a/brain/CMakeLists.txt +++ b/brain/CMakeLists.txt @@ -27,9 +27,14 @@ set(BRAIN_SOURCES ) set(BRAIN_PUBLIC_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) -set(BRAIN_LINK_LIBRARIES PUBLIC Brion vmmlib - PRIVATE MVDTool ${HDF5_LIBRARIES}) +set(BRAIN_LINK_LIBRARIES PUBLIC Brion vmmlib) set(BRAIN_INCLUDE_NAME brain) set(BRAIN_NAMESPACE brain) +if(TARGET MVDTool) + list(APPEND BRAIN_LINK_LIBRARIES MVDTool) +endif() common_library(Brain) +if(TARGET MVDTool) + target_compile_definitions(Brain PUBLIC BRAIN_USE_MVD3) +endif() diff --git a/brain/circuit.cpp b/brain/circuit.cpp index 81d79ba..254661f 100644 --- a/brain/circuit.cpp +++ b/brain/circuit.cpp @@ -1,5 +1,8 @@ /* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando + * Adrien.Devresse@epfl.ch + * Daniel.Nachbaur@epfl.ch + * Stefan.Eilemann@epfl.ch * * This file is part of Brion * @@ -27,23 +30,21 @@ #include -#include -#include +#ifdef BRAIN_USE_MVD3 +# include +# include +#endif #include -#include -#include - -#include -#include -#include using boost::lexical_cast; namespace brain { + namespace { +#ifdef BRAIN_USE_MVD3 bool isSequence( const GIDSet& gids ) { return ( *gids.rbegin() - *gids.begin() + 1 ) == gids.size(); @@ -76,15 +77,18 @@ void assign( const ::MVD3::Range& range, const GIDSet& gids, } } -Vector3f toVector3f( const ::MVD3::Positions::const_subarray< 1 >::type& subarray ) +Vector3f toVector3f( + const ::MVD3::Positions::const_subarray< 1 >::type& subarray ) { return Vector3f( subarray[0], subarray[1], subarray[2] ); } -Quaternionf toQuaternion( const ::MVD3::Rotations::const_subarray< 1 >::type& subarray ) +Quaternionf toQuaternion( + const ::MVD3::Rotations::const_subarray< 1 >::type& subarray ) { return Quaternionf( subarray[0], subarray[1], subarray[2], subarray[3] ); } +#endif std::string toString( const std::string& in ) { return in; } } @@ -161,7 +165,7 @@ class MVD2 : public Circuit::Impl Quaternionfs getRotations( const GIDSet& gids ) const final { - const float deg_rad2 = float( M_PI ) / 360.f; + const float deg2rad = float( M_PI ) / 180.f; const brion::NeuronMatrix& data = _circuit.get( gids, brion::NEURON_ROTATION ); Quaternionfs rotations( gids.size( )); @@ -172,9 +176,8 @@ class MVD2 : public Circuit::Impl try { // transform rotation Y angle in degree into rotation quaternion - const float angle2 = lexical_cast( data[i][0] )*deg_rad2; - rotations[i] = Quaternionf( 0.f, std::sin( angle2 ), - 0.f, std::cos( angle2 )); + const float angle = lexical_cast( data[i][0] ) * deg2rad; + rotations[i] = Quaternionf( angle, Vector3f( 0, 1, 0 )); } catch( const boost::bad_lexical_cast& ) { @@ -203,6 +206,7 @@ class MVD2 : public Circuit::Impl brion::Circuit _circuit; }; +#ifdef BRAIN_USE_MVD3 class MVD3 : public Circuit::Impl { public: @@ -241,13 +245,18 @@ class MVD3 : public Circuit::Impl private: ::MVD3::MVD3File _circuit; }; +#endif Circuit::Impl* newImpl( const brion::BlueConfig& config ) { const std::string circuit = config.getCircuitSource().getPath(); if( boost::algorithm::ends_with( circuit, ".mvd2" )) return new MVD2( config ); +#ifdef BRAIN_USE_MVD3 return new MVD3( config ); +#else + throw std::runtime_error( "MVD3 support requires CMake 3" ); +#endif } Circuit::Circuit( const URI& source ) diff --git a/brain/circuit.h b/brain/circuit.h index ceaf15a..73e5082 100644 --- a/brain/circuit.h +++ b/brain/circuit.h @@ -1,5 +1,6 @@ /* Copyright (c) 2013-2016, EPFL/Blue Brain Project * Juan Hernando + * Adrien.Devresse@epfl.ch * * This file is part of Brion * diff --git a/brion/blueConfig.h b/brion/blueConfig.h index f1e7dbf..b49c7df 100644 --- a/brion/blueConfig.h +++ b/brion/blueConfig.h @@ -102,7 +102,7 @@ class BlueConfig : public boost::noncopyable /** @name Semantic read API */ //@{ /** - * @return the URI to the circuit information. + * @return the URI to the circuit information. * @sa Circuit * @version 1.7 */ @@ -151,8 +151,6 @@ class BlueConfig : public boost::noncopyable BRION_API float getTimestep() const; //@} - - private: friend std::ostream& operator << ( std::ostream&, const BlueConfig& ); diff --git a/tests/circuit.cpp b/tests/circuit.cpp index 7742775..9aa46ec 100644 --- a/tests/circuit.cpp +++ b/tests/circuit.cpp @@ -284,7 +284,9 @@ BOOST_AUTO_TEST_CASE( load_global_morphologies ) _checkMorphology( *morphologies[0], "R-C010306G.h5", matrix ); } -BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) +#ifdef BRAIN_USE_MVD3 + +BOOST_AUTO_TEST_CASE(all_mvd3) { brion::BlueConfig config(BBP_TEST_BLUECONFIG3); brain::Circuit circuit(config); @@ -314,19 +316,19 @@ BOOST_AUTO_TEST_CASE(brain_circuit_all_mvd3) 0.00001f )); } -BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) +BOOST_AUTO_TEST_CASE(partial_mvd3) { brion::BlueConfig config(BBP_TEST_BLUECONFIG3); brain::Circuit circuit(config); - brion::GIDSet set; - set.insert(6); - set.insert(21); - set.insert(101); - set.insert(501); + brion::GIDSet gids; + gids.insert(6); + gids.insert(21); + gids.insert(101); + gids.insert(501); - const brain::Vector3fs& positions = circuit.getPositions( set ); - const brain::Matrix4fs& transforms = circuit.getTransforms( set ); + const brain::Vector3fs& positions = circuit.getPositions( gids ); + const brain::Matrix4fs& transforms = circuit.getTransforms( gids ); BOOST_CHECK_EQUAL( positions.size(), 4 ); BOOST_CHECK_EQUAL( transforms.size(), 4 ); @@ -348,3 +350,22 @@ BOOST_AUTO_TEST_CASE(brain_circuit_partial_mvd3) brain::Vector3f( 48.757924, 1824.458993, 15.302584 )), 0.00001f )); } + +BOOST_AUTO_TEST_CASE(morphology_names_mvd3) +{ + brion::BlueConfig config(BBP_TEST_BLUECONFIG3); + brain::Circuit circuit(config); + + brion::GIDSet gids; + gids.insert(21); + gids.insert(501); + + const brain::URIs& names = circuit.getMorphologyURIs( gids ); + BOOST_REQUIRE_EQUAL( names.size(), 2 ); + BOOST_CHECK( boost::algorithm::ends_with( std::to_string( names[0] ), + "dend-C280998A-P3_axon-sm110131a1-3_INT_idA.h5" )); + BOOST_CHECK( boost::algorithm::ends_with( std::to_string( names[1] ), + "dend-ch160801B_axon-Fluo55_low.h5" )); +} + +#endif