diff --git a/.gitexternals b/.gitexternals index 3256f45..430419e 100644 --- a/.gitexternals +++ b/.gitexternals @@ -1,2 +1,2 @@ # -*- mode: cmake -*- -# CMake/common https://github.com/Eyescale/CMake.git dd94e50 +# CMake/common https://github.com/Eyescale/CMake.git 8c248b9 diff --git a/CMakeLists.txt b/CMakeLists.txt index f7b5c4e..1d570bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ common_find_package(Boost REQUIRED COMPONENTS date_time filesystem program_options regex system unit_test_framework) common_find_package(HDF5 SYSTEM REQUIRED COMPONENTS C CXX) common_find_package(Lunchbox REQUIRED) +common_find_package(NumPy 1.7 REQUIRED) common_find_package(OpenMP) common_find_package(PythonInterp) common_find_package(PythonLibs) diff --git a/brain/python/CMakeLists.txt b/brain/python/CMakeLists.txt index c820bd3..009c280 100644 --- a/brain/python/CMakeLists.txt +++ b/brain/python/CMakeLists.txt @@ -1,5 +1,6 @@ -# -# Copyright (c) 2011-2015, ahmet.bilgili@epfl.ch +# Copyright (c) 2013-2016, EPFL/Blue Brain Project +# ahmet.bilgili@epfl.ch +# juan.hernando@epfl.ch # # This file is part of Brion # @@ -12,17 +13,34 @@ if( NOT Boost_PYTHON${USE_BOOST_PYTHON_VERSION}_LIBRARY OR endif() set(BRAIN_PYTHON_SOURCE_FILES + arrayHelpers.cpp brain.cpp + circuit.cpp spikeReportWriter.cpp spikeReportReader.cpp - spikes.cpp) + spikes.cpp + synapses.cpp + submodules.cpp + neuron/module.cpp + neuron/morphology.cpp +) +if(TARGET BBPTestData) + list(APPEND BRAIN_PYTHON_SOURCE_FILES test.cpp) +endif() + +include_directories(${PYTHON_INCLUDE_DIRS} + ${PYTHON_NUMPY_INCLUDE_DIR}) -include_directories(${PYTHON_INCLUDE_DIRS}) add_library(brain_python MODULE ${BRAIN_PYTHON_SOURCE_FILES}) +common_compile_options(brain_python) add_dependencies(brain_python Brain) target_link_libraries(brain_python - Brain ${PYTHON_LIBRARIES} ${Boost_PYTHON${USE_BOOST_PYTHON_VERSION}_LIBRARY}) + PRIVATE Brain ${PYTHON_LIBRARIES} + ${Boost_PYTHON${USE_BOOST_PYTHON_VERSION}_LIBRARY}) +if(BBPTESTDATA_FOUND) + target_link_libraries(brain_python PRIVATE BBPTestData) +endif() set_target_properties(brain_python PROPERTIES OUTPUT_NAME "_brain" PREFIX "" @@ -32,7 +50,17 @@ configure_file(brain/__init__.py set_property(GLOBAL APPEND PROPERTY BRION_ALL_DEP_TARGETS brain_python) +macro(COPY_AND_INSTALL_PACKAGE_DIRECTORY DIRECTORY) + file(COPY brain/${DIRECTORY} + DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/brain) + + install(DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/brain/${DIRECTORY} + DESTINATION ${PYTHON_LIBRARY_SUFFIX}/brain + COMPONENT COMMON) +endmacro() + install(TARGETS brain_python LIBRARY DESTINATION ${PYTHON_LIBRARY_SUFFIX}/brain) install(FILES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/brain/__init__.py DESTINATION ${PYTHON_LIBRARY_SUFFIX}/brain) +copy_and_install_package_directory(neuron) diff --git a/brain/python/arrayHelpers.cpp b/brain/python/arrayHelpers.cpp new file mode 100644 index 0000000..3149a81 --- /dev/null +++ b/brain/python/arrayHelpers.cpp @@ -0,0 +1,256 @@ +/* Copyright (c) 2013-2016, Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "arrayHelpers.h" +#include "../types.h" +#include "../neuron/types.h" + +#include +#include +#include + +#include +#if NPY_API_VERSION >= 0x00000007 +# define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#endif +#include + +namespace bp = boost::python; + +namespace brain +{ + +namespace +{ + +// Helper clasess for template meta-programming of create_array_from_vector +template< typename T > struct NumpyArrayInfo; + +#define DECLARE_ARRAY_INFO( T, NPY_TYPE, NUM_DIM, DIMENSIONS... ) \ +template<> struct NumpyArrayInfo< T > \ +{ \ + NumpyArrayInfo( const T*, const npy_intp size ) \ + : dims{ size, DIMENSIONS } \ + {} \ + static const int ndims = NUM_DIM; \ + static const int type = NPY_TYPE; \ + npy_intp dims[ndims]; \ +} + +DECLARE_ARRAY_INFO( uint32_t, NPY_UINT, 1 ); +DECLARE_ARRAY_INFO( int, NPY_INT, 1 ); +DECLARE_ARRAY_INFO( size_t, NPY_LONG, 1 ); +DECLARE_ARRAY_INFO( float, NPY_FLOAT, 1 ); +DECLARE_ARRAY_INFO( neuron::SectionType, NPY_INT, 1 ); +DECLARE_ARRAY_INFO( Vector2i, NPY_INT, 2, 2 ); +DECLARE_ARRAY_INFO( Vector3f, NPY_FLOAT, 2, 3 ); +DECLARE_ARRAY_INFO( Vector4f, NPY_FLOAT, 2, 4 ); +DECLARE_ARRAY_INFO( Quaternionf, NPY_FLOAT, 2, 4 ); +DECLARE_ARRAY_INFO( Matrix4f, NPY_FLOAT, 3, 4, 4 ); + +// Functions for the boost::shared_ptr< std::vector< T >> to numpy converter + +template< typename T > +PyObject* _createNumpyArray( const T* data, const size_t size, + const AbstractCustodianPtr& keeper ) +{ + typedef NumpyArrayInfo< T > Info; + Info info( data, size ); + PyObject* array = PyArray_SimpleNewFromData( + Info::ndims, info.dims, Info::type, ( void* )data ); + + // Pointer sharing between the C++ shrared_ptr and the numpy array is only + // available for Numpy >= 1.7. + // PyArray_SetBaseObject steels the reference. + bp::object pykeeper( keeper ); + Py_INCREF( pykeeper.ptr( )); + if( PyArray_SetBaseObject(( PyArrayObject* )array, pykeeper.ptr( )) == -1 ) + { + // The reference is not clear about the error string having been + // set or not. Let's assume it has been. + Py_DECREF( array ); + Py_DECREF( pykeeper.ptr( )); + bp::throw_error_already_set(); + } + return array; +} + +template< typename T > +PyObject* _createNumpyArray( const std::vector< T >& vector, + const AbstractCustodianPtr& keeper ) +{ + return _createNumpyArray( vector.data(), vector.size(), keeper ); +} + +template< typename T > +struct VectorTsToNumpyArray +{ + static PyObject* convert( const VectorPtr< T >& input ) + { + AbstractCustodianPtr custodian( new Custodian< VectorPtr< T >>( input )); + return _createNumpyArray( *input, custodian ); + } +}; + +template< typename T > +struct ConstVectorTsWithCustodianToNumpyArray +{ + static PyObject* convert( + const ConstVectorWithCustodian< T >& input ) + { + PyObject* object = _createNumpyArray( input.vector, input.custodian ); + PyArrayObject* array = (PyArrayObject*)object; + PyArray_CLEARFLAGS( array, NPY_ARRAY_WRITEABLE ); + return object; + } +}; + +template< typename T > +struct ConstArrayTsWithCustodianToNumpyArray +{ + static PyObject* convert( const ConstArrayWithCustodian< T >& input ) + { + PyObject* object = _createNumpyArray( input.array, input.size, + input.custodian ); + PyArrayObject* array = ( PyArrayObject* )object; + PyArray_CLEARFLAGS( array, NPY_ARRAY_WRITEABLE ); + return object; + } +}; + +} + +// Import and registrations + +#if PY_VERSION_HEX >= 0x03000000 +void* _importArray() +{ + import_array(); + return PyArray_API; +} +#else +void _importArray() +{ + import_array(); +} +#endif + +#define REGISTER_ARRAY_CONVERTER( type ) \ + bp::to_python_converter< VectorPtr< type >, \ + VectorTsToNumpyArray< type >>(); \ + bp::to_python_converter< ConstVectorWithCustodian< type >, \ + ConstVectorTsWithCustodianToNumpyArray< type >>();\ + bp::to_python_converter< ConstArrayWithCustodian< type >, \ + ConstArrayTsWithCustodianToNumpyArray< type >>(); + +void importArray() +{ + _importArray(); + + REGISTER_ARRAY_CONVERTER( uint32_t ); + REGISTER_ARRAY_CONVERTER( int ); + REGISTER_ARRAY_CONVERTER( size_t ); + REGISTER_ARRAY_CONVERTER( float ); + REGISTER_ARRAY_CONVERTER( neuron::SectionType ); + REGISTER_ARRAY_CONVERTER( Vector2i ); + REGISTER_ARRAY_CONVERTER( Vector3f ); + REGISTER_ARRAY_CONVERTER( Vector4f ); + REGISTER_ARRAY_CONVERTER( Quaternionf ); + REGISTER_ARRAY_CONVERTER( Matrix4f ); + + bp::class_< AbstractCustodian, AbstractCustodianPtr >( "_Custodian" ); +} + +bp::object toNumpy( const brain::Matrix4f& matrix ) +{ + npy_intp dims[2] = { 4, 4 }; + void* data = malloc( sizeof( float ) * 16 ); + if( !data ) + { + PyErr_SetString( + PyExc_MemoryError, "Allocating numpy array for Matrix4f" ); + bp::throw_error_already_set(); + } + memcpy( data, &matrix, sizeof( brain::Matrix4f )); + PyObject* array = PyArray_New( + &PyArray_Type, 2, dims, NPY_FLOAT, + 0, data, 0, NPY_ARRAY_OWNDATA | NPY_ARRAY_F_CONTIGUOUS, 0 ); + return bp::object( bp::handle<>( array )); +} + +namespace +{ +template< typename T > +void _copyArrayToMatrix( PyArrayObject* array, Matrix4f& matrix ) +{ + for( size_t i = 0; i != 4; ++i ) + for( size_t j = 0; j != 4; ++j ) + matrix(i, j) = *static_cast< T* >(PyArray_GETPTR2( array, i, j )); +} + +} + +Matrix4f fromNumpy( const bp::object& o ) +{ + if( !PyArray_Check( o.ptr( ))) + { + PyErr_SetString( PyExc_ValueError, "Cannot convert object to Matrix4f" ); + bp::throw_error_already_set(); + } + PyArrayObject* array = reinterpret_cast< PyArrayObject* >( o.ptr( )); + + if( PyArray_NDIM( array ) != 2 || PyArray_DIMS(array)[0] != 4 || + PyArray_DIMS( array )[0] != 4 ) + { + PyErr_SetString( PyExc_ValueError, + "Cannot convert array to Matrix4f, bad dimensions" ); + bp::throw_error_already_set(); + } + + Matrix4f result; + switch( PyArray_TYPE( array )) + { + case NPY_FLOAT: + _copyArrayToMatrix< float >( array, result ); + break; + case NPY_DOUBLE: + _copyArrayToMatrix< double >( array, result ); + break; + case NPY_LONG: + _copyArrayToMatrix< long >( array, result ); + break; + case NPY_INT: + _copyArrayToMatrix< int >( array, result ); + break; + case NPY_UINT: + _copyArrayToMatrix< unsigned int >( array, result ); + break; + default: + { + std::stringstream msg; + PyArray_Descr* desc = PyArray_DESCR( array ); + msg << "Cannot convert numpy array of type " << desc->kind + << desc->elsize << " into Matrix4f" << std::endl; + PyErr_SetString( PyExc_ValueError, msg.str().c_str( )); + bp::throw_error_already_set(); + } + } + return result; +} + +} diff --git a/brain/python/arrayHelpers.h b/brain/python/arrayHelpers.h new file mode 100644 index 0000000..1786f18 --- /dev/null +++ b/brain/python/arrayHelpers.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2013-2016, Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef BRAIN_PYTHON_ARRAYHELPERS_H +#define BRAIN_PYTHON_ARRAYHELPERS_H + +#include + +#include +#include +#include + +namespace brain +{ + +void importArray(); + +template< typename T > +boost::python::object toNumpy( std::vector< T >&& vector ); + +/** The custodian object must be copy constructible. In general it's expected + to be a std::shared_ptr or boost::shared_ptr. */ +template< typename T, typename U > +boost::python::object toNumpy( const std::vector< T >& vector, + const U& custodian ); + +/** The custodian object must be copy constructible. In general it's expected + to be a std::shared_ptr or boost::shared_ptr. */ +template< typename T, typename U > +boost::python::object toNumpy( const T* array, size_t size, + const U& custodian ); + +boost::python::object toNumpy( const Matrix4f& matrix ); + +Matrix4f fromNumpy( const boost::python::object& object ); + +} + +#include "arrayHelpers.inc" +#endif diff --git a/brain/python/arrayHelpers.inc b/brain/python/arrayHelpers.inc new file mode 100644 index 0000000..a89f1ad --- /dev/null +++ b/brain/python/arrayHelpers.inc @@ -0,0 +1,102 @@ +/* Copyright (c) 2013-2016, Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +namespace brain +{ + +/** @internal */ +class AbstractCustodian +{ +public: + virtual ~AbstractCustodian() {} +}; + +/** @internal */ +template< typename T > +class Custodian : public AbstractCustodian +{ +public: + Custodian( const T& custodian ) : _custodian( custodian ) {} +private: + const T _custodian; +}; + +/** @internal */ +template< typename T > +using VectorPtr = std::shared_ptr< std::vector< T >>; + +// An boost::shared_ptr is used instead std::shared_ptr because it gets on +// well with Boost.Python. +typedef boost::shared_ptr< AbstractCustodian > AbstractCustodianPtr; + +template< typename T > +inline boost::python::object toNumpy( std::vector< T >&& vector ) +{ + return boost::python::object( + VectorPtr< T >( new std::vector< T >( std::move( vector )))); +} + +template< typename T > +struct ConstVectorWithCustodian +{ + ConstVectorWithCustodian( const std::vector< T >& v, + const AbstractCustodianPtr& c ) + : vector( v ) + , custodian( c ) + {} + + const std::vector< T >& vector; + AbstractCustodianPtr custodian; +}; + +template< typename T, typename U > +inline boost::python::object toNumpy( const std::vector< T >& vector, + const U& custodian ) +{ + AbstractCustodianPtr custodianProxy( new Custodian< U >( custodian )); + return boost::python::object( + ConstVectorWithCustodian< T >( vector, custodianProxy )); +} + +template< typename T > +struct ConstArrayWithCustodian +{ + ConstArrayWithCustodian( const T* v, const size_t s, + const AbstractCustodianPtr& c ) + : array( v ) + , size( s ) + , custodian( c ) + {} + + const T* array; + size_t size; + AbstractCustodianPtr custodian; +}; + +template< typename T, typename U > +inline boost::python::object toNumpy( const T* array, const size_t size, + const U& custodian ) +{ + AbstractCustodianPtr custodianProxy( new Custodian< U >( custodian )); + return boost::python::object( + ConstArrayWithCustodian< T >( array, size, custodianProxy )); +} + +} diff --git a/brain/python/brain.cpp b/brain/python/brain.cpp index a211789..22363f6 100644 --- a/brain/python/brain.cpp +++ b/brain/python/brain.cpp @@ -1,4 +1,3 @@ - /* Copyright (c) 2006-2016, Ahmet Bilgili * Juan Hernando * @@ -24,13 +23,66 @@ #include -#include "spikeReportReader.h" -#include "spikeReportWriter.h" -#include "spikes.h" +#include "arrayHelpers.h" + +#include + +namespace brain +{ + +void export_Circuit(); +void export_Spikes(); +void export_SpikeReportReader(); +void export_SpikeReportWriter(); +void export_Synapses(); +void export_test(); + +namespace neuron +{ + void export_module(); +} + +} + +struct Vector3fToTuple +{ + static PyObject* convert( const brain::Vector3f& v ) + { + boost::python::object tuple = + boost::python::make_tuple( v.x(), v.y(), v.z( )); + return boost::python::incref(tuple.ptr()); + } +}; + +struct URItoString +{ + static PyObject* convert( const servus::URI& uri ) + { + boost::python::object result( std::to_string( uri )); + return boost::python::incref(result.ptr()); + } +}; BOOST_PYTHON_MODULE(_brain) { - export_SpikeReportReader(); - export_SpikeReportWriter(); - export_Spikes(); + boost::python::to_python_converter< servus::URI, URItoString >(); + boost::python::to_python_converter< brain::Vector3f, Vector3fToTuple >(); + + brain::importArray(); + + boost::python::enum_< brain::SynapsePrefetch >( "SynapsePrefetch" ) + .value( "none", brain::SynapsePrefetch::none ) + .value( "attributes", brain::SynapsePrefetch::attributes ) + .value( "positions", brain::SynapsePrefetch::positions ) + .value( "all", brain::SynapsePrefetch::all ); + + brain::neuron::export_module(); + + brain::export_test(); + + brain::export_Circuit(); + brain::export_Spikes(); + brain::export_SpikeReportReader(); + brain::export_SpikeReportWriter(); + brain::export_Synapses(); } diff --git a/brain/python/brain/__init__.py b/brain/python/brain/__init__.py index 320a5fa..db88e59 100644 --- a/brain/python/brain/__init__.py +++ b/brain/python/brain/__init__.py @@ -1,6 +1,32 @@ +# Copyright (c) 2013-2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License version 3.0 as published +# by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + import sys as _sys if _sys.version_info[0] != ${USE_PYTHON_VERSION}: raise ImportError("Invalid Python version") from ._brain import * + +from . import neuron + +# Import the test helper module if present +try: + from ._brain import _test as test +except ImportError as e: + pass diff --git a/brain/python/brain/neuron/__init__.py b/brain/python/brain/neuron/__init__.py new file mode 100644 index 0000000..ed03d35 --- /dev/null +++ b/brain/python/brain/neuron/__init__.py @@ -0,0 +1,19 @@ +# Copyright (c) 2013-2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License version 3.0 as published +# by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from .._brain._neuron import * diff --git a/brain/python/circuit.cpp b/brain/python/circuit.cpp new file mode 100644 index 0000000..1a14154 --- /dev/null +++ b/brain/python/circuit.cpp @@ -0,0 +1,181 @@ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "arrayHelpers.h" +#include "helpers.h" +#include "types.h" + +#include +#include +#include + +namespace bp = boost::python; + +namespace brain +{ +namespace +{ + +CircuitPtr Circuit_initFromURI( const std::string& uri ) +{ + return CircuitPtr( new Circuit( URI( uri ))); +} + +bp::object Circuit_getAllGIDs( const Circuit& circuit ) +{ + return toPythonSet( circuit.getGIDs( )); +} + +bp::object Circuit_getGIDs( const Circuit& circuit, const std::string& target ) +{ + return toPythonSet( circuit.getGIDs( target )); +} + +bp::object Circuit_getRandomTargetGIDs( + const Circuit& circuit, const float fraction, const std::string& target ) +{ + return toPythonSet( circuit.getRandomGIDs( fraction, target )); +} + +bp::object Circuit_getRandomGIDs( const Circuit& circuit, const float fraction ) +{ + return toPythonSet( circuit.getRandomGIDs( fraction )); +} + +#define GET_CIRCUIT_PROPERTY_FOR_GIDS(property) \ + bp::object Circuit_get##property( const Circuit& circuit, bp::object gids ) \ +{ \ + return toNumpy( circuit.get##property( gidsFromPython( gids ))); \ +} + +GET_CIRCUIT_PROPERTY_FOR_GIDS(MorphologyTypes) +GET_CIRCUIT_PROPERTY_FOR_GIDS(ElectrophysiologyTypes) + +bp::object Circuit_getMorphologyURIs( const Circuit& circuit, bp::object gids ) +{ + return toPythonList( circuit.getMorphologyURIs( gidsFromPython( gids ))); +} + +#define GET_CIRCUIT_PROPERTY_VALUES(property) \ + bp::list Circuit_get##property( const Circuit& circuit )\ +{ \ + return toPythonList( circuit.get##property( )); \ +} +GET_CIRCUIT_PROPERTY_VALUES(MorphologyNames) +GET_CIRCUIT_PROPERTY_VALUES(ElectrophysiologyNames) + +bp::list Circuit_loadMorphologies( const Circuit& circuit, + bp::object gids, Circuit::Coordinates coords ) +{ + return toPythonList( + circuit.loadMorphologies( gidsFromPython( gids ), coords )); +} + +bp::object Circuit_getPositions( const Circuit& circuit, bp::object gids ) +{ + return toNumpy( circuit.getPositions( gidsFromPython( gids ))); +} + +bp::object Circuit_getTransforms( const Circuit& circuit, bp::object gids ) +{ + bp::object matrices = + toNumpy( circuit.getTransforms( gidsFromPython( gids ))); + // We want the result to be indexed using regular mathematical notation + // even if the actual storage is column-major. + return matrices.attr( "transpose" )( 0, 2, 1 ); +} + +bp::object Circuit_getRotations( const Circuit& circuit, bp::object gids ) +{ + return toNumpy( circuit.getRotations( gidsFromPython( gids ))); +} + +SynapsesWrapper Circuit_getAfferentSynapses( + const CircuitPtr& circuit, bp::object gids, + const brain::SynapsePrefetch prefetch ) +{ + return SynapsesWrapper( circuit->getAfferentSynapses( gidsFromPython( gids ), + prefetch ), + circuit ); +} + +SynapsesWrapper Circuit_getEfferentSynapses( + const CircuitPtr& circuit, bp::object gids, + const brain::SynapsePrefetch prefetch ) +{ + return SynapsesWrapper( circuit->getEfferentSynapses( gidsFromPython( gids ), + prefetch ), + circuit ); +} + +SynapsesWrapper Circuit_getProjectedSynapses( + const CircuitPtr& circuit, bp::object pre, bp::object post, + const brain::SynapsePrefetch prefetch ) +{ + return SynapsesWrapper( circuit->getProjectedSynapses( + gidsFromPython( pre ), gidsFromPython( post ), + prefetch ), + circuit ); +} + +} + +void export_Circuit() +{ + +bp::class_< Circuit, boost::noncopyable, CircuitPtr > + circuitWrapper( "Circuit", bp::no_init ); + +bp::scope circuitScope = circuitWrapper; + +bp::enum_< Circuit::Coordinates >( "Coordinates" ) + .value( "global_", Circuit::Coordinates::global ) + .value( "local", Circuit::Coordinates::local ) + ; + +circuitWrapper + .def( "__init__", bp::make_constructor( Circuit_initFromURI )) + .def( "gids", Circuit_getAllGIDs ) + .def( "gids", Circuit_getGIDs ) + .def( "random_gids", Circuit_getRandomTargetGIDs ) + .def( "random_gids", Circuit_getRandomGIDs ) + .def( "morphology_uris", Circuit_getMorphologyURIs ) + .def( "load_morphologies", Circuit_loadMorphologies ) + .def( "positions", Circuit_getPositions ) + .def( "morphology_types", Circuit_getMorphologyTypes ) + .def( "morphology_names", Circuit_getMorphologyNames ) + .def( "electrophysiology_types", Circuit_getElectrophysiologyTypes ) + .def( "electrophysiology_names", Circuit_getElectrophysiologyNames ) + .def( "transforms", Circuit_getTransforms ) + .def( "rotations", Circuit_getRotations ) + .def( "num_neurons", &Circuit::getNumNeurons ) + .def( "afferent_synapses", Circuit_getAfferentSynapses, + ( bp::arg( "gids"), bp::arg( "prefetch" ) = SynapsePrefetch::all )) + .def( "efferent_synapses", Circuit_getEfferentSynapses, + ( bp::arg( "gids"), bp::arg( "prefetch" ) = SynapsePrefetch::all )) + .def( "projected_synapses", Circuit_getProjectedSynapses, + ( bp::arg( "preGids"), bp::arg( "postGIDs" ), + bp::arg( "prefetch" ) = SynapsePrefetch::all )) + ; +} + +} diff --git a/brain/python/helpers.h b/brain/python/helpers.h new file mode 100644 index 0000000..21bbc44 --- /dev/null +++ b/brain/python/helpers.h @@ -0,0 +1,95 @@ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef BRAIN_PYTHON_HELPERS_H +#define BRAIN_PYTHON_HELPERS_H + +#include +#include + +#include + +namespace brain +{ + +template< typename T > +inline std::vector< T > vectorFromPython( boost::python::object o, + const char* errorMessage ) +{ + std::vector< T > vector; + try + { + vector.reserve( boost::python::len( o )); + boost::python::stl_input_iterator< T > i( o ), end; + for( ; i != end; ++i) + vector.push_back( *i ); + } + catch(...) + { + PyErr_SetString(PyExc_ValueError, errorMessage ); + boost::python::throw_error_already_set(); + } + return vector; +} + +template< typename T > +inline boost::python::list toPythonList( const std::vector< T >& vector ) +{ + boost::python::list result; + for( const T& i : vector ) + result.append( i ); + return result; +} + +inline boost::python::object toPythonSet( const GIDSet& ids ) +{ + boost::python::object set( boost::python::handle<>( PySet_New( 0 ))); + for( uint32_t gid : ids ) +#if PY_MAJOR_VERSION >= 3 + PySet_Add( set.ptr(), PyLong_FromLong( gid )); +#else + PySet_Add( set.ptr(), PyInt_FromLong( gid )); +#endif + + return set; +} + +inline GIDSet gidsFromPython( const boost::python::object iterable ) +{ + GIDSet result; + try + { + boost::python::stl_input_iterator< unsigned int > i( iterable ), end; + uint32_ts vector; + vector.reserve( len( iterable )); + for( ; i != end; ++i) + vector.push_back( *i ); + result.insert( vector.begin(), vector.end( )); + } + catch(...) + { + PyErr_SetString( PyExc_ValueError, + "Cannot convert argument to GID set" ); + boost::python::throw_error_already_set(); + } + return result; +} + +} +#endif diff --git a/brain/python/spikes.h b/brain/python/neuron/module.cpp similarity index 51% rename from brain/python/spikes.h rename to brain/python/neuron/module.cpp index 5e4c7ab..a674ad5 100644 --- a/brain/python/spikes.h +++ b/brain/python/neuron/module.cpp @@ -1,5 +1,5 @@ - -/* Copyright (c) 2006-2016, Juan Hernando +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando * * This file is part of Brion * @@ -17,9 +17,30 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef BRAIN_BINDING_SPIKES_H -#define BRAIN_BINDING_SPIKES_H +#include "../submodules.h" + +#include + +namespace brain +{ +namespace neuron +{ + +void export_Morphology(); + +void export_module() +{ + boost::python::scope neuron = exportSubmodule("neuron"); + + boost::python::enum_< neuron::SectionType >( "SectionType" ) + .value( "soma", neuron::SectionType::soma ) + .value( "axon", neuron::SectionType::axon ) + .value( "dendrite", neuron::SectionType::dendrite ) + .value( "apical_dendrite", neuron::SectionType::apicalDendrite ) + .value( "undefined", neuron::SectionType::undefined ); -void export_Spikes(); + export_Morphology(); +} -#endif +} +} diff --git a/brain/python/neuron/morphology.cpp b/brain/python/neuron/morphology.cpp new file mode 100644 index 0000000..6cf0eca --- /dev/null +++ b/brain/python/neuron/morphology.cpp @@ -0,0 +1,222 @@ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "../arrayHelpers.h" +#include "../helpers.h" + +#include +#include +#include + +#include +#include + +namespace bp = boost::python; + +namespace brain +{ +namespace neuron +{ + +namespace +{ + +template< typename Part > +class MorphologyPartWrapper : public Part +{ +public: + MorphologyPartWrapper( const Part& part, const MorphologyPtr& morphology_ ) + : Part( part ) + , morphology( morphology_ ) + {} + + MorphologyPtr morphology; +}; + +typedef MorphologyPartWrapper SomaWrapper; +typedef MorphologyPartWrapper
SectionWrapper; + +bp::object Soma_getProfilePoints( const SomaWrapper& soma ) +{ + return toNumpy( soma.getProfilePoints( )); +} + +#define GET_SECTION_ARRAY( Array ) \ + bp::object Section_get##Array( const SectionWrapper& section ) \ + { \ + return toNumpy( section.get##Array( )); \ + } + +GET_SECTION_ARRAY( Samples ) +GET_SECTION_ARRAY( SampleDistancesToSoma ) + +bp::object Section_getSamplesFromPositions( const SectionWrapper& section, + bp::object points ) +{ + const floats pointVector = vectorFromPython< float >( + points, "Cannot convert argument to float vector"); + return toNumpy( section.getSamples( pointVector )); +} + +bp::object Section_getParent( const SectionWrapper& section ) +{ + if( section.hasParent( )) + return bp::object( SectionWrapper( section.getParent( ), + section.morphology )); + return bp::object(); +} + +bp::object Section_getChildren( const SectionWrapper& section ) +{ + const Sections& sections = section.getChildren(); + bp::list result; + for( const auto& i : sections ) + result.append( SectionWrapper( i, section.morphology )); + return result; +} + +MorphologyPtr Morphology_initFromURI( const std::string& uri ) +{ + return MorphologyPtr( new Morphology( URI( uri ))); +} + +MorphologyPtr Morphology_initFromURIAndTransform( const std::string& uri, + bp::object transform ) +{ + return MorphologyPtr( new Morphology( URI( uri ), fromNumpy( transform ))); +} + +#define GET_MORPHOLOGY_ARRAY( Array ) \ + bp::object Morphology_get##Array( const MorphologyPtr& morphology ) \ + { \ + return toNumpy( morphology->get##Array(), morphology ); \ + } + +GET_MORPHOLOGY_ARRAY( Points ) +GET_MORPHOLOGY_ARRAY( Sections ) +GET_MORPHOLOGY_ARRAY( Apicals ) + +bp::object Morphology_getSectionIDs( const MorphologyPtr& morphology, + bp::object types ) +{ + const SectionTypes typeVector = vectorFromPython< SectionType >( + types, "Cannot convert argument to SectionType list"); + return toNumpy( morphology->getSectionIDs( typeVector )); +} + +bp::object Morphology_getSectionTypes( const MorphologyPtr& morphology ) +{ + return toNumpy( morphology->getSectionTypes( ), morphology ); +} + +bp::object Morphology_getSectionsByType( const MorphologyPtr& morphology, + bp::object types ) +{ + SectionTypes typeVector; + try + { + bp::extract< SectionType > extractor( types ); + if( extractor.check( )) + { + typeVector.push_back(( SectionType )extractor ); + } + else + { + bp::stl_input_iterator< SectionType > i( types ), end; + for( ; i != end; ++i ) + typeVector.push_back( *i ); + } + } + catch(...) + { + PyErr_SetString(PyExc_ValueError, + "Cannot convert argument to SectionType list"); + bp::throw_error_already_set(); + } + const Sections& sections = morphology->getSections( typeVector ); + bp::list result; + for( const auto& section : sections ) + result.append( SectionWrapper( section, morphology )); + return result; +} + +SectionWrapper Morphology_getSection( const MorphologyPtr& morphology, + const uint32_t id ) +{ + return SectionWrapper( morphology->getSection( id ), morphology ); +} + +SomaWrapper Morphology_getSoma( const MorphologyPtr& morphology ) +{ + return SomaWrapper( morphology->getSoma(), morphology ); +} + +bp::object Morphology_getTransformation( const MorphologyPtr& morphology ) +{ + return toNumpy( morphology->getTransformation( )); +} + +} + +void export_Morphology() +{ + +bp::class_< SomaWrapper >( + "Soma", bp::no_init ) + .def( "profile_points", Soma_getProfilePoints ) + .def( "mean_radius", &Soma::getMeanRadius ) + .def( "centroid", &Soma::getCentroid ) + ; + +bp::class_< SectionWrapper >( + "Section", bp::no_init ) + .def( bp::self == bp::self ) + .def( "id", &Section::getID ) + .def( "type", &Section::getType ) + .def( "length", &Section::getLength ) + .def( "samples", Section_getSamples ) + .def( "samples", Section_getSamplesFromPositions ) + .def( "distance_to_soma", &Section::getDistanceToSoma ) + .def( "sample_distances_to_soma", Section_getSampleDistancesToSoma ) + .def( "parent", Section_getParent ) + .def( "children", Section_getChildren ) + ; + +bp::class_< Morphology, boost::noncopyable, MorphologyPtr >( + "Morphology", bp::no_init ) + .def( "__init__", bp::make_constructor( Morphology_initFromURI )) + .def( "__init__", bp::make_constructor( Morphology_initFromURIAndTransform )) + .def( "points", Morphology_getPoints ) + .def( "sections", Morphology_getSections ) + .def( "section_types", Morphology_getSectionTypes) + .def( "apicals", Morphology_getApicals ) + .def( "section_ids", Morphology_getSectionIDs ) + .def( "sections", Morphology_getSectionsByType ) + .def( "section", Morphology_getSection ) + .def( "soma", Morphology_getSoma ) + .def( "transformation", Morphology_getTransformation ) + ; + +} + +} +} diff --git a/brain/python/spikeReportReader.cpp b/brain/python/spikeReportReader.cpp index 9dbfd2b..358c91f 100644 --- a/brain/python/spikeReportReader.cpp +++ b/brain/python/spikeReportReader.cpp @@ -1,4 +1,3 @@ - /* Copyright (c) 2006-2016, Ahmet Bilgili * Juan Hernando * @@ -24,25 +23,25 @@ #include #include -using namespace brain; -using namespace boost::python; +namespace bp = boost::python; -namespace +namespace brain { -SpikeReportReaderPtr initURI( const std::string& uri ) +namespace +{ +SpikeReportReaderPtr _initURI( const std::string& uri ) { return SpikeReportReaderPtr( new SpikeReportReader( brion::URI( uri ))); } - } void export_SpikeReportReader() { -class_< SpikeReportReader, boost::noncopyable >( - "SpikeReportReader", no_init ) - .def( "__init__", make_constructor( initURI )) +bp::class_< SpikeReportReader, boost::noncopyable >( + "SpikeReportReader", bp::no_init ) + .def( "__init__", bp::make_constructor( _initURI )) .def( "close", &SpikeReportReader::close ) .def( "getStartTime", &SpikeReportReader::getStartTime ) .def( "getEndTime", &SpikeReportReader::getEndTime ) @@ -55,3 +54,5 @@ class_< SpikeReportReader, boost::noncopyable >( .def( "isStream", &SpikeReportReader::isStream ); } + +} diff --git a/brain/python/spikeReportWriter.cpp b/brain/python/spikeReportWriter.cpp index 6b3e576..1ab87f7 100644 --- a/brain/python/spikeReportWriter.cpp +++ b/brain/python/spikeReportWriter.cpp @@ -1,4 +1,3 @@ - /* Copyright (c) 2006-2016, Ahmet Bilgili * Juan Hernando * @@ -24,27 +23,29 @@ #include #include -using namespace boost::python; -using namespace brain; +namespace bp = boost::python; -namespace +namespace brain { -SpikeReportWriterPtr initURI( const std::string& uri ) +namespace +{ +SpikeReportWriterPtr _initURI( const std::string& uri ) { return SpikeReportWriterPtr( new SpikeReportWriter( brion::URI( uri ))); } - } void export_SpikeReportWriter() { -class_< SpikeReportWriter, boost::noncopyable >( - "SpikeReportWriter", no_init ) - .def( "__init__", make_constructor( initURI )) +bp::class_< SpikeReportWriter, boost::noncopyable >( + "SpikeReportWriter", bp::no_init ) + .def( "__init__", bp::make_constructor( _initURI )) .def( "close", &SpikeReportWriter::close ) .def( "writeSpikes", &SpikeReportWriter::writeSpikes ) ; } + +} diff --git a/brain/python/spikes.cpp b/brain/python/spikes.cpp index 683ccdf..4557811 100644 --- a/brain/python/spikes.cpp +++ b/brain/python/spikes.cpp @@ -20,8 +20,10 @@ #include -using namespace boost::python; -using namespace brain; +namespace bp = boost::python; + +namespace brain +{ namespace { @@ -29,7 +31,7 @@ struct Conversion { static PyObject* convert(const std::pair< float, unsigned int >& pair) { - tuple t = make_tuple(pair.first, pair.second); + bp::tuple t = bp::make_tuple(pair.first, pair.second); Py_INCREF(t.ptr()); return t.ptr(); } @@ -39,11 +41,13 @@ struct Conversion void export_Spikes() { -to_python_converter< brion::Spike, Conversion >(); +bp::to_python_converter< brion::Spike, Conversion >(); -class_< Spikes >( "Spikes", no_init ) - .def( "__iter__", range( &Spikes::begin, &Spikes::end )) +bp::class_< Spikes >( "Spikes", bp::no_init ) + .def( "__iter__", bp::range( &Spikes::begin, &Spikes::end )) .def( "__len__", &Spikes::size ) ; } + +} diff --git a/brain/python/submodules.cpp b/brain/python/submodules.cpp new file mode 100644 index 0000000..fe4c542 --- /dev/null +++ b/brain/python/submodules.cpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "submodules.h" + +namespace brain +{ + +namespace bp = boost::python; + +bp::scope exportSubmodule( const std::string& name ) +{ + // I'm not fully sure that the module stack is left in a conventional + // state after this code is run. For example the module neuron appears + // as built-in in the interpreter, which smells fishy. + // Nonetheless, the current implementation allows to do: + // + // import _brain + // import _brain._neuron + // from _brain._neuron import X (auto-completion of X works in IPython) + // + // And that's good enough. + + bp::object module( bp::handle<>( bp::borrowed( + PyImport_AddModule(( "brain._brain._" + name).c_str( ))))); + bp::scope().attr(( "_" + name).c_str( )) = module; + bp::scope moduleScope = module; + // Despite these paths are not completely true in the build directory, + // they ensures that _brain._neuron can be found and that + // _brain.so is not loaded twice. + moduleScope.attr( "__package__" ) = "brain._brain"; + moduleScope.attr( "__path__" ) = "brain._brain"; + + return moduleScope; +} + +} diff --git a/brain/python/spikeReportReader.h b/brain/python/submodules.h similarity index 72% rename from brain/python/spikeReportReader.h rename to brain/python/submodules.h index 4ed6efb..b20e917 100644 --- a/brain/python/spikeReportReader.h +++ b/brain/python/submodules.h @@ -1,6 +1,5 @@ - -/* Copyright (c) 2006-2015, Ahmet Bilgili - * Juan Hernando +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando * * This file is part of Brion * @@ -18,9 +17,15 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef BRAIN_BINDING_SPIKEREPORTREADER_H -#define BRAIN_BINDING_SPIKEREPORTREADER_H +#ifndef BRAIN_PYTHON_SUBMODULES +#define BRAIN_PYTHON_SUBMODULES + +#include + +namespace brain +{ -void export_SpikeReportReader(); +boost::python::scope exportSubmodule( const std::string& name ); +} #endif diff --git a/brain/python/synapses.cpp b/brain/python/synapses.cpp new file mode 100644 index 0000000..eb90eff --- /dev/null +++ b/brain/python/synapses.cpp @@ -0,0 +1,154 @@ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "types.h" +#include "arrayHelpers.h" + +#include +#include + +#include + +namespace bp = boost::python; + +namespace brain +{ + +namespace +{ + +bool nonzero( const SynapsesWrapper& ) +{ + return true; +} + +SynapseWrapper Synapses_get( const SynapsesWrapper& synapses, long int index ) +{ + if( index < 0 ) + index = synapses.size() + index; + if( index < 0 || size_t(index) >= synapses.size( )) + { + PyErr_SetString( PyExc_IndexError, "Index out of bounds" ); + bp::throw_error_already_set(); + } + return SynapseWrapper( synapses[index], synapses, synapses._circuit ); +} + +#define GET_SYNAPSES_ARRAY_PROPERTY( type, name ) \ +bp::object Synapses_##name( const SynapsesWrapper& synapses ) \ + { return toNumpy( synapses.name(), synapses.size(), synapses._impl ); } + +GET_SYNAPSES_ARRAY_PROPERTY( size_t, indices ) +GET_SYNAPSES_ARRAY_PROPERTY( uin32_t, preGIDs ) +GET_SYNAPSES_ARRAY_PROPERTY( uin32_t, preSectionIDs ) +GET_SYNAPSES_ARRAY_PROPERTY( uin32_t, preSegmentIDs ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preDistances ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preSurfaceXPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preSurfaceYPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preSurfaceZPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preCenterXPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preCenterYPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, preCenterZPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( uint32_t, postGIDs ) +GET_SYNAPSES_ARRAY_PROPERTY( uint32_t, postSectionIDs ) +GET_SYNAPSES_ARRAY_PROPERTY( uint32_t, postSegmentIDs ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postDistances ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postSurfaceXPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postSurfaceYPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postSurfaceZPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postCenterXPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postCenterYPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, postCenterZPositions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, delays ) +GET_SYNAPSES_ARRAY_PROPERTY( float, conductances ) +GET_SYNAPSES_ARRAY_PROPERTY( float, utilizations ) +GET_SYNAPSES_ARRAY_PROPERTY( float, depressions ) +GET_SYNAPSES_ARRAY_PROPERTY( float, facilitations ) +GET_SYNAPSES_ARRAY_PROPERTY( float, decays ) +GET_SYNAPSES_ARRAY_PROPERTY( int, efficacies ) + +} + +void export_Synapses() +{ + +bp::class_< SynapseWrapper >( "Synapse", bp::no_init ) + .def( "pre_gid", &Synapse::getPresynapticGID ) + .def( "pre_section", &Synapse::getPresynapticSectionID ) + .def( "pre_segment", &Synapse::getPresynapticSegmentID ) + .def( "pre_distance", &Synapse::getPresynapticDistance ) + .def( "pre_center_position", &Synapse::getPresynapticCenterPosition ) + .def( "pre_surface_position", &Synapse::getPresynapticSurfacePosition ) + .def( "post_gid", &Synapse::getPostsynapticGID ) + .def( "post_section", &Synapse::getPostsynapticSectionID ) + .def( "post_segment", &Synapse::getPostsynapticSegmentID ) + .def( "post_distance", &Synapse::getPostsynapticDistance ) + .def( "post_center_position", &Synapse::getPostsynapticCenterPosition ) + .def( "post_surface_position", &Synapse::getPostsynapticSurfacePosition ) + .def( "delay", &Synapse::getDelay ) + .def( "conductance", &Synapse::getConductance ) + .def( "utilization", &Synapse::getUtilization ) + .def( "depression", &Synapse::getDepression ) + .def( "facilitation", &Synapse::getFacilitation ) + .def( "decay", &Synapse::getDecay ) + .def( "efficacy", &Synapse::getEfficacy ) + ; + +bp::class_< SynapsesWrapper >( "Synapses", bp::no_init ) + .def( "__nonzero__", nonzero ) + .def( "__len__", &Synapses::size ) + .def( "__getitem__", Synapses_get ) + // There is no need to wrap the iterator, Python provides one out of the + // box thanks to __len__ and __getitem__ + .def( "empty", &Synapses::empty ) + .def( "indices", Synapses_indices ) + .def( "pre_gids", Synapses_preGIDs ) + .def( "pre_section_ids", Synapses_preSectionIDs ) + .def( "pre_segment_ids", Synapses_preSegmentIDs ) + .def( "pre_distances", Synapses_preDistances ) + .def( "pre_surface_x_positions", Synapses_preSurfaceXPositions ) + .def( "pre_surface_y_positions", Synapses_preSurfaceYPositions ) + .def( "pre_surface_z_positions", Synapses_preSurfaceZPositions ) + .def( "pre_center_x_positions", Synapses_preCenterXPositions ) + .def( "pre_center_y_positions", Synapses_preCenterYPositions ) + .def( "pre_center_z_positions", Synapses_preCenterZPositions ) + .def( "post_gids", Synapses_postGIDs ) + .def( "post_section_ids", Synapses_postSectionIDs ) + .def( "post_segment_ids", Synapses_postSegmentIDs ) + .def( "post_distances", Synapses_postDistances ) + .def( "post_surface_x_positions", Synapses_postSurfaceXPositions ) + .def( "post_surface_y_positions", Synapses_postSurfaceYPositions ) + .def( "post_surface_z_positions", Synapses_postSurfaceZPositions ) + .def( "post_center_x_positions", Synapses_postCenterXPositions ) + .def( "post_center_y_positions", Synapses_postCenterYPositions ) + .def( "post_center_z_positions", Synapses_postCenterZPositions ) + .def( "delays", Synapses_delays ) + .def( "conductances", Synapses_conductances ) + .def( "utilizations", Synapses_utilizations ) + .def( "depressions", Synapses_depressions ) + .def( "facilitations", Synapses_facilitations ) + .def( "decays", Synapses_decays ) + .def( "efficacies", Synapses_efficacies ) + ; + +} + +} diff --git a/brain/python/spikeReportWriter.h b/brain/python/test.cpp similarity index 55% rename from brain/python/spikeReportWriter.h rename to brain/python/test.cpp index 09dd44f..7fdcaef 100644 --- a/brain/python/spikeReportWriter.h +++ b/brain/python/test.cpp @@ -1,6 +1,4 @@ - -/* Copyright (c) 2006-2016, Ahmet Bilgili - * Juan Hernando +/* Copyright (c) 2016, Juan Hernando * * This file is part of Brion * @@ -18,9 +16,31 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef BRAIN_BINDING_SPIKEREPORTWRITER_H -#define BRAIN_BINDING_SPIKEREPORTWRITER_H +#ifndef BRION_USE_BBPTESTDATA +namespace brain { void export_test() {} } +#else + +#include + +#include "submodules.h" + +#include + +namespace brain +{ + +void export_test() +{ + boost::python::list configs; + for( const auto& config : bbp::test::getBlueconfigs( )) + configs.append( config ); + + boost::python::scope test = brain::exportSubmodule("test"); -void export_SpikeReportWriter(); + test.attr("blue_config") = bbp::test::getBlueconfig(); + test.attr("blue_configs") = configs; + test.attr("circuit_config") = bbp::test::getCircuitconfig(); +} +} #endif diff --git a/brain/python/types.h b/brain/python/types.h new file mode 100644 index 0000000..a0417cd --- /dev/null +++ b/brain/python/types.h @@ -0,0 +1,72 @@ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project + * Juan Hernando + * + * This file is part of Brion + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef BRAIN_PYTHON_TYPES +#define BRAIN_PYTHON_TYPES + +#include +#include +#include + +namespace brain +{ + +typedef boost::shared_ptr CircuitPtr; + +/** Synapse container wrapping helper. + + This class is used to keep a valid reference to the circuit together with any + Synapse container held by a Python variable. +*/ +class SynapsesWrapper : public Synapses +{ +public: + SynapsesWrapper( const SynapsesStream& stream, const CircuitPtr& circuit ) + : Synapses( stream) + , _circuit( circuit ) + {} + + CircuitPtr _circuit; + + // Unprotecting the _impl member because it needs to be accessed by the + // wrapping to use it as custodian. + using Synapses::_impl; +}; + +/** Synapse container wrapping helper. + + This class is used to keep a valid reference to the circuit together with any + Synapse container held by a Python variable. +*/ +class SynapseWrapper : public Synapse +{ +public: + SynapseWrapper( Synapse&& synapse, + const Synapses& synapses, const CircuitPtr& circuit ) + : Synapse( std::move( synapse )) + , _synapses( synapses ) + , _circuit( circuit ) + {} + + Synapses _synapses; + CircuitPtr _circuit; +}; + +} +#endif diff --git a/brain/synapse.cpp b/brain/synapse.cpp index 386c7ff..e993845 100644 --- a/brain/synapse.cpp +++ b/brain/synapse.cpp @@ -142,7 +142,7 @@ float Synapse::getDecay() const int Synapse::getEfficacy() const { - return _synapses.efficacys()[_index]; + return _synapses.efficacies()[_index]; } } diff --git a/brain/synapses.cpp b/brain/synapses.cpp index db3d30c..5fb902e 100644 --- a/brain/synapses.cpp +++ b/brain/synapses.cpp @@ -58,7 +58,7 @@ template void _allocate( T& data, const size_t size ) } } -struct Synapses::Impl +struct Synapses::Impl : public Synapses::BaseImpl { Impl( const Circuit& circuit, const GIDSet& gids, const GIDSet& filterGIDs, const bool afferent, const SynapsePrefetch prefetch ) @@ -402,8 +402,9 @@ Synapses& Synapses::operator=( Synapses&& rhs ) size_t Synapses::size() const { - lunchbox::ScopedRead mutex( _impl->_lock ); - return _impl->_size; + const Impl& impl = static_cast< const Impl& >( *_impl ); + lunchbox::ScopedRead mutex( impl._lock ); + return impl._size; } bool Synapses::empty() const @@ -428,170 +429,198 @@ Synapse Synapses::operator[]( const size_t index_ ) const const size_t* Synapses::indices() const { - lunchbox::ScopedRead mutex( _impl->_lock ); - if( !_impl->_index ) + const Impl& impl = static_cast< const Impl& >( *_impl ); + lunchbox::ScopedRead mutex( impl._lock ); + if( !impl._index ) LBTHROW( std::runtime_error( "No synapse index file available" )); - return _impl->_index.get(); + return impl._index.get(); } const uint32_t* Synapses::preGIDs() const { - return _impl->_preGID.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + return impl._preGID.get(); } const uint32_t* Synapses::preSectionIDs() const { - _impl->_ensureAttributes(); - return _impl->_preSectionID.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._preSectionID.get(); } const uint32_t* Synapses::preSegmentIDs() const { - _impl->_ensureAttributes(); - return _impl->_preSegmentID.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._preSegmentID.get(); } const float* Synapses::preDistances() const { - _impl->_ensureAttributes(); - return _impl->_preDistance.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._preDistance.get(); } const float* Synapses::preSurfaceXPositions() const { - _impl->_ensurePositions(); - return _impl->_preSurfacePositionX.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._preSurfacePositionX.get(); } const float* Synapses::preSurfaceYPositions() const { - _impl->_ensurePositions(); - return _impl->_preSurfacePositionY.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._preSurfacePositionY.get(); } const float* Synapses::preSurfaceZPositions() const { - _impl->_ensurePositions(); - return _impl->_preSurfacePositionZ.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._preSurfacePositionZ.get(); } const float* Synapses::preCenterXPositions() const { - _impl->_ensurePositions(); - return _impl->_preCenterPositionX.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._preCenterPositionX.get(); } const float* Synapses::preCenterYPositions() const { - _impl->_ensurePositions(); - return _impl->_preCenterPositionY.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._preCenterPositionY.get(); } const float* Synapses::preCenterZPositions() const { - _impl->_ensurePositions(); - return _impl->_preCenterPositionZ.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._preCenterPositionZ.get(); } const uint32_t* Synapses::postGIDs() const { - return _impl->_postGID.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + return impl._postGID.get(); } const uint32_t* Synapses::postSectionIDs() const { - _impl->_ensureAttributes(); - return _impl->_postSectionID.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._postSectionID.get(); } const uint32_t* Synapses::postSegmentIDs() const { - _impl->_ensureAttributes(); - return _impl->_postSegmentID.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._postSegmentID.get(); } const float* Synapses::postDistances() const { - _impl->_ensureAttributes(); - return _impl->_postDistance.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._postDistance.get(); } const float* Synapses::postSurfaceXPositions() const { - _impl->_ensurePositions(); - return _impl->_postSurfacePositionX.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._postSurfacePositionX.get(); } const float* Synapses::postSurfaceYPositions() const { - _impl->_ensurePositions(); - return _impl->_postSurfacePositionY.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._postSurfacePositionY.get(); } const float* Synapses::postSurfaceZPositions() const { - _impl->_ensurePositions(); - return _impl->_postSurfacePositionZ.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._postSurfacePositionZ.get(); } const float* Synapses::postCenterXPositions() const { - _impl->_ensurePositions(); - return _impl->_postCenterPositionX.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._postCenterPositionX.get(); } const float* Synapses::postCenterYPositions() const { - _impl->_ensurePositions(); - return _impl->_postCenterPositionY.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._postCenterPositionY.get(); } const float* Synapses::postCenterZPositions() const { - _impl->_ensurePositions(); - return _impl->_postCenterPositionZ.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensurePositions(); + return impl._postCenterPositionZ.get(); } const float* Synapses::delays() const { - _impl->_ensureAttributes(); - return _impl->_delay.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._delay.get(); } const float* Synapses::conductances() const { - _impl->_ensureAttributes(); - return _impl->_conductance.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._conductance.get(); } const float* Synapses::utilizations() const { - _impl->_ensureAttributes(); - return _impl->_utilization.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._utilization.get(); } const float* Synapses::depressions() const { - _impl->_ensureAttributes(); - return _impl->_depression.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._depression.get(); } const float* Synapses::facilitations() const { - _impl->_ensureAttributes(); - return _impl->_facilitation.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._facilitation.get(); } const float* Synapses::decays() const { - _impl->_ensureAttributes(); - return _impl->_decay.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._decay.get(); } -const int* Synapses::efficacys() const +const int* Synapses::efficacies() const { - _impl->_ensureAttributes(); - return _impl->_efficacy.get(); + const Impl& impl = static_cast< const Impl& >( *_impl ); + impl._ensureAttributes(); + return impl._efficacy.get(); } } diff --git a/brain/synapses.h b/brain/synapses.h index e669af1..4b6b4bb 100644 --- a/brain/synapses.h +++ b/brain/synapses.h @@ -205,16 +205,25 @@ class Synapses BRAIN_API const float* decays() const; /** @return the absolute synaptic efficacies in millivolts. */ - BRAIN_API const int* efficacys() const; + BRAIN_API const int* efficacies() const; //@} +protected: + // The Impl pointer needs to be used in the Python wrapping as a custodian. + // Instead of moving the Impl declaration outside the implementation, this + // base class is used to give access to a virtual destructor, which is all + // the wrapping needs. + struct BaseImpl + { + virtual ~BaseImpl() {}; + }; + struct Impl; + std::shared_ptr< const BaseImpl > _impl; + private: friend struct detail::SynapsesStream; Synapses( const Circuit& circuit, const GIDSet& gids, const GIDSet& filterGIDs, bool afferent, SynapsePrefetch prefetch ); - - struct Impl; - std::shared_ptr< const Impl > _impl; }; } diff --git a/doc/Changelog.md b/doc/Changelog.md index 1ac5aa9..7736961 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -3,6 +3,8 @@ Changelog {#Changelog} # Release 1.9.0 (git master) +* [89](https://github.com/BlueBrain/Brion/pull/89): + Python wrapping of brain classes. * [88](https://github.com/BlueBrain/Brion/pull/88): - Brain namespace enums made strongly typed. - Fix for brain::Section::getSamples for sections where the first point diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 603d2c7..e2391ca 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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 @@ -22,3 +22,5 @@ else() file(GLOB EXCLUDE_FROM_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} brain/*.cpp) endif() include(CommonCTest) + +add_subdirectory(brain/python) \ No newline at end of file diff --git a/tests/blueConfig.cpp b/tests/blueConfig.cpp index b487175..4425f12 100644 --- a/tests/blueConfig.cpp +++ b/tests/blueConfig.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/brain/circuit.cpp b/tests/brain/circuit.cpp index 9b139c4..c0b872e 100644 --- a/tests/brain/circuit.cpp +++ b/tests/brain/circuit.cpp @@ -3,29 +3,18 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/tests/brain/morphology.cpp b/tests/brain/morphology.cpp index 9201aae..f5754a3 100644 --- a/tests/brain/morphology.cpp +++ b/tests/brain/morphology.cpp @@ -4,29 +4,18 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/tests/brain/python/CMakeLists.txt b/tests/brain/python/CMakeLists.txt new file mode 100644 index 0000000..fd90bf4 --- /dev/null +++ b/tests/brain/python/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# Change this number when adding tests to force a CMake run: 1 + +if(NOT TARGET BBPTestData OR NOT TARGET brain_python) + return() +endif() + +set(PYTHON_TEST_DEPENDENCIES brain_python) +include(CommonPythonCTest) +configure_file(setup.py.in ${PYTHON_TEST_OUTPUT_PATH}/setup.py) diff --git a/tests/brain/python/circuit.py b/tests/brain/python/circuit.py new file mode 100644 index 0000000..758bbe9 --- /dev/null +++ b/tests/brain/python/circuit.py @@ -0,0 +1,94 @@ +# Copyright (c) 2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License version 3.0 as published +# by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import setup +import brain + +import unittest + +class TestCircuitOpen(unittest.TestCase): + + def test_bad_open(self): + self.assertRaises(RuntimeError, lambda: brain.Circuit("foo")) + + def test_open(self): + circuit = brain.Circuit(brain.test.circuit_config) + +class TestCircuit(unittest.TestCase): + def setUp(self): + self.circuit = brain.Circuit(brain.test.circuit_config) + + def test_gids(self): + assert(self.circuit.num_neurons() == 1000) + gids = self.circuit.gids('Column') + assert(len(gids) == 1000) + for gid, index in zip(gids, range(1000)): + assert(gid == index + 1) + + assert(len(self.circuit.gids()) == 1000) + + assert(len(self.circuit.random_gids(0.1)) == 100) + assert(len(self.circuit.random_gids(0.1, 'Column')) == 100) + + def test_geometry(self): + gids = self.circuit.gids() + transforms = self.circuit.transforms(gids) + positions = self.circuit.positions(gids) + rotations = self.circuit.rotations(gids) + assert(transforms.shape == (1000, 4, 4)) + assert(positions.shape == (1000, 3)) + assert(rotations.shape == (1000, 4)) + + def test_load_morphology(self): + morphologies = self.circuit.load_morphologies( + [1, 100, 1000], brain.Circuit.Coordinates.local) + morphologies = self.circuit.load_morphologies( + [1, 100, 1000], brain.Circuit.Coordinates.global_) + + def test_metypes(self): + count = self.circuit.num_neurons() + mnames = self.circuit.morphology_names() + assert(len(mnames) == 9) + for t in ['L1_SLAC', 'L23_PC', 'L23_MC', 'L4_PC', 'L4_MC', + 'L5_TTPC1', 'L5_MC', 'L6_TPC_L1', 'L6_MC']: + assert(t in mnames) + + gids = self.circuit.gids('L23_PC') + mtypes = self.circuit.morphology_types(gids) + assert(len(mtypes) == len(gids)) + for t in mtypes: + assert(mnames[t] == 'L23_PC') + + enames = self.circuit.electrophysiology_names() + assert(len(enames) == 2) + for t in ['cACint', 'cADpyr']: + assert(t in enames) + etypes = self.circuit.electrophysiology_types(gids) + assert(len(etypes) == len(gids)) + for t in etypes: + assert(enames[t] == 'cADpyr') + + def test_bad_gids(self): + self.assertRaises(RuntimeError, + lambda: self.circuit.load_morphologies( + [100000], brain.Circuit.Coordinates.local)) + +if __name__ == '__main__': + unittest.main() + + diff --git a/tests/brain/python/morphology.py b/tests/brain/python/morphology.py new file mode 100644 index 0000000..8dde843 --- /dev/null +++ b/tests/brain/python/morphology.py @@ -0,0 +1,174 @@ +# Copyright (c) 2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License version 3.0 as published +# by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import setup +import brain +import numpy +from brain.neuron import Morphology + +import unittest + +morphology_path = setup.test_data_path + "/h5/test_neuron.h5" + +class TestConstructors(unittest.TestCase): + + def test_simple(self): + morphology = Morphology(morphology_path) + + def test_transform(self): + transform = numpy.array([[1, 0, 0, 7], + [0, 1, 0, 8], + [0, 0, 1, 9], + [0, 0, 0, 1]]) + morphology = Morphology(morphology_path, transform) + assert(numpy.allclose(morphology.transformation(), transform)) + + def test_transform_errors(self): + self.assertRaises(ValueError, + lambda: Morphology(morphology_path, 'foo')) + transform = numpy.array([[2, 2], [2, 2]]) + self.assertRaises(ValueError, + lambda: Morphology(morphology_path, transform)) + transform = numpy.array([[1, 0, 0, 7], + [0, 'a', 0, 8], + [0, 0, 1, 9], + [0, 0, 0, 1]]) + + def test_bad(self): + self.assertRaises(RuntimeError, lambda: Morphology("mars")) + +class TestCircuitFunctions(unittest.TestCase): + def setUp(self): + self.circuit = brain.Circuit(brain.test.circuit_config) + + def test_uris(self): + uris = self.circuit.morphology_uris([1, 2, 3]) + for uri in uris: + Morphology(uri) + + def test_load(self): + circuit = self.circuit + + def is_centered_at_zero(m): + return numpy.allclose(m.soma().centroid(), [0, 0, 0], atol=1e-7) + + morphologies = circuit.load_morphologies([1, 2, 3], + circuit.Coordinates.local) + for m in morphologies: + assert(is_centered_at_zero(m)) + + morphologies = circuit.load_morphologies([1, 2, 3], + circuit.Coordinates.global_) + for m in morphologies: + assert(not is_centered_at_zero(m)) + +class TestMorphologyFunctions(unittest.TestCase): + def setUp(self): + self.morphology = Morphology(morphology_path) + + def test_array_accessors(self): + points = self.morphology.points() + assert(points.shape == (96, 4)) + sections = self.morphology.sections() + assert(sections.shape == (13, 2)) + section_types = self.morphology.section_types() + assert(section_types.shape == (13,)) + apicals = self.morphology.apicals() + assert(len(apicals) == 0) + + def test_section(self): + Type = brain.neuron.SectionType + neurites = [Type.axon, Type.dendrite, Type.apical_dendrite] + + ids = self.morphology.section_ids([Type.soma]) + assert(ids == [0]) + self.assertRaises(RuntimeError, lambda: self.morphology.section(0)) + + ids = self.morphology.section_ids(neurites) + assert(len(ids) == 12) + + sections = self.morphology.sections([Type.soma]) + assert(len(sections) == 0) + sections = self.morphology.sections(neurites) + assert(len(sections) == 12) + for id in ids: + self.morphology.section(int(id)) + self.assertRaises(RuntimeError, lambda: self.morphology.section(1234)) + + def test_soma(self): + soma = self.morphology.soma() + assert(len(soma.profile_points()) == 4) + for p in soma.profile_points(): + assert(len(p) == 4) + assert(numpy.isclose(soma.mean_radius(), 0.1)) + assert(soma.centroid() == (0, 0, 0)) + +class TestMorphologyMemoryManagement(unittest.TestCase): + + def setUp(self): + self.morphology = Morphology(morphology_path) + + def test_soma(self): + soma = self.morphology.soma() + del self.morphology + points = soma.profile_points() + sum = numpy.zeros(4) + for p in points: + sum += p + + def test_section(self): + section = self.morphology.section(1) + del self.morphology + samples = section.samples() + sum = numpy.zeros(4) + for s in samples: + sum += s + +class TestSectionFunctions(unittest.TestCase): + def setUp(self): + self.morphology = Morphology(morphology_path) + self.section = self.morphology.section(1) + + def test_equality(self): + assert(self.section == self.section) + assert(self.section == self.morphology.section(1)) + assert(self.section != self.morphology.section(2)) + + def test_simple_data(self): + assert(self.section.id() == 1) + assert(self.section.type() == brain.neuron.SectionType.axon) + assert(numpy.isclose(self.section.children()[0].distance_to_soma(), + self.section.length())) + + def test_samples(self): + distances = self.section.sample_distances_to_soma() + assert(distances.shape == (11,)) + samples = self.section.samples() + assert(samples.shape == (11, 4)) + samples = self.section.samples([0, 0.5, 1.0]) + assert(samples.shape == (3, 4)) + + def test_tree(self): + assert(self.section.parent() == None) + children = self.section.children() + assert(len(children) == 2) + for child in children: + assert(child.parent() == self.section) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/brain/python/setup.py.in b/tests/brain/python/setup.py.in new file mode 100644 index 0000000..8a08174 --- /dev/null +++ b/tests/brain/python/setup.py.in @@ -0,0 +1,28 @@ +# Copyright (c) 2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License version 3.0 as published +# by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys + +prefix_paths = '${CMAKE_PREFIX_PATH}'.split(';') +prefix_paths[:] = [item + '/${PYTHON_LIBRARY_SUFFIX}' for item in prefix_paths] +sys.path = (['${CMAKE_BINARY_DIR}/lib', + '${CMAKE_INSTALL_PREFIX}/lib', + '${CMAKE_INSTALL_PREFIX}/${PYTHON_LIBRARY_SUFFIX}'] + + prefix_paths + sys.path) + +test_data_path = "${PROJECT_SOURCE_DIR}/tests/data" diff --git a/tests/brain/python/synapses.py b/tests/brain/python/synapses.py new file mode 100644 index 0000000..38bff91 --- /dev/null +++ b/tests/brain/python/synapses.py @@ -0,0 +1,147 @@ +# Copyright (c) 2016, EPFL/Blue Brain Project +# Juan Hernando +# +# This file is part of Brion +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License version 3.0 as published +# by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import setup +import brain + +import unittest + +class TestCircuitFunctions(unittest.TestCase): + def setUp(self): + self.circuit = brain.Circuit(brain.test.circuit_config) + + def test_afferent(self): + gids = [340, 350] + synapses = self.circuit.afferent_synapses(gids) + assert(len(synapses) == 312) + synapses = self.circuit.afferent_synapses(gids, + brain.SynapsePrefetch.none) + assert(len(synapses) == 312) + + def test_efferent(self): + gids = [340, 350] + synapses = self.circuit.efferent_synapses(gids) + assert(len(synapses) == 331) + synapses = self.circuit.efferent_synapses(gids, + brain.SynapsePrefetch.none) + assert(len(synapses) == 331) + + def test_projection(self): + pre = self.circuit.gids("Layer5") + post = self.circuit.gids("Layer2") + synapses = self.circuit.projected_synapses(pre, post) + print(len(synapses) == 1888) + synapses = self.circuit.projected_synapses(pre, post, + brain.SynapsePrefetch.none) + assert(len(synapses) == 1888) + +class TestSynapsesAccessors(unittest.TestCase): + + def setUp(self): + self.circuit = brain.Circuit(brain.test.circuit_config) + self.synapses = self.circuit.afferent_synapses([320]) + + def test_iterator(self): + synapses = [s for s in self.synapses] + assert(len(synapses) == len(self.synapses)) + + def test_getitem(self): + synapse = self.synapses[0] + synapse = self.synapses[-1] + size = len(self.synapses) + synapse = self.synapses[size - 1] + synapse = self.synapses[-size] + self.assertRaises(IndexError, lambda: self.synapses[-size - 1]) + self.assertRaises(IndexError, lambda: self.synapses[size]) + +class TestSynapseArrays(unittest.TestCase): + def setUp(self): + self.circuit = brain.Circuit(brain.test.circuit_config) + self.synapses = self.circuit.afferent_synapses([320]) + + def test_arrays(self): + size = len(self.synapses) + + for function in ["pre_gids", "pre_section_ids", "pre_segment_ids", + "pre_distances", "pre_surface_x_positions", + "pre_surface_y_positions", "pre_surface_z_positions", + "pre_center_x_positions", "pre_center_y_positions", + "pre_center_z_positions", + "post_gids", "post_section_ids", "post_segment_ids", + "post_distances", "post_surface_x_positions", + "post_surface_y_positions", "post_surface_z_positions", + "post_center_x_positions", "post_center_y_positions", + "post_center_z_positions", + "delays", "conductances", "utilizations", "depressions", + "facilitations", "decays", "efficacies"]: + array = getattr(self.synapses, function)() + assert(array.shape == (size,)) + # This data is not available in the test dataset, so we only check the + # function exists + self.assertRaises(RuntimeError, lambda: self.synapses.indices()) + +class TestSynapse(unittest.TestCase): + + def setUp(self): + self.circuit = brain.Circuit(brain.test.circuit_config) + self.synapses = self.circuit.afferent_synapses([320]) + self.synapse = self.synapses[0] + + def test_synapse(self): + pre_gid = self.synapse.pre_gid() + pre_section_id = self.synapse.pre_section() + pre_segment_id = self.synapse.pre_segment() + pre_distance = self.synapse.pre_distance() + pre_surface_position = self.synapse.pre_surface_position() + pre_center_position = self.synapse.pre_center_position() + post_gid = self.synapse.post_gid() + post_section_id = self.synapse.post_section() + post_segment_id = self.synapse.post_segment() + post_distance = self.synapse.post_distance() + post_surface_position = self.synapse.post_surface_position() + post_center_position = self.synapse.post_center_position() + delay = self.synapse.delay() + conductance = self.synapse.conductance() + utilization = self.synapse.utilization() + depression = self.synapse.depression() + facilitation = self.synapse.facilitation() + decay = self.synapse.decay() + efficacy = self.synapse.efficacy() + +class TestMemoryManagement(unittest.TestCase): + + def test_synapses(self): + circuit = brain.Circuit(brain.test.circuit_config) + synapses = circuit.afferent_synapses([320], brain.SynapsePrefetch.none) + del circuit + delays = synapses.delays() + for delay in delays: + assert(delay < 10) + + def test_synapse(self): + circuit = brain.Circuit(brain.test.circuit_config) + synapses = circuit.afferent_synapses([320], brain.SynapsePrefetch.none) + del circuit + synapses = [s for s in synapses] + for synapse in synapses: + assert(synapse.delay() < 10) + +if __name__ == '__main__': + unittest.main() + + diff --git a/tests/brain/synapses.cpp b/tests/brain/synapses.cpp index 667f9d5..42d5e08 100644 --- a/tests/brain/synapses.cpp +++ b/tests/brain/synapses.cpp @@ -3,29 +3,18 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/tests/compartmentReport.cpp b/tests/compartmentReport.cpp index 8e97b72..a4e879b 100644 --- a/tests/compartmentReport.cpp +++ b/tests/compartmentReport.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/data/h5/createNeuron.py b/tests/data/h5/createNeuron.py index 569403c..a021541 100644 --- a/tests/data/h5/createNeuron.py +++ b/tests/data/h5/createNeuron.py @@ -17,7 +17,7 @@ def createTBranchPoints(): # Creates a branch with a T shape - # The first section is a non-homogeneous distance sampling of 10 points + # The first section is a non-homogeneous distance sampling of 11 points # on a straight line from (0, 0, 0) to (0, 5, 5). first = [[0, i*i / 20.0, i*i / 20.0, 0.5 + i*i/1000.0] for i in range(11)] # The second section is an homogeneous sampling from (0, 5, 5) to (-2, 5, 5) @@ -35,7 +35,7 @@ def createTBranchStructure(firstPoint, nextSection, sectionType): [-.1, .0, .0, .1], [.0, -.1, .0, .1]]) structure = numpy.array([[0, 1, -1]]) -# Axon section +# Axon section to the bottom structure = numpy.append( structure, createTBranchStructure(points.shape[0], structure.shape[0], AXON), axis=0) diff --git a/tests/mesh.cpp b/tests/mesh.cpp index 97acd03..70f8a7a 100644 --- a/tests/mesh.cpp +++ b/tests/mesh.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/morphology.cpp b/tests/morphology.cpp index c2eefd4..e2a9f74 100644 --- a/tests/morphology.cpp +++ b/tests/morphology.cpp @@ -4,29 +4,18 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -46,12 +35,6 @@ typedef brion::Vector2i V2i; namespace { -const std::string TEST_MORPHOLOGY_FILENAME = - std::string( BRION_TESTDATA ) + "/h5/test_neuron.h5"; -const brion::URI TEST_MORPHOLOGY_URI = - brion::URI( "file://" + TEST_MORPHOLOGY_FILENAME ); - - // Ellipsis promotes enums to ints, so we need to use int. #pragma clang diagnostic ignored "-Wnon-pod-varargs" const int UNDEFINED = brion::SECTION_UNDEFINED; diff --git a/tests/paths.h.in b/tests/paths.h.in index 3dc6474..5ee1feb 100644 --- a/tests/paths.h.in +++ b/tests/paths.h.in @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #ifndef BRION_TEST_PATHS diff --git a/tests/spikeReport.cpp b/tests/spikeReport.cpp index 7769f0b..255238d 100644 --- a/tests/spikeReport.cpp +++ b/tests/spikeReport.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/spikeReportStreaming.cpp b/tests/spikeReportStreaming.cpp index d2b26c1..1b21142 100644 --- a/tests/spikeReportStreaming.cpp +++ b/tests/spikeReportStreaming.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include "../brion/plugin/spikeReportSimpleStreamer.h" diff --git a/tests/synapse.cpp b/tests/synapse.cpp index 76ac9d5..58e4b38 100644 --- a/tests/synapse.cpp +++ b/tests/synapse.cpp @@ -5,29 +5,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/synapseSummary.cpp b/tests/synapseSummary.cpp index 8f26628..91df2a6 100644 --- a/tests/synapseSummary.cpp +++ b/tests/synapseSummary.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/target.cpp b/tests/target.cpp index a85af2c..6c514c7 100644 --- a/tests/target.cpp +++ b/tests/target.cpp @@ -4,29 +4,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include diff --git a/tests/threadHDF5.cpp b/tests/threadHDF5.cpp index d9d6fd2..f82217e 100644 --- a/tests/threadHDF5.cpp +++ b/tests/threadHDF5.cpp @@ -3,29 +3,19 @@ * * This file is part of Brion * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of Eyescale Software GmbH nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * This file is part of Brion */ #include