diff --git a/.gitexternals b/.gitexternals index a9f2ba5..5213f5d 100644 --- a/.gitexternals +++ b/.gitexternals @@ -1,2 +1,2 @@ # -*- mode: cmake -*- -# CMake/common https://github.com/Eyescale/CMake.git b0afcac +# CMake/common https://github.com/Eyescale/CMake.git dd25554 diff --git a/.gitsubprojects b/.gitsubprojects index f2e4a33..036db2e 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 891fce2) +git_subproject(Servus https://github.com/HBPVIS/Servus.git ea759d8) +git_subproject(Lunchbox https://github.com/Eyescale/Lunchbox.git 33c5ce7) +git_subproject(vmmlib https://github.com/Eyescale/vmmlib.git 9455489) git_subproject(MVDTool https://github.com/BlueBrain/MVDTool.git 3a41f39) diff --git a/brain/circuit.cpp b/brain/circuit.cpp index 26f2d11..2647b86 100644 --- a/brain/circuit.cpp +++ b/brain/circuit.cpp @@ -98,15 +98,23 @@ class Circuit::Impl public: Impl( const brion::BlueConfig& config ) : _morphologySource( config.getMorphologySource( )) - , _circuitTarget( config.getCircuitTarget( )) , _targetParsers( config.getTargets( )) {} virtual ~Impl() {} + virtual size_t getNumNeurons() const = 0; + + GIDSet getGIDs() const + { + brain::GIDSet gids; + for( size_t i = 0; i < getNumNeurons(); ++i ) + gids.insert( i + 1 ); + return gids; + } + GIDSet getGIDs( const std::string& target ) const { - return brion::Target::parse( - _targetParsers, target.empty() ? _circuitTarget : target ); + return brion::Target::parse( _targetParsers, target ); } virtual Vector3fs getPositions( const GIDSet& gids ) const = 0; @@ -123,7 +131,6 @@ class Circuit::Impl private: const brion::URI _morphologySource; - const std::string _circuitTarget; const brion::Targets _targetParsers; }; @@ -135,6 +142,11 @@ class MVD2 : public Circuit::Impl , _circuit( config.getCircuitSource().getPath( )) {} + size_t getNumNeurons() const final + { + return _circuit.getNumNeurons(); + } + Vector3fs getPositions( const GIDSet& gids ) const final { const brion::NeuronMatrix& data = _circuit.get( gids, @@ -215,6 +227,11 @@ class MVD3 : public Circuit::Impl , _circuit( config.getCircuitSource().getPath( )) {} + size_t getNumNeurons() const final + { + return _circuit.getNbNeuron(); + } + Vector3fs getPositions( const GIDSet& gids ) const final { Vector3fs results( gids.size( )); @@ -274,6 +291,11 @@ Circuit::~Circuit() delete _impl; } +GIDSet Circuit::getGIDs() const +{ + return _impl->getGIDs(); +} + GIDSet Circuit::getGIDs( const std::string& target ) const { return _impl->getGIDs( target ); @@ -349,10 +371,14 @@ Matrix4fs Circuit::getTransforms( const GIDSet& gids ) const } +size_t Circuit::getNumNeurons() const +{ + return _impl->getNumNeurons(); +} + Quaternionfs Circuit::getRotations( const GIDSet& gids ) const { return _impl->getRotations( gids ); } - } diff --git a/brain/circuit.h b/brain/circuit.h index ccfc635..04e6797 100644 --- a/brain/circuit.h +++ b/brain/circuit.h @@ -61,12 +61,13 @@ 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 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. + * return all the GIDs held by the circuit. If the target cannot be + * found, a runtime exception is raised. */ - BRAIN_API GIDSet getGIDs( const std::string& target = "" ) const; + BRAIN_API GIDSet getGIDs( const std::string& target ) const; + + /** @return All GIDs held by the circuit */ + BRAIN_API GIDSet getGIDs() const; /** @return The set of URIs to access the morphologies of the given cells */ BRAIN_API URIs getMorphologyURIs( const GIDSet& gids ) const; @@ -86,6 +87,8 @@ class Circuit : public boost::noncopyable BRAIN_API Matrix4fs getTransforms( const GIDSet& gids ) const; /** @return The local to world rotation of the given cells. */ BRAIN_API Quaternionfs getRotations( const GIDSet& gids ) const; + /** @return The number of neurons in the circuit. */ + BRAIN_API size_t getNumNeurons() const; class Impl; //!< @internal diff --git a/brion/blueConfig.cpp b/brion/blueConfig.cpp index a977230..6c6bcc9 100644 --- a/brion/blueConfig.cpp +++ b/brion/blueConfig.cpp @@ -239,11 +239,18 @@ brion::Targets BlueConfig::getTargets() const { const std::string& run = _impl->getRun(); brion::Targets targets; - targets.push_back( brion::Target( - get( brion::CONFIGSECTION_RUN, run, BLUECONFIG_NRN_PATH_KEY ) + - CIRCUIT_TARGET_FILE )); - targets.push_back( brion::Target( - get( brion::CONFIGSECTION_RUN, run, BLUECONFIG_TARGET_FILE_KEY ))); + + const std::string& nrnPath = + get( brion::CONFIGSECTION_RUN, run, BLUECONFIG_NRN_PATH_KEY ); + if( !nrnPath.empty( )) + targets.push_back( brion::Target( + nrnPath + "/" + CIRCUIT_TARGET_FILE )); + + const std::string& targetPath = + get( brion::CONFIGSECTION_RUN, run, BLUECONFIG_TARGET_FILE_KEY ); + if( !targetPath.empty( )) + targets.push_back( brion::Target( targetPath )); + return targets; } @@ -332,8 +339,7 @@ std::string BlueConfig::getCircuitTarget() const GIDSet BlueConfig::parseTarget( const std::string& target ) const { - return brion::Target::parse( - getTargets(), target.empty() ? _impl->getCircuitTarget() : target ); + return brion::Target::parse( getTargets(), target ); } float BlueConfig::getTimestep() const diff --git a/brion/blueConfig.h b/brion/blueConfig.h index 45cad6a..87b6959 100644 --- a/brion/blueConfig.h +++ b/brion/blueConfig.h @@ -139,8 +139,8 @@ class BlueConfig : public boost::noncopyable BRION_API std::string getCircuitTarget() const; /** - * @return the set of GIDs for the given target, or the circuit target if - * the given target is empty. + * @return the set of GIDs for the given target + * @throw std::runtime_error if target is invalid * @version 1.7 */ BRION_API GIDSet parseTarget( const std::string& target ) const; diff --git a/brion/target.cpp b/brion/target.cpp index 1f4cbf3..46d5da8 100644 --- a/brion/target.cpp +++ b/brion/target.cpp @@ -98,8 +98,7 @@ class Target ValueTable::const_iterator i = _targetValues.find( name ); if( i != _targetValues.end( )) return i->second; - static Strings empty; - return empty; + LBTHROW( std::runtime_error( name + " not a valid target" )); } private: @@ -151,20 +150,26 @@ void _parse( const Targets& targets, const std::string& name, GIDSet& gids ) { BOOST_FOREACH( const Target& target, targets ) { - const brion::Strings& values = target.get( name ); - BOOST_FOREACH( const std::string& value, values ) + try { - try - { - gids.insert( lexical_cast< uint32_t >( value.substr( 1 ))); - } - catch( ... ) + const brion::Strings& values = target.get( name ); + BOOST_FOREACH( const std::string& value, values ) { - if( value != name ) - _parse( targets, value, gids ); + try + { + gids.insert( lexical_cast< uint32_t >( value.substr( 1 ))); + } + catch( ... ) + { + if( value != name ) + _parse( targets, value, gids ); + } } + return; } + catch( ... ) {} } + LBTHROW( std::runtime_error( name + " not a valid target" )); } } diff --git a/brion/target.h b/brion/target.h index f429734..aefee13 100644 --- a/brion/target.h +++ b/brion/target.h @@ -67,6 +67,7 @@ class Target * * @param name target name to get the values from * @return list of values in the target. Can be targets and/or GIDSet + * @throw std::runtime_error if name is an invalid target * @version 1.0 */ BRION_API const Strings& get( const std::string& name ) const; @@ -80,6 +81,7 @@ class Target * @param targets the targets to parse * @param name the target name to parse * @return the set of cell identifiers parsed + * @throw std::runtime_error if name is an invalid target * @version 1.6 */ BRION_API static GIDSet parse( const Targets& targets, diff --git a/doc/Changelog.md b/doc/Changelog.md index dd51633..d5912f7 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -7,6 +7,12 @@ Changelog {#Changelog} Added the method brain::Circuit::getRotations * [46](https://github.com/BlueBrain/Brion/pull/46): Fixed a bug in enum to string conversions affecting morphologyConverter. +* [45](https://github.com/BlueBrain/Brion/pull/45): + Made targets optional. + - brain::Circuit::getGIDs() returns all GIDs handled by the circuit. + - brain::Circuit::getGIDs( target ) returns GIDS for a specified target. + - brain::Circuit::getNumNeurons() returns the total number of neurons in the + circuit. * [39](https://github.com/BlueBrain/Brion/pull/39): Add compartment report converter tool * [30](https://github.com/BlueBrain/Brion/pull/30), diff --git a/tests/blueConfig.cpp b/tests/blueConfig.cpp index 6b18e14..b487175 100644 --- a/tests/blueConfig.cpp +++ b/tests/blueConfig.cpp @@ -185,12 +185,9 @@ BOOST_AUTO_TEST_CASE( semantic_api ) BOOST_AUTO_TEST_CASE( parse_target ) { const brion::BlueConfig config( bbp::test::getBlueconfig( )); - const brion::GIDSet defaultTarget = config.parseTarget( "" ); - BOOST_CHECK( defaultTarget.size( )); + BOOST_CHECK_THROW( config.parseTarget( "" ), std::runtime_error ); const brion::GIDSet columnTarget = config.parseTarget( "Column" ); BOOST_CHECK( columnTarget.size( )); - // Can't use BOOST_CHECK_EQUAL because GIDSet lacks operator<< - BOOST_CHECK( defaultTarget == columnTarget ); const brion::GIDSet fromUserTarget = config.parseTarget( "AllL5CSPC" ); BOOST_CHECK( fromUserTarget.size( )); @@ -198,7 +195,5 @@ BOOST_AUTO_TEST_CASE( parse_target ) BOOST_CHECK( fromStartTarget.size( )); BOOST_CHECK( fromStartTarget == fromUserTarget ); - // Shouldn't this throw instead? - const brion::GIDSet empty = config.parseTarget( "unexistent" ); - BOOST_CHECK( empty.empty( )); + BOOST_CHECK_THROW( config.parseTarget( "unexistent" ), std::runtime_error ); } diff --git a/tests/circuit.cpp b/tests/circuit.cpp index 5494805..31f562c 100644 --- a/tests/circuit.cpp +++ b/tests/circuit.cpp @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE( brain_circuit_target ) const brion::BlueConfig config( bbp::test::getBlueconfig( )); brion::GIDSet first = circuit.getGIDs(); - brion::GIDSet second = config.parseTarget( "" ); + brion::GIDSet second = config.parseTarget( "Column" ); BOOST_CHECK_EQUAL_COLLECTIONS( first.begin(), first.end(), second.begin(), second.end( )); @@ -171,10 +171,13 @@ BOOST_AUTO_TEST_CASE( brain_circuit_target ) BOOST_CHECK_EQUAL_COLLECTIONS( first.begin(), first.end(), second.begin(), second.end( )); - first = circuit.getGIDs( "AllL5CSPC" ); - second = config.parseTarget( "AllL5CSPC" ); + first = circuit.getGIDs( "Layer1" ); + second = config.parseTarget( "Layer1" ); BOOST_CHECK_EQUAL_COLLECTIONS( first.begin(), first.end(), second.begin(), second.end( )); + + BOOST_CHECK_THROW( circuit.getGIDs( "!ThisIsAnInvalidTarget!" ), + std::runtime_error); } BOOST_AUTO_TEST_CASE( brain_circuit_positions ) @@ -290,12 +293,13 @@ BOOST_AUTO_TEST_CASE(all_mvd3) { brion::BlueConfig config(BBP_TEST_BLUECONFIG3); brain::Circuit circuit(config); - BOOST_CHECK_EQUAL( circuit.getGIDs().size(), 1000 ); + const size_t numNeurons = circuit.getNumNeurons( ); + BOOST_CHECK_EQUAL( circuit.getGIDs().size(), numNeurons ); 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 ); + BOOST_CHECK_EQUAL( positions.size(), numNeurons ); + BOOST_CHECK_EQUAL( transforms.size(), numNeurons ); BOOST_CHECK_SMALL( ( positions[20] - brion::Vector3f( 30.1277100000, 1794.1259110000, 19.8605870000 )).length(), @@ -306,10 +310,9 @@ BOOST_AUTO_TEST_CASE(all_mvd3) BOOST_CHECK( transforms[20].equals( brain::Matrix4f( - brain::Quaternionf( 0, 0.923706, 0, 0.383102 ), + brain::Quaternionf( 0, 0.923706, 0, 0.383102 ), brain::Vector3f( 30.12771, 1794.125911, 19.860587 )), 0.00001f )); - BOOST_CHECK( transforms[100].equals( brain::Matrix4f( brain::Quaternionf ( 0, -0.992667, 0, 0.120884 ),