From efe524c30a0e2cb9b4e0d9d346db2b950aad1d81 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 13 Feb 2018 15:59:05 +0100 Subject: [PATCH 01/82] Modularize python bindings --- CMakeLists.txt | 2 + cmake/python_module.cmake | 93 +++++++++++++++++++ demo/brunel_example/CMakeLists.txt | 4 +- demo/brunel_example/nest_python_vis.py | 6 +- demo/nest_python_vis/CMakeLists.txt | 4 +- demo/nest_python_vis/nest_python_vis.py | 8 +- pyniv/CMakeLists.txt | 29 +----- pyniv/src/CMakeLists.txt | 43 +++++++++ pyniv/src/__init__.py | 26 ++++++ pyniv/src/conduit/CMakeLists.txt | 34 +++++++ pyniv/src/conduit/__init__.py | 22 +++++ pyniv/src/conduit/conduit.cpp | 34 +++++++ .../{conduit_node.cpp => conduit/node.cpp} | 2 +- pyniv/src/consumer/CMakeLists.txt | 36 +++++++ pyniv/src/consumer/__init__.py | 22 +++++ pyniv/src/consumer/backend.cpp | 2 +- pyniv/src/consumer/consumer.cpp | 38 ++++++++ pyniv/src/consumer/device.cpp | 8 +- pyniv/src/consumer/multimeter.cpp | 2 +- pyniv/src/consumer/receiver.cpp | 2 +- pyniv/src/pyniv.cpp | 21 +---- pyniv/src/testing/CMakeLists.txt | 37 ++++++++ pyniv/src/testing/__init__.py | 22 +++++ pyniv/src/{ => testing}/nest_test_data.cpp | 35 ++++--- pyniv/src/testing/testing.cpp | 30 ++++++ pyniv/tests/CMakeLists.txt | 2 +- pyniv/tests/src/consumer/test_backend.py | 10 +- pyniv/tests/src/consumer/test_device.py | 8 +- pyniv/tests/src/consumer/test_integration.py | 14 +-- pyniv/tests/src/consumer/test_multimeter.py | 14 +-- pyniv/tests/src/consumer/test_receiver.py | 13 +-- pyniv/tests/src/test_conduit_node.py | 2 +- 32 files changed, 515 insertions(+), 110 deletions(-) create mode 100644 cmake/python_module.cmake create mode 100644 pyniv/src/CMakeLists.txt create mode 100644 pyniv/src/__init__.py create mode 100644 pyniv/src/conduit/CMakeLists.txt create mode 100644 pyniv/src/conduit/__init__.py create mode 100644 pyniv/src/conduit/conduit.cpp rename pyniv/src/{conduit_node.cpp => conduit/node.cpp} (97%) create mode 100644 pyniv/src/consumer/CMakeLists.txt create mode 100644 pyniv/src/consumer/__init__.py create mode 100644 pyniv/src/consumer/consumer.cpp create mode 100644 pyniv/src/testing/CMakeLists.txt create mode 100644 pyniv/src/testing/__init__.py rename pyniv/src/{ => testing}/nest_test_data.cpp (71%) create mode 100644 pyniv/src/testing/testing.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5911e8c..42ceab6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,8 @@ include(GenerateExportHeader) include(py.test) +include(python_module) + include(WarningLevels) find_package(Conduit) diff --git a/cmake/python_module.cmake b/cmake/python_module.cmake new file mode 100644 index 0000000..5ac32c1 --- /dev/null +++ b/cmake/python_module.cmake @@ -0,0 +1,93 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +function(ADD_PYTHON_MODULE) + # parse arguments + set(options ) + set(oneValueArgs NAME OUTPUT_DIRECTORY) + set(multiValueArgs + SOURCES HEADERS PYTHON_SOURCES INCLUDE_DIRECTORIES LINK_LIBRARIES) + cmake_parse_arguments(ADD_PYTHON_MODULE + "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + python_add_module(${ADD_PYTHON_MODULE_NAME} + ${ADD_PYTHON_MODULE_SOURCES} + ${ADD_PYTHON_MODULE_HEADERS} + ) + + target_include_directories(${ADD_PYTHON_MODULE_NAME} + PRIVATE ${Boost_INCLUDE_DIRS} + PRIVATE ${PYTHON_INCLUDE_DIRS} + ${ADD_PYTHON_MODULE_INCLUDE_DIRECTORIES} + ) + + target_link_libraries(${ADD_PYTHON_MODULE_NAME} + ${Boost_LIBRARIES} + ${PYTHON_LIBRARIES} + ${ADD_PYTHON_MODULE_LINK_LIBRARIES} + ) + + set_warning_levels_RWTH(${ADD_PYTHON_MODULE_NAME} + SUPPRESS_WARNINGS_HEADER ${CMAKE_CURRENT_BINARY_DIR}/include/pyniv/suppress_warnings.hpp + ) + + add_test_cpplint(NAME "${ADD_PYTHON_MODULE_NAME}--cpplint" + ${ADD_PYTHON_MODULE_SOURCES} + ${ADD_PYTHON_MODULE_HEADERS} + ) + + add_custom_command(TARGET ${ADD_PYTHON_MODULE_NAME} + POST_BUILD + #OUTPUT ${ADD_PYTHON_MODULE_OUTPUT_DIRECTORY}/$ + #DEPENDS $ + COMMAND ${CMAKE_COMMAND} + -E copy_if_different + $ + ${ADD_PYTHON_MODULE_OUTPUT_DIRECTORY}/$ + ) + + foreach (ADD_PYTHON_MODULE_PYTHON_INPUT ${ADD_PYTHON_MODULE_PYTHON_SOURCES}) + get_filename_component(ADD_PYTHON_MODULE_PYTHON_INPUT_NAME + ${ADD_PYTHON_MODULE_PYTHON_INPUT} + NAME) + set(ADD_PYTHON_MODULE_PYTHON_OUTPUT + "${ADD_PYTHON_MODULE_OUTPUT_DIRECTORY}/${ADD_PYTHON_MODULE_PYTHON_INPUT_NAME}" + ) + set(ADD_PYTHON_MODULE_CUSTOM_TARGET_NAME + "${ADD_PYTHON_MODULE_NAME}_COPY_${ADD_PYTHON_MODULE_PYTHON_INPUT_NAME}" + ) + add_custom_command( + OUTPUT ${ADD_PYTHON_MODULE_PYTHON_OUTPUT} + DEPENDS ${ADD_PYTHON_MODULE_PYTHON_INPUT} + COMMAND ${CMAKE_COMMAND} + -E copy_if_different + ${ADD_PYTHON_MODULE_PYTHON_INPUT} + ${ADD_PYTHON_MODULE_PYTHON_OUTPUT} + ) + add_custom_target(${ADD_PYTHON_MODULE_CUSTOM_TARGET_NAME} + DEPENDS + ${ADD_PYTHON_MODULE_PYTHON_OUTPUT} + ) + add_dependencies(${ADD_PYTHON_MODULE_NAME} + ${ADD_PYTHON_MODULE_CUSTOM_TARGET_NAME} + ) + endforeach(ADD_PYTHON_MODULE_PYTHON_INPUT) +endfunction() diff --git a/demo/brunel_example/CMakeLists.txt b/demo/brunel_example/CMakeLists.txt index 0a78ca1..9d45c1e 100644 --- a/demo/brunel_example/CMakeLists.txt +++ b/demo/brunel_example/CMakeLists.txt @@ -25,7 +25,7 @@ set(NEST_SIM_SOURCE nest_sim.py) if(NOT CMAKE_MAKE_PROGRAM STREQUAL "/usr/bin/xcodebuild") file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_vis.sh - CONTENT "PYTHONPATH=$:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_PYTHON_VIS_SOURCE}" + CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_PYTHON_VIS_SOURCE}" ) set(NEST_DIR @@ -33,7 +33,7 @@ set(NEST_DIR file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_sim.sh CONTENT "source ${NEST_DIR}/bin/nest_vars.sh -PYTHONPATH=$:$PYTHONPATH ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_SIM_SOURCE}" +PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$PYTHONPATH ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_SIM_SOURCE}" ) endif() diff --git a/demo/brunel_example/nest_python_vis.py b/demo/brunel_example/nest_python_vis.py index 41e19ea..7602051 100644 --- a/demo/brunel_example/nest_python_vis.py +++ b/demo/brunel_example/nest_python_vis.py @@ -38,12 +38,12 @@ def __init__(self): self.SetupUpdateTimer() def SetupStreaming(self): - self.receiver = pyniv.ConsumerReceiver() + self.receiver = pyniv.consumer.Receiver() - self.multimeter = pyniv.ConsumerMultimeter("recordingNode51") + self.multimeter = pyniv.consumer.Multimeter("recordingNode51") self.multimeter.SetAttribute("V_m") - self.backend = pyniv.ConsumerBackend(); + self.backend = pyniv.consumer.Backend(); self.backend.Connect(self.receiver); self.backend.Connect(self.multimeter); diff --git a/demo/nest_python_vis/CMakeLists.txt b/demo/nest_python_vis/CMakeLists.txt index 0a78ca1..9d45c1e 100644 --- a/demo/nest_python_vis/CMakeLists.txt +++ b/demo/nest_python_vis/CMakeLists.txt @@ -25,7 +25,7 @@ set(NEST_SIM_SOURCE nest_sim.py) if(NOT CMAKE_MAKE_PROGRAM STREQUAL "/usr/bin/xcodebuild") file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_vis.sh - CONTENT "PYTHONPATH=$:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_PYTHON_VIS_SOURCE}" + CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_PYTHON_VIS_SOURCE}" ) set(NEST_DIR @@ -33,7 +33,7 @@ set(NEST_DIR file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_sim.sh CONTENT "source ${NEST_DIR}/bin/nest_vars.sh -PYTHONPATH=$:$PYTHONPATH ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_SIM_SOURCE}" +PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$PYTHONPATH ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_SIM_SOURCE}" ) endif() diff --git a/demo/nest_python_vis/nest_python_vis.py b/demo/nest_python_vis/nest_python_vis.py index 97141a9..4d48750 100644 --- a/demo/nest_python_vis/nest_python_vis.py +++ b/demo/nest_python_vis/nest_python_vis.py @@ -38,15 +38,15 @@ def __init__(self): self.SetupUpdateTimer() def SetupStreaming(self): - self.receiver = pyniv.ConsumerReceiver() + self.receiver = pyniv.consumer.Receiver() - self.multimeter_a = pyniv.ConsumerMultimeter("multimeter A") + self.multimeter_a = pyniv.consumer.Multimeter("multimeter A") self.multimeter_a.SetAttribute("V_m") - self.multimeter_b = pyniv.ConsumerMultimeter("multimeter B") + self.multimeter_b = pyniv.consumer.Multimeter("multimeter B") self.multimeter_b.SetAttribute("V_m") - self.backend = pyniv.ConsumerBackend(); + self.backend = pyniv.consumer.Backend(); self.backend.Connect(self.receiver); self.backend.Connect(self.multimeter_a); self.backend.Connect(self.multimeter_b); diff --git a/pyniv/CMakeLists.txt b/pyniv/CMakeLists.txt index 98a808b..690d8b3 100644 --- a/pyniv/CMakeLists.txt +++ b/pyniv/CMakeLists.txt @@ -19,33 +19,6 @@ # limitations under the License. #------------------------------------------------------------------------------- - - -file(GLOB PYNIV_SOURCES src/*.cpp src/**/*.cpp) -file(GLOB PYNIV_HEADERS src/*.hpp src/**/*.hpp) - -python_add_module(pyniv - ${PYNIV_SOURCES} - ${PYNIV_HEADERS} -) -target_link_libraries(pyniv niv) - -target_include_directories(pyniv - PRIVATE ${Boost_INCLUDE_DIRS} - PRIVATE ${PYTHON_INCLUDE_DIRS} - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src - ) -target_link_libraries(pyniv - ${Boost_LIBRARIES} - ${PYTHON_LIBRARIES} - ) - -set_warning_levels_RWTH(pyniv - SUPPRESS_WARNINGS_HEADER ${CMAKE_CURRENT_BINARY_DIR}/include/pyniv/suppress_warnings.hpp -) - -add_test_cpplint(NAME "pyniv--cpplint" - ${PYNIV_SOURCES} -) +add_subdirectory(src) add_subdirectory(tests) diff --git a/pyniv/src/CMakeLists.txt b/pyniv/src/CMakeLists.txt new file mode 100644 index 0000000..64a5d69 --- /dev/null +++ b/pyniv/src/CMakeLists.txt @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +file(GLOB SOURCES *.cpp) +file(GLOB HEADERS *.hpp) +file(GLOB PYTHON_SOURCES *.py) + +set(PYNIV_OUTPUT_DIR + ${CMAKE_CURRENT_BINARY_DIR}/../pyniv + CACHE PATH "Output path for pyniv python module" + ) + +add_python_module( + NAME _pyniv + SOURCES ${SOURCES} + HEADERS ${HEADERS} + PYTHON_SOURCES ${PYTHON_SOURCES} + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} + LINK_LIBRARIES niv + OUTPUT_DIRECTORY ${PYNIV_OUTPUT_DIR} + ) + +add_subdirectory(conduit) +add_subdirectory(consumer) +add_subdirectory(testing) diff --git a/pyniv/src/__init__.py b/pyniv/src/__init__.py new file mode 100644 index 0000000..ce503ef --- /dev/null +++ b/pyniv/src/__init__.py @@ -0,0 +1,26 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +from _pyniv import * + +import conduit +import consumer +import testing diff --git a/pyniv/src/conduit/CMakeLists.txt b/pyniv/src/conduit/CMakeLists.txt new file mode 100644 index 0000000..5cdf9d0 --- /dev/null +++ b/pyniv/src/conduit/CMakeLists.txt @@ -0,0 +1,34 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +file(GLOB SOURCES *.cpp) +file(GLOB HEADERS *.hpp) +file(GLOB PYTHON_SOURCES *.py) + +add_python_module( + NAME _conduit + SOURCES ${SOURCES} + HEADERS ${HEADERS} + PYTHON_SOURCES ${PYTHON_SOURCES} + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/.. + LINK_LIBRARIES conduit + OUTPUT_DIRECTORY ${PYNIV_OUTPUT_DIR}/conduit + ) diff --git a/pyniv/src/conduit/__init__.py b/pyniv/src/conduit/__init__.py new file mode 100644 index 0000000..90d9a29 --- /dev/null +++ b/pyniv/src/conduit/__init__.py @@ -0,0 +1,22 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +from _conduit import * diff --git a/pyniv/src/conduit/conduit.cpp b/pyniv/src/conduit/conduit.cpp new file mode 100644 index 0000000..5454160 --- /dev/null +++ b/pyniv/src/conduit/conduit.cpp @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "pyniv.hpp" + +SUPPRESS_WARNINGS_BEGIN +#include "boost/python/numpy.hpp" +SUPPRESS_WARNINGS_END + +#include "conduit/conduit_node.hpp" + +namespace pyniv { + +BOOST_PYTHON_MODULE(_conduit) { pyniv::expose(); } + +} // namespace pyniv diff --git a/pyniv/src/conduit_node.cpp b/pyniv/src/conduit/node.cpp similarity index 97% rename from pyniv/src/conduit_node.cpp rename to pyniv/src/conduit/node.cpp index 1ff69b3..1a6dcde 100644 --- a/pyniv/src/conduit_node.cpp +++ b/pyniv/src/conduit/node.cpp @@ -38,7 +38,7 @@ void SetDoubleAtPath(const conduit::Node& node, const std::string& path, template <> void expose() { - class_("ConduitNode") + class_("Node") .def("GetDoubleAtPath", &pyniv::GetDoubleAtPath) .def("SetDoubleAtPath", &pyniv::SetDoubleAtPath); } diff --git a/pyniv/src/consumer/CMakeLists.txt b/pyniv/src/consumer/CMakeLists.txt new file mode 100644 index 0000000..152ab6b --- /dev/null +++ b/pyniv/src/consumer/CMakeLists.txt @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + + +file(GLOB SOURCES *.cpp) +file(GLOB HEADERS *.hpp) +file(GLOB PYTHON_SOURCES *.py) + +add_python_module( + NAME _consumer + SOURCES ${SOURCES} + HEADERS ${HEADERS} + PYTHON_SOURCES ${PYTHON_SOURCES} + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/.. + LINK_LIBRARIES conduit niv + OUTPUT_DIRECTORY ${PYNIV_OUTPUT_DIR}/consumer + ) + diff --git a/pyniv/src/consumer/__init__.py b/pyniv/src/consumer/__init__.py new file mode 100644 index 0000000..5f5d103 --- /dev/null +++ b/pyniv/src/consumer/__init__.py @@ -0,0 +1,22 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +from _consumer import * diff --git a/pyniv/src/consumer/backend.cpp b/pyniv/src/consumer/backend.cpp index b4b5cee..0a539fd 100644 --- a/pyniv/src/consumer/backend.cpp +++ b/pyniv/src/consumer/backend.cpp @@ -28,7 +28,7 @@ namespace pyniv { template <> void expose() { - class_("ConsumerBackend") + class_("Backend") .def("Connect", static_cast(&niv::consumer::Backend::Connect)) diff --git a/pyniv/src/consumer/consumer.cpp b/pyniv/src/consumer/consumer.cpp new file mode 100644 index 0000000..01149e5 --- /dev/null +++ b/pyniv/src/consumer/consumer.cpp @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "pyniv.hpp" + +#include "niv/consumer/backend.hpp" +#include "niv/consumer/device.hpp" +#include "niv/consumer/multimeter.hpp" +#include "niv/consumer/receiver.hpp" + +namespace pyniv { + +BOOST_PYTHON_MODULE(_consumer) { + pyniv::expose(); + pyniv::expose(); + pyniv::expose(); + pyniv::expose(); +} + +} // namespace pyniv diff --git a/pyniv/src/consumer/device.cpp b/pyniv/src/consumer/device.cpp index 2c3e59b..56cf1c6 100644 --- a/pyniv/src/consumer/device.cpp +++ b/pyniv/src/consumer/device.cpp @@ -45,16 +45,20 @@ struct DeviceWrap : niv::consumer::Device, wrapper { boost::python::make_tuple(timesteps.size()), boost::python::make_tuple(sizeof(double)), boost::python::object()); } + + static void SetNodePointer(niv::consumer::Device* device, PyObject* node) { + device->SetNode(boost::python::extract(node)); + } }; } // namespace consumer template <> void expose() { - class_("ConsumerDevice", + class_("Device", init()) .def("GetTimesteps", &pyniv::consumer::DeviceWrap::GetTimesteps) - .def("SetNode", &niv::consumer::Device::SetNode) + .def("SetNode", &pyniv::consumer::DeviceWrap::SetNodePointer) .def("SetTime", &niv::consumer::Device::SetTime) .def("Update", pure_virtual(&niv::consumer::Device::Update)); } diff --git a/pyniv/src/consumer/multimeter.cpp b/pyniv/src/consumer/multimeter.cpp index b7e9a71..0ff7865 100644 --- a/pyniv/src/consumer/multimeter.cpp +++ b/pyniv/src/consumer/multimeter.cpp @@ -52,7 +52,7 @@ boost::python::numpy::ndarray GetValues( template <> void expose() { class_>( - "ConsumerMultimeter", init()) + "Multimeter", init()) .def("GetValues", &pyniv::consumer::GetValues) .def("SetAttribute", &niv::consumer::Multimeter::SetAttribute) .def("Update", &niv::consumer::Multimeter::Update); diff --git a/pyniv/src/consumer/receiver.cpp b/pyniv/src/consumer/receiver.cpp index 67614f7..4997064 100644 --- a/pyniv/src/consumer/receiver.cpp +++ b/pyniv/src/consumer/receiver.cpp @@ -42,7 +42,7 @@ struct ReceiverWrap : niv::consumer::Receiver, template <> void expose() { - class_("ConsumerReceiver") + class_("Receiver") .def("Receive", &pyniv::consumer::ReceiverWrap::Receive) .def("SetNode", &niv::consumer::Receiver::SetNode); } diff --git a/pyniv/src/pyniv.cpp b/pyniv/src/pyniv.cpp index 185e507..3417358 100644 --- a/pyniv/src/pyniv.cpp +++ b/pyniv/src/pyniv.cpp @@ -25,24 +25,13 @@ SUPPRESS_WARNINGS_BEGIN #include "boost/python/numpy.hpp" SUPPRESS_WARNINGS_END -#include "conduit/conduit_node.hpp" - -#include "niv/consumer/backend.hpp" -#include "niv/consumer/multimeter.hpp" -#include "niv/consumer/receiver.hpp" -#include "niv/nest_test_data.hpp" #include "niv/niv.hpp" -BOOST_PYTHON_MODULE(pyniv) { +namespace pyniv { + +BOOST_PYTHON_MODULE(_pyniv) { boost::python::numpy::initialize(); def("Greet", niv::Greet); - - pyniv::expose(); - - pyniv::expose(); - pyniv::expose(); - pyniv::expose(); - pyniv::expose(); - - pyniv::expose(); } + +} // namespace pyniv diff --git a/pyniv/src/testing/CMakeLists.txt b/pyniv/src/testing/CMakeLists.txt new file mode 100644 index 0000000..f2cd268 --- /dev/null +++ b/pyniv/src/testing/CMakeLists.txt @@ -0,0 +1,37 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + + +file(GLOB SOURCES *.cpp) +file(GLOB HEADERS *.hpp) +file(GLOB PYTHON_SOURCES *.py) + +add_python_module( + NAME _testing + SOURCES ${SOURCES} + HEADERS ${HEADERS} + PYTHON_SOURCES ${PYTHON_SOURCES} + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/.. + LINK_LIBRARIES conduit niv + OUTPUT_DIRECTORY ${PYNIV_OUTPUT_DIR}/testing + ) +message ("PYNIV_OUTPUT_DIR ${PYNIV_OUTPUT_DIR}") + diff --git a/pyniv/src/testing/__init__.py b/pyniv/src/testing/__init__.py new file mode 100644 index 0000000..47b82d6 --- /dev/null +++ b/pyniv/src/testing/__init__.py @@ -0,0 +1,22 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +from _testing import * diff --git a/pyniv/src/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp similarity index 71% rename from pyniv/src/nest_test_data.cpp rename to pyniv/src/testing/nest_test_data.cpp index 30a63ac..08783a2 100644 --- a/pyniv/src/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -74,24 +74,23 @@ boost::python::numpy::ndarray AnotherAttributesValues() { template <> void expose() { - def("TestingAnyAttribute", &niv::testing::AnyAttribute); - def("TestingAnotherAttribute", &niv::testing::AnotherAttribute); - def("TestingThirdAttribute", &niv::testing::ThirdAttribute); - def("TestingAnyTime", &niv::testing::AnyTime); - def("TestingAnyAttributesValues", &pyniv::testing::AnyAttributesValues); - def("TestingAnotherAttributesValues", - &pyniv::testing::AnotherAttributesValues); - def("TestingThirdAttributesValues", &niv::testing::ThirdAttributesValues); - def("TestingAnyValueNames", &pyniv::testing::AnyValueNames); - def("TestingAnyMultimeterName", &niv::testing::AnyMultimeterName); - def("TestingAnyNestData", &niv::testing::AnyNestData); - def("TestingSend", &niv::testing::Send); - def("TestingAnyNode", &niv::testing::AnyNode); - def("TestingAnotherNode", &niv::testing::AnotherNode); - def("TestingUpdate", &niv::testing::Update); - def("TestingUpdatedNode", &niv::testing::UpdatedNode); - def("TestingADifferentNode", &niv::testing::ADifferentNode); - def("TestingEqual", &pyniv::testing::Equal); + def("AnyAttribute", &niv::testing::AnyAttribute); + def("AnotherAttribute", &niv::testing::AnotherAttribute); + def("ThirdAttribute", &niv::testing::ThirdAttribute); + def("AnyTime", &niv::testing::AnyTime); + def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues); + def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); + def("ThirdAttributesValues", &niv::testing::ThirdAttributesValues); + def("AnyValueNames", &pyniv::testing::AnyValueNames); + def("AnyMultimeterName", &niv::testing::AnyMultimeterName); + def("AnyNestData", &niv::testing::AnyNestData); + def("Send", &niv::testing::Send); + def("AnyNode", &niv::testing::AnyNode); + def("AnotherNode", &niv::testing::AnotherNode); + def("Update", &niv::testing::Update); + def("UpdatedNode", &niv::testing::UpdatedNode); + def("ADifferentNode", &niv::testing::ADifferentNode); + def("Equal", &pyniv::testing::Equal); } } // namespace pyniv diff --git a/pyniv/src/testing/testing.cpp b/pyniv/src/testing/testing.cpp new file mode 100644 index 0000000..8066e7d --- /dev/null +++ b/pyniv/src/testing/testing.cpp @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "pyniv.hpp" + +#include "niv/nest_test_data.hpp" + +namespace pyniv { + +BOOST_PYTHON_MODULE(_testing) { pyniv::expose(); } + +} // namespace pyniv diff --git a/pyniv/tests/CMakeLists.txt b/pyniv/tests/CMakeLists.txt index 1575632..2d56229 100644 --- a/pyniv/tests/CMakeLists.txt +++ b/pyniv/tests/CMakeLists.txt @@ -25,5 +25,5 @@ file(GLOB PYNIV_TEST_SOURCES src/*.py src/**/*.py) add_test_py_test(NAME test_pyniv ${CMAKE_CURRENT_SOURCE_DIR} - PYTHONPATH "$:$" + PYTHONPATH "${PYNIV_OUTPUT_DIR}/..:$" ) diff --git a/pyniv/tests/src/consumer/test_backend.py b/pyniv/tests/src/consumer/test_backend.py index 36056f9..025bf25 100644 --- a/pyniv/tests/src/consumer/test_backend.py +++ b/pyniv/tests/src/consumer/test_backend.py @@ -21,24 +21,24 @@ import pyniv -class Receiver(pyniv.ConsumerReceiver): +class Receiver(pyniv.consumer.Receiver): def __init__(self): - pyniv.ConsumerReceiver.__init__(self) + pyniv.consumer.Receiver.__init__(self) self.count_receives = 0; def Receive(self): self.count_receives += 1; -class Device(pyniv.ConsumerDevice): +class Device(pyniv.consumer.Device): def __init__(self): - pyniv.ConsumerDevice.__init__(self, "any_name") + pyniv.consumer.Device.__init__(self, "any_name") self.count_updates = 0; def Update(self): self.count_updates += 1; def test_pyniv_consumer_backend(): - backend = pyniv.ConsumerBackend() + backend = pyniv.consumer.Backend() receiver = Receiver() backend.Connect(receiver) diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index b904089..bf045b7 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -21,13 +21,13 @@ import pyniv -class Device(pyniv.ConsumerDevice): +class Device(pyniv.consumer.Device): def __init__(self, name): - pyniv.ConsumerDevice.__init__(self, name) + pyniv.consumer.Device.__init__(self, name) def test_consumer_device_lists_timesteps(): - any_data = pyniv.TestingAnyNestData() - device = Device(pyniv.TestingAnyMultimeterName()) + any_data = pyniv.testing.AnyNestData() + device = Device(pyniv.testing.AnyMultimeterName()) device.SetNode(any_data) timesteps = device.GetTimesteps() assert (timesteps == [0.0]).all() diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index 9e2996e..e9d724c 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -22,21 +22,21 @@ import pyniv def test_integration_consumer(): - backend = pyniv.ConsumerBackend() + backend = pyniv.consumer.Backend() - receiver = pyniv.ConsumerReceiver() + receiver = pyniv.consumer.Receiver() backend.Connect(receiver) - multimeter = pyniv.ConsumerMultimeter(pyniv.TestingAnyMultimeterName()) - multimeter.SetAttribute(pyniv.TestingAnyValueNames(0)) + multimeter = pyniv.consumer.Multimeter(pyniv.testing.AnyMultimeterName()) + multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) backend.Connect(multimeter) - pyniv.TestingSend(pyniv.TestingAnyNestData()) + pyniv.testing.Send(pyniv.testing.AnyNestData()) backend.Receive() - multimeter.SetTime(pyniv.TestingAnyTime()) + multimeter.SetTime(pyniv.testing.AnyTime()) multimeter.Update() values = multimeter.GetValues() - assert (values == pyniv.TestingAnyAttributesValues()).all() + assert (values == pyniv.testing.AnyAttributesValues()).all() diff --git a/pyniv/tests/src/consumer/test_multimeter.py b/pyniv/tests/src/consumer/test_multimeter.py index 69c85dc..84e3d2e 100644 --- a/pyniv/tests/src/consumer/test_multimeter.py +++ b/pyniv/tests/src/consumer/test_multimeter.py @@ -22,18 +22,18 @@ import pyniv def test_multimeter_provides_access_to_data_stored_in_a_conduit_node(): - nest_data = pyniv.TestingAnyNestData() - multimeter = pyniv.ConsumerMultimeter(pyniv.TestingAnyMultimeterName()) + nest_data = pyniv.testing.AnyNestData() + multimeter = pyniv.consumer.Multimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetNode(nest_data) - multimeter.SetTime(pyniv.TestingAnyTime()) + multimeter.SetTime(pyniv.testing.AnyTime()) - multimeter.SetAttribute(pyniv.TestingAnyValueNames(0)) + multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) multimeter.Update() result = multimeter.GetValues() - assert (result == pyniv.TestingAnyAttributesValues()).all() + assert (result == pyniv.testing.AnyAttributesValues()).all() - multimeter.SetAttribute(pyniv.TestingAnyValueNames(1)) + multimeter.SetAttribute(pyniv.testing.AnyValueNames(1)) multimeter.Update() result = multimeter.GetValues() - assert (result == pyniv.TestingAnotherAttributesValues()).all() + assert (result == pyniv.testing.AnotherAttributesValues()).all() diff --git a/pyniv/tests/src/consumer/test_receiver.py b/pyniv/tests/src/consumer/test_receiver.py index e210187..4945d36 100644 --- a/pyniv/tests/src/consumer/test_receiver.py +++ b/pyniv/tests/src/consumer/test_receiver.py @@ -22,15 +22,16 @@ import pyniv def test_receiver_aggregates_data(): - receiver = pyniv.ConsumerReceiver() - receiving_node = pyniv.ConduitNode() + receiver = pyniv.consumer.Receiver() + receiving_node = pyniv.conduit.Node() receiver.SetNode(receiving_node) - pyniv.TestingSend(pyniv.TestingAnyNode()) + pyniv.testing.Send(pyniv.testing.AnyNode()) receiver.Receive() - assert pyniv.TestingEqual(receiving_node, pyniv.TestingAnyNode()) + assert pyniv.testing.Equal(receiving_node, pyniv.testing.AnyNode()) - pyniv.TestingSend(pyniv.TestingUpdate()) + + pyniv.testing.Send(pyniv.testing.Update()) receiver.Receive() - assert pyniv.TestingEqual(receiving_node, pyniv.TestingUpdatedNode()) + assert pyniv.testing.Equal(receiving_node, pyniv.testing.UpdatedNode()) diff --git a/pyniv/tests/src/test_conduit_node.py b/pyniv/tests/src/test_conduit_node.py index 4fa0bea..af68fc8 100644 --- a/pyniv/tests/src/test_conduit_node.py +++ b/pyniv/tests/src/test_conduit_node.py @@ -25,6 +25,6 @@ def test_conduit_node(): any_path = "any/path" any_double = 42.0 - node = pyniv.ConduitNode() + node = pyniv.conduit.Node() node.SetDoubleAtPath(any_path, any_double) assert node.GetDoubleAtPath(any_path) == any_double From 08d1039b19cb998c88c11cad446bf0939002fdb1 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 13 Feb 2018 17:01:10 +0100 Subject: [PATCH 02/82] Add second time step to nest test data --- niv/include/niv/nest_test_data.hpp | 7 ++-- niv/src/nest_test_data.cpp | 30 ++++++++++++--- niv/tests/src/consumer/test_device.cpp | 39 +++++++++++++++++++- niv/tests/src/consumer/test_integration.cpp | 10 ++++- niv/tests/src/consumer/test_multimeter.cpp | 25 +++++++++++++ pyniv/src/testing/nest_test_data.cpp | 12 ++++-- pyniv/tests/src/consumer/test_device.py | 7 +++- pyniv/tests/src/consumer/test_integration.py | 10 ++++- 8 files changed, 120 insertions(+), 20 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index 6f72db5..eb78f93 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -47,10 +47,11 @@ std::string AnotherAttribute(); std::string ThirdAttribute(); double AnyTime(); +double AnotherTime(); -std::vector AnyAttributesValues(); -std::vector AnotherAttributesValues(); -std::vector ThirdAttributesValues(); +std::vector AnyAttributesValues(double time = 0.0); +std::vector AnotherAttributesValues(double time = 0.0); +std::vector ThirdAttributesValues(double time = 0.0); std::vector AnyValueNames(); diff --git a/niv/src/nest_test_data.cpp b/niv/src/nest_test_data.cpp index 9e35f5b..6faa8fe 100644 --- a/niv/src/nest_test_data.cpp +++ b/niv/src/nest_test_data.cpp @@ -34,15 +34,25 @@ std::string AnotherAttribute() { return "g_m"; } std::string ThirdAttribute() { return "g_i"; } double AnyTime() { return 0.0; } +double AnotherTime() { return 0.1; } -std::vector AnyAttributesValues() { - return std::vector{0.0, -0.1, 0.2, -0.3, 0.4, -0.5}; +std::vector AnyAttributesValues(double time) { + const double timed_offset = 1.1 * time + 2.2; + return std::vector{0.0 + timed_offset, -0.1 + timed_offset, + 0.2 + timed_offset, -0.3 + timed_offset, + 0.4 + timed_offset, -0.5 + timed_offset}; } -std::vector AnotherAttributesValues() { - return std::vector{1.0, -1.1, 1.2, -1.3, 1.4, -1.5}; +std::vector AnotherAttributesValues(double time) { + const double timed_offset = 2.2 * time + 3.3; + return std::vector{1.0 + timed_offset, -1.1 + timed_offset, + 1.2 + timed_offset, -1.3 + timed_offset, + 1.4 + timed_offset, -1.5 + timed_offset}; } -std::vector ThirdAttributesValues() { - return std::vector{-2.01, 3.12, -4.23, 5.34, -6.45, 7.56}; +std::vector ThirdAttributesValues(double time) { + const double timed_offset = 3.3 * time + 4.4; + return std::vector{-2.01 + timed_offset, 3.12 + timed_offset, + -4.23 + timed_offset, 5.34 + timed_offset, + -6.45 + timed_offset, 7.56 + timed_offset}; } std::vector AnyValueNames() { @@ -63,6 +73,14 @@ conduit::Node AnyNestData() { ThirdAttributesValues()[i]}); } + multimeter.SetRecordingTime(AnotherTime()); + for (auto i = 0u; i < AnyAttributesValues().size(); ++i) { + multimeter.Record( + i, std::vector{AnyAttributesValues(AnotherTime())[i], + AnotherAttributesValues(AnotherTime())[i], + ThirdAttributesValues(AnotherTime())[i]}); + } + return node; } diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index e25ef2b..b41e745 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -44,6 +44,39 @@ class Device : public niv::consumer::Device { } // namespace +namespace Catch { +namespace Matchers { +namespace Vector { +template +struct EqualsApproxMatcher : MatcherBase, std::vector > { + explicit EqualsApproxMatcher(std::vector const& comparator) + : comparator_(comparator) {} + + bool match(std::vector const& v) const CATCH_OVERRIDE { + // !TBD: This currently works if all elements can be compared using != + // - a more general approach would be via a compare template that defaults + // to using !=. but could be specialised for, e.g. std::vector etc + // - then just call that directly + if (comparator_.size() != v.size()) return false; + for (size_t i = 0; i < v.size(); ++i) + if (Approx(comparator_[i]) != v[i]) return false; + return true; + } + virtual std::string describe() const CATCH_OVERRIDE { + return "Equals: " + Catch::toString(comparator_); + } + std::vector const& comparator_; +}; +} // namespace Vector + +template +Vector::EqualsApproxMatcher EqualsApprox(std::vector const& comparator) { + return Vector::EqualsApproxMatcher(comparator); +} + +} // namespace Matchers +} // namespace Catch + SCENARIO("A consumer::Device can list its timesteps", "[niv][niv::consumer][niv::consumer::Device]") { GIVEN("A device accessing a node") { @@ -53,8 +86,10 @@ SCENARIO("A consumer::Device can list its timesteps", WHEN("The device is asked for the timesteps") { auto timesteps(device.GetTimesteps()); THEN("the list of timesteps is correct") { - REQUIRE_THAT(timesteps, - Catch::Matchers::Equals(std::vector{0})); + REQUIRE_THAT( + timesteps, + Catch::Matchers::EqualsApprox(std::vector{ + niv::testing::AnyTime(), niv::testing::AnotherTime()})); } } } diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index 8ff1d1a..c20a8bd 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -48,10 +48,16 @@ SCENARIO("Consumer integration", "[niv][integration]") { WHEN("the multimeter queries the data") { multimeter.SetTime(niv::testing::AnyTime()); multimeter.Update(); - std::vector values{multimeter.GetValues()}; + std::vector values_at_t0{multimeter.GetValues()}; + + multimeter.SetTime(niv::testing::AnotherTime()); + multimeter.Update(); + std::vector values_at_t1{multimeter.GetValues()}; THEN("the received values are correct") { - REQUIRE(values == niv::testing::AnyAttributesValues()); + REQUIRE(values_at_t0 == niv::testing::AnyAttributesValues()); + REQUIRE(values_at_t1 == niv::testing::AnyAttributesValues( + niv::testing::AnotherTime())); } } } diff --git a/niv/tests/src/consumer/test_multimeter.cpp b/niv/tests/src/consumer/test_multimeter.cpp index b3f4d2d..18ebe5c 100644 --- a/niv/tests/src/consumer/test_multimeter.cpp +++ b/niv/tests/src/consumer/test_multimeter.cpp @@ -56,6 +56,31 @@ SCENARIO("a Multimeter provides access to data stored in a conduit node", niv::testing::AnotherAttributesValues())); } } + + WHEN("The time step is set to another value") { + multimeter.SetTime(niv::testing::AnotherTime()); + WHEN("one attribute is queried") { + multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); + multimeter.Update(); + auto result = multimeter.GetValues(); + THEN("the result is correct") { + REQUIRE_THAT(result, Catch::Matchers::Equals( + niv::testing::AnyAttributesValues( + niv::testing::AnotherTime()))); + } + } + WHEN("another attribute is queried") { + multimeter.SetAttribute(niv::testing::AnyValueNames()[1]); + multimeter.Update(); + + auto result = multimeter.GetValues(); + THEN("the result is correct") { + REQUIRE_THAT(result, Catch::Matchers::Equals( + niv::testing::AnotherAttributesValues( + niv::testing::AnotherTime()))); + } + } + } } } } diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 08783a2..37ced33 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -52,8 +52,9 @@ std::string AnyValueNames(std::size_t index) { return niv::testing::AnyValueNames()[index]; } -boost::python::numpy::ndarray AnyAttributesValues() { - static std::vector values{niv::testing::AnyAttributesValues()}; +boost::python::numpy::ndarray AnyAttributesValues(double time = 0) { + static std::vector values; + values = std::vector{niv::testing::AnyAttributesValues(time)}; return boost::python::numpy::from_data( values.data(), boost::python::numpy::dtype::get_builtin(), @@ -70,6 +71,9 @@ boost::python::numpy::ndarray AnotherAttributesValues() { boost::python::make_tuple(sizeof(double)), boost::python::object()); } +BOOST_PYTHON_FUNCTION_OVERLOADS(AnyAttributesValuesOverloads, + AnyAttributesValues, 0, 1) + } // namespace testing template <> @@ -78,7 +82,9 @@ void expose() { def("AnotherAttribute", &niv::testing::AnotherAttribute); def("ThirdAttribute", &niv::testing::ThirdAttribute); def("AnyTime", &niv::testing::AnyTime); - def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues); + def("AnotherTime", &niv::testing::AnotherTime); + def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, + pyniv::testing::AnyAttributesValuesOverloads()); def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); def("ThirdAttributesValues", &niv::testing::ThirdAttributesValues); def("AnyValueNames", &pyniv::testing::AnyValueNames); diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index bf045b7..b02d773 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -19,6 +19,8 @@ # limitations under the License. #------------------------------------------------------------------------------- +import numpy as np + import pyniv class Device(pyniv.consumer.Device): @@ -30,5 +32,6 @@ def test_consumer_device_lists_timesteps(): device = Device(pyniv.testing.AnyMultimeterName()) device.SetNode(any_data) timesteps = device.GetTimesteps() - assert (timesteps == [0.0]).all() - assert len(timesteps) == 1 + assert len(timesteps) == 2 + expected_timesteps = [pyniv.testing.AnyTime(), pyniv.testing.AnotherTime()] + assert np.isclose(timesteps, expected_timesteps).all() diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index e9d724c..2350d98 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -19,6 +19,8 @@ # limitations under the License. #------------------------------------------------------------------------------- +import numpy as np + import pyniv def test_integration_consumer(): @@ -37,6 +39,10 @@ def test_integration_consumer(): multimeter.SetTime(pyniv.testing.AnyTime()) multimeter.Update() + values_at_t0 = multimeter.GetValues() + assert np.isclose(values_at_t0, pyniv.testing.AnyAttributesValues()).all() - values = multimeter.GetValues() - assert (values == pyniv.testing.AnyAttributesValues()).all() + multimeter.SetTime(pyniv.testing.AnotherTime()) + multimeter.Update() + values_at_t1 = multimeter.GetValues() + assert np.isclose(values_at_t1, pyniv.testing.AnyAttributesValues(pyniv.testing.AnotherTime())).all() From 558e36a8bbd08600559a3261aa16a3a2f7b9faae Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Feb 2018 07:56:07 +0100 Subject: [PATCH 03/82] Update .gitignore respecting improved emacs tooling --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d59e10a..58a8786 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build* BUILD* .dir-locals.el *.pyc +TAGS From c5f99cb02595fa348487f5258b783a867328438e Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Feb 2018 07:58:06 +0100 Subject: [PATCH 04/82] Add printing capabilities to brunel_example demo for debugging --- demo/brunel_example/CMakeLists.txt | 5 ++ demo/brunel_example/dump_to_stdout.py | 85 +++++++++++++++++++++++++++ niv/include/niv/consumer/device.hpp | 2 + niv/src/consumer/device.cpp | 6 ++ pyniv/src/consumer/multimeter.cpp | 3 +- 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 demo/brunel_example/dump_to_stdout.py diff --git a/demo/brunel_example/CMakeLists.txt b/demo/brunel_example/CMakeLists.txt index 9d45c1e..8e871c6 100644 --- a/demo/brunel_example/CMakeLists.txt +++ b/demo/brunel_example/CMakeLists.txt @@ -20,6 +20,7 @@ #------------------------------------------------------------------------------- set(NEST_PYTHON_VIS_SOURCE nest_python_vis.py) +set(NEST_PYTHON_DUMP_SOURCE dump_to_stdout.py) set(NEST_SIM_SOURCE nest_sim.py) if(NOT CMAKE_MAKE_PROGRAM STREQUAL "/usr/bin/xcodebuild") @@ -28,6 +29,10 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_vis.sh CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_PYTHON_VIS_SOURCE}" ) +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_dump.sh + CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${NEST_PYTHON_DUMP_SOURCE}" + ) + set(NEST_DIR CACHE PATH "Path to installed nest") file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_sim.sh diff --git a/demo/brunel_example/dump_to_stdout.py b/demo/brunel_example/dump_to_stdout.py new file mode 100644 index 0000000..2d4a4ae --- /dev/null +++ b/demo/brunel_example/dump_to_stdout.py @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +import sys + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns + +import pyniv + +from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout, QPushButton +from PyQt5.QtCore import QTimer + +class MainWindow: + def __init__(self): + self.SetupStreaming() + self.SetupWindow() + self.SetupUpdateTimer() + + def SetupStreaming(self): + self.receiver = pyniv.consumer.Receiver() + + self.multimeter = pyniv.consumer.Multimeter("recordingNode51") + self.multimeter.SetAttribute("V_m") + + self.backend = pyniv.consumer.Backend(); + self.backend.Connect(self.receiver); + self.backend.Connect(self.multimeter); + + def SetupWindow(self): + self.print_button = QPushButton("Print") + self.print_button.clicked.connect(self.PrintButtonClicked) + + def SetupUpdateTimer(self): + self.update_timer = QTimer() + self.update_timer.timeout.connect(self.Receive) + self.update_timer.start(1) + + def PrintButtonClicked(self): + self.multimeter.Print() + + def Show(self): + self.print_button.show() + button_geometry = self.print_button.geometry() + self.print_button.setGeometry( + 0, 0, + button_geometry.width(), + button_geometry.height()) + + def Receive(self): + self.backend.Receive() + + def Dump(self): + print("DUMP") + + +def main(argv): + app = QApplication(argv) + + w = MainWindow() + w.Show() + + return app.exec_() + +if __name__ == "__main__": + main(sys.argv) diff --git a/niv/include/niv/consumer/device.hpp b/niv/include/niv/consumer/device.hpp index 603e055..8fd4a46 100644 --- a/niv/include/niv/consumer/device.hpp +++ b/niv/include/niv/consumer/device.hpp @@ -48,6 +48,8 @@ class Device { void SetNode(const conduit::Node* node) { node_ = node; } + void Print() const; + protected: explicit Device(const std::string& name); diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index b9e4adc..7111ac3 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -67,6 +67,12 @@ void Device::SetTimestepNode() { } } +void Device::Print() const { + if (node_ != nullptr) { + node_->print(); + } +} + const conduit::Node* Device::GetTimestepNode() const { return timestep_node_; } } // namespace consumer diff --git a/pyniv/src/consumer/multimeter.cpp b/pyniv/src/consumer/multimeter.cpp index 0ff7865..39efc40 100644 --- a/pyniv/src/consumer/multimeter.cpp +++ b/pyniv/src/consumer/multimeter.cpp @@ -55,7 +55,8 @@ void expose() { "Multimeter", init()) .def("GetValues", &pyniv::consumer::GetValues) .def("SetAttribute", &niv::consumer::Multimeter::SetAttribute) - .def("Update", &niv::consumer::Multimeter::Update); + .def("Update", &niv::consumer::Multimeter::Update) + .def("Print", &niv::consumer::Multimeter::Print); } } // namespace pyniv From a2d760950a30fd7311e3c7b56c003d4fc0729481 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Feb 2018 08:12:53 +0100 Subject: [PATCH 05/82] Add conan library test verifying update behaviour into preallocated node --- niv/include/niv/nest_test_data.hpp | 1 + niv/src/nest_test_data.cpp | 11 ++++++ niv/tests/src/test_conduit.cpp | 57 +++++++++++++++++++++--------- 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index eb78f93..9614f38 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -68,6 +68,7 @@ conduit::Node AnotherNode(); conduit::Node Update(); conduit::Node UpdatedNode(); +conduit::Node UpdatedNodeAllZeros(); conduit::Node ADifferentNode(); diff --git a/niv/src/nest_test_data.cpp b/niv/src/nest_test_data.cpp index 6faa8fe..6594724 100644 --- a/niv/src/nest_test_data.cpp +++ b/niv/src/nest_test_data.cpp @@ -124,6 +124,17 @@ conduit::Node UpdatedNode() { return node; } +conduit::Node UpdatedNodeAllZeros() { + conduit::Node node; + node["A/B/C"] = 0.0; + node["A/B/D"] = 0.0; + node["A/E"] = 0.0; + node["A/B/F"] = 0.0; + node["A/B/G"] = 0.0; + node["A/H"] = 0.0; + return node; +} + conduit::Node ADifferentNode() { return Update(); } } // namespace testing diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index 97d4d1c..93ce99d 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -39,21 +39,6 @@ DataArray::~DataArray(); } // namespace conduit -SCENARIO("update inserts new nodes", "[conduit]") { - GIVEN("A conduit tree") { - conduit::Node a = niv::testing::AnyNode(); - - WHEN("A second node updates the tree") { - conduit::Node b = niv::testing::Update(); - a.update(b); - - THEN("the first node contains also the content of the second") { - REQUIRE_THAT(a, Equals(niv::testing::UpdatedNode())); - } - } - } -} - SCENARIO("conduit array leafs are compatible to std::vector", "[conduit]") { const std::string some_path{"root/inner/leaf"}; @@ -258,4 +243,44 @@ SCENARIO( } } -SCENARIO("node updates ", "[]") {} +SCENARIO("update inserts new nodes", "[conduit]") { + GIVEN("A conduit tree") { + conduit::Node a = niv::testing::AnyNode(); + + WHEN("A second node updates the tree") { + conduit::Node b = niv::testing::Update(); + a.update(b); + + THEN("the first node contains also the content of the second") { + REQUIRE_THAT(a, Equals(niv::testing::UpdatedNode())); + } + } + } +} + +SCENARIO("node updates into empty node with unexpected order", "[conduit]") { + GIVEN("an empty conduit node") { + conduit::Node target; + WHEN("the target node is updated with some data in unexpected order") { + target.update(niv::testing::Update()); + target.update(niv::testing::AnyNode()); + THEN("the node's layout is unexpected") { + REQUIRE_THAT(target, !Equals(niv::testing::UpdatedNode())); + } + } + } +} + +SCENARIO("node updates into pre-allocated node with unexpected order", + "[conduit]") { + GIVEN("an allocated conduit node") { + conduit::Node preallocated{niv::testing::UpdatedNodeAllZeros()}; + WHEN("the node is updated with some data in unexpected order") { + preallocated.update(niv::testing::Update()); + preallocated.update(niv::testing::AnyNode()); + THEN("the node's layout is as expected") { + REQUIRE_THAT(preallocated, Equals(niv::testing::UpdatedNode())); + } + } + } +} From 5a512866f98952ac4631cba7a060c2dcc1b5afdf Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Feb 2018 16:48:22 +0100 Subject: [PATCH 06/82] Add printing schema on multimeter print --- niv/src/consumer/device.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index 7111ac3..4713c7f 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -23,6 +23,8 @@ #include +#include + #include #include #include @@ -69,6 +71,9 @@ void Device::SetTimestepNode() { void Device::Print() const { if (node_ != nullptr) { + std::cout << "Schema" << std::endl; + std::cout << node_->schema().to_json() << std::endl; + std::cout << "Data" << std::endl; node_->print(); } } From dc5aa9c37418b170127bf254bdce53a3f731abda Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Feb 2018 16:49:10 +0100 Subject: [PATCH 07/82] Add tests to verify whether a `conduit::Node`'s data is contiguous --- niv/tests/src/exchange/test_node_storage.cpp | 14 ++++++++++++++ niv/tests/src/test_conduit.cpp | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/niv/tests/src/exchange/test_node_storage.cpp b/niv/tests/src/exchange/test_node_storage.cpp index 7d0a40d..9566230 100644 --- a/niv/tests/src/exchange/test_node_storage.cpp +++ b/niv/tests/src/exchange/test_node_storage.cpp @@ -67,6 +67,20 @@ SCENARIO("storing and reading a node", "[niv][niv::NodeStorage]") { } } +SCENARIO("storing and reading a node yields contifguous data", + "[niv][niv::NodeStorage]") { + GIVEN("a node storage") { + ::NodeStorage storage; + WHEN("a node is stored and retrieved") { + storage.Store(niv::testing::AnyNode()); + conduit::Node read{storage.Read()}; + THEN("the read node's data is contiguous") { + REQUIRE(read.is_contiguous()); + } + } + } +} + SCENARIO("a node can be stored and read multiple times", "[niv][niv::NodeStorage]") { GIVEN("a node stored and read back") { diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index 93ce99d..965b705 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -284,3 +284,21 @@ SCENARIO("node updates into pre-allocated node with unexpected order", } } } + +SCENARIO("conduit data layout", "[conduit]") { + GIVEN("a compacted conduit node") { + conduit::Node node; + niv::testing::AnyNode().compact_to(node); + + THEN("the node's data is contiguous") { REQUIRE(node.is_contiguous()); } + WHEN("the node's data is accessed via ptr") { + const double* data_ptr = + reinterpret_cast(node.contiguous_data_ptr()); + THEN("the leafs' data is accessible as an array") { + REQUIRE(data_ptr[0] == 3.1415); + REQUIRE(data_ptr[1] == 4.124); + REQUIRE(data_ptr[2] == 42.0); + } + } + } +} From 94b8c183283d07bea17a8193168cafe13b485e2b Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 20 Feb 2018 07:14:36 +0100 Subject: [PATCH 08/82] Add ArborMultimeter with just its factory method --- niv/include/niv/producer/arbor_multimeter.hpp | 57 +++++++++++++++++++ niv/src/producer/arbor_multimeter.cpp | 45 +++++++++++++++ .../src/producer/test_arbor_multimeter.cpp | 38 +++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 niv/include/niv/producer/arbor_multimeter.hpp create mode 100644 niv/src/producer/arbor_multimeter.cpp create mode 100644 niv/tests/src/producer/test_arbor_multimeter.cpp diff --git a/niv/include/niv/producer/arbor_multimeter.hpp b/niv/include/niv/producer/arbor_multimeter.hpp new file mode 100644 index 0000000..754056b --- /dev/null +++ b/niv/include/niv/producer/arbor_multimeter.hpp @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_INCLUDE_NIV_PRODUCER_ARBOR_MULTIMETER_HPP_ +#define NIV_INCLUDE_NIV_PRODUCER_ARBOR_MULTIMETER_HPP_ + +#include +#include +#include + +#include "niv/producer/device.hpp" + +namespace niv { +namespace producer { + +class ArborMultimeter final : public Device { + public: + ArborMultimeter(const std::string& name, + const std::vector& value_names, + conduit::Node* node); + ArborMultimeter(const ArborMultimeter&) = default; + ArborMultimeter(ArborMultimeter&&) = default; + ~ArborMultimeter() = default; + + ArborMultimeter& operator=(const ArborMultimeter&) = default; + ArborMultimeter& operator=(ArborMultimeter&&) = default; + + static std::unique_ptr New( + const std::string& name, const std::vector& value_names, + conduit::Node* node); + + private: + std::vector value_names_; +}; + +} // namespace producer +} // namespace niv + +#endif // NIV_INCLUDE_NIV_PRODUCER_ARBOR_MULTIMETER_HPP_ diff --git a/niv/src/producer/arbor_multimeter.cpp b/niv/src/producer/arbor_multimeter.cpp new file mode 100644 index 0000000..0fe714c --- /dev/null +++ b/niv/src/producer/arbor_multimeter.cpp @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include +#include +#include + +#include "conduit/conduit_node.hpp" + +#include "niv/producer/arbor_multimeter.hpp" + +namespace niv { +namespace producer { + +ArborMultimeter::ArborMultimeter(const std::string& name, + const std::vector& value_names, + conduit::Node* node) + : Device{name, node}, value_names_{value_names} {} + +std::unique_ptr ArborMultimeter::New( + const std::string& name, const std::vector& value_names, + conduit::Node* node) { + return std::make_unique(name, value_names, node); +} + +} // namespace producer +} // namespace niv diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp new file mode 100644 index 0000000..55c6eec --- /dev/null +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include +#include +#include + +#include "catch/catch.hpp" + +#include "niv/producer/arbor_multimeter.hpp" + +SCENARIO("A unique multimeter ptr can be constructed via its factory", + "[niv][niv::ArborMultimeter]") { + WHEN("a multimeter is constructed") { + std::unique_ptr multimeter{ + niv::producer::ArborMultimeter::New("name", std::vector(), + nullptr)}; + THEN("a pointer was obtained") { REQUIRE(multimeter.get() != nullptr); } + } +} From bf84bf48dded98605aa7afb6c90e153f5ac81228 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 20 Feb 2018 16:52:50 +0100 Subject: [PATCH 09/82] Adjust naming of some test data constants to style guide --- niv/include/niv/nest_test_data.hpp | 44 +++++++++++++++++--- niv/src/nest_test_data.cpp | 27 ++++++------ niv/tests/src/consumer/test_device.cpp | 7 ++-- niv/tests/src/consumer/test_integration.cpp | 6 +-- niv/tests/src/consumer/test_multimeter.cpp | 8 ++-- pyniv/src/pyniv.hpp | 1 + pyniv/src/testing/nest_test_data.cpp | 15 ++++--- pyniv/tests/src/consumer/test_device.py | 2 +- pyniv/tests/src/consumer/test_integration.py | 6 +-- pyniv/tests/src/consumer/test_multimeter.py | 2 +- 10 files changed, 76 insertions(+), 42 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index 9614f38..a36c7a3 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -42,12 +42,44 @@ class Testing { namespace testing { -std::string AnyAttribute(); -std::string AnotherAttribute(); -std::string ThirdAttribute(); - -double AnyTime(); -double AnotherTime(); +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +static const char* ANY_MULTIMETER_NAME{"multimeter A"}; + +static const std::vector ANY_TIMES{0.1, 0.2, 0.3}; +static const double ANY_TIME{ANY_TIMES[0]}; +static const double ANOTHER_TIME{ANY_TIMES[1]}; +static const double THIRD_TIME{ANY_TIMES[2]}; + +static const std::vector ANY_TIME_OFFSETS{0.0123, 0.0234, 0.0345}; +static const double ANY_TIME_OFFSET{ANY_TIME_OFFSETS[0]}; +static const double ANOTHER_TIME_OFFSET{ANY_TIME_OFFSETS[1]}; +static const double THIRD_TIME_OFFSET{ANY_TIME_OFFSETS[2]}; + +static const std::vector ANY_ATTRIBUTES{"V_m", "g_e", "g_i"}; +static const char* ANY_ATTRIBUTE{ANY_ATTRIBUTES[0].c_str()}; +static const char* ANOTHER_ATTRIBUTE{ANY_ATTRIBUTES[1].c_str()}; +static const char* THIRD_ATTRIBUTE{ANY_ATTRIBUTES[2].c_str()}; + +static const std::vector ANY_IDS{1, 2, 3}; +static const std::size_t ANY_ID{ANY_IDS[0]}; +static const std::size_t ANOTHER_ID{ANY_IDS[0]}; +static const std::size_t THIRD_ID{ANY_IDS[0]}; + +// clang-format off +static const std::vector ANY_VALUES{ + 0.111, 0.112, 0.113, 0.121, 0.122, 0.123, 0.131, 0.132, 0.133, + 0.211, 0.212, 0.213, 0.221, 0.222, 0.223, 0.231, 0.232, 0.233, + 0.311, 0.312, 0.313, 0.321, 0.322, 0.323, 0.331, 0.332, 0.333}; +// clang-format on +static const double ANY_VALUE{ANY_VALUES[0]}; + +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif std::vector AnyAttributesValues(double time = 0.0); std::vector AnotherAttributesValues(double time = 0.0); diff --git a/niv/src/nest_test_data.cpp b/niv/src/nest_test_data.cpp index 6594724..502557c 100644 --- a/niv/src/nest_test_data.cpp +++ b/niv/src/nest_test_data.cpp @@ -29,12 +29,14 @@ namespace niv { namespace testing { -std::string AnyAttribute() { return "V_m"; } -std::string AnotherAttribute() { return "g_m"; } -std::string ThirdAttribute() { return "g_i"; } +void unused() { (void)(ANY_MULTIMETER_NAME); } -double AnyTime() { return 0.0; } -double AnotherTime() { return 0.1; } +std::vector AnyValueNames() { + return std::vector{"V_m", "g_e", "g_i"}; +} +std::string AnyAttribute() { return AnyValueNames()[0]; } +std::string AnotherAttribute() { return AnyValueNames()[1]; } +std::string ThirdAttribute() { return AnyValueNames()[2]; } std::vector AnyAttributesValues(double time) { const double timed_offset = 1.1 * time + 2.2; @@ -55,30 +57,25 @@ std::vector ThirdAttributesValues(double time) { -6.45 + timed_offset, 7.56 + timed_offset}; } -std::vector AnyValueNames() { - return std::vector{AnyAttribute(), AnotherAttribute(), - ThirdAttribute()}; -} - std::string AnyMultimeterName() { return "multimeter A"; } conduit::Node AnyNestData() { conduit::Node node; niv::producer::Multimeter multimeter(AnyMultimeterName(), AnyValueNames(), &node); - multimeter.SetRecordingTime(AnyTime()); + multimeter.SetRecordingTime(ANY_TIME); for (auto i = 0u; i < AnyAttributesValues().size(); ++i) { multimeter.Record(i, std::vector{AnyAttributesValues()[i], AnotherAttributesValues()[i], ThirdAttributesValues()[i]}); } - multimeter.SetRecordingTime(AnotherTime()); + multimeter.SetRecordingTime(ANOTHER_TIME); for (auto i = 0u; i < AnyAttributesValues().size(); ++i) { multimeter.Record( - i, std::vector{AnyAttributesValues(AnotherTime())[i], - AnotherAttributesValues(AnotherTime())[i], - ThirdAttributesValues(AnotherTime())[i]}); + i, std::vector{AnyAttributesValues(ANOTHER_TIME)[i], + AnotherAttributesValues(ANOTHER_TIME)[i], + ThirdAttributesValues(ANOTHER_TIME)[i]}); } return node; diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index b41e745..69ff838 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -86,10 +86,9 @@ SCENARIO("A consumer::Device can list its timesteps", WHEN("The device is asked for the timesteps") { auto timesteps(device.GetTimesteps()); THEN("the list of timesteps is correct") { - REQUIRE_THAT( - timesteps, - Catch::Matchers::EqualsApprox(std::vector{ - niv::testing::AnyTime(), niv::testing::AnotherTime()})); + REQUIRE_THAT(timesteps, + Catch::Matchers::EqualsApprox(std::vector{ + niv::testing::ANY_TIME, niv::testing::ANOTHER_TIME})); } } } diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index c20a8bd..aca8b1f 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -46,18 +46,18 @@ SCENARIO("Consumer integration", "[niv][integration]") { backend.Receive(); WHEN("the multimeter queries the data") { - multimeter.SetTime(niv::testing::AnyTime()); + multimeter.SetTime(niv::testing::ANY_TIME); multimeter.Update(); std::vector values_at_t0{multimeter.GetValues()}; - multimeter.SetTime(niv::testing::AnotherTime()); + multimeter.SetTime(niv::testing::ANOTHER_TIME); multimeter.Update(); std::vector values_at_t1{multimeter.GetValues()}; THEN("the received values are correct") { REQUIRE(values_at_t0 == niv::testing::AnyAttributesValues()); REQUIRE(values_at_t1 == niv::testing::AnyAttributesValues( - niv::testing::AnotherTime())); + niv::testing::ANOTHER_TIME)); } } } diff --git a/niv/tests/src/consumer/test_multimeter.cpp b/niv/tests/src/consumer/test_multimeter.cpp index 18ebe5c..7147c31 100644 --- a/niv/tests/src/consumer/test_multimeter.cpp +++ b/niv/tests/src/consumer/test_multimeter.cpp @@ -36,7 +36,7 @@ SCENARIO("a Multimeter provides access to data stored in a conduit node", multimeter.SetNode(&nest_data); WHEN("The time step is set") { - multimeter.SetTime(niv::testing::AnyTime()); + multimeter.SetTime(niv::testing::ANY_TIME); WHEN("one attribute is queried") { multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); multimeter.Update(); @@ -58,7 +58,7 @@ SCENARIO("a Multimeter provides access to data stored in a conduit node", } WHEN("The time step is set to another value") { - multimeter.SetTime(niv::testing::AnotherTime()); + multimeter.SetTime(niv::testing::ANOTHER_TIME); WHEN("one attribute is queried") { multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); multimeter.Update(); @@ -66,7 +66,7 @@ SCENARIO("a Multimeter provides access to data stored in a conduit node", THEN("the result is correct") { REQUIRE_THAT(result, Catch::Matchers::Equals( niv::testing::AnyAttributesValues( - niv::testing::AnotherTime()))); + niv::testing::ANOTHER_TIME))); } } WHEN("another attribute is queried") { @@ -77,7 +77,7 @@ SCENARIO("a Multimeter provides access to data stored in a conduit node", THEN("the result is correct") { REQUIRE_THAT(result, Catch::Matchers::Equals( niv::testing::AnotherAttributesValues( - niv::testing::AnotherTime()))); + niv::testing::ANOTHER_TIME))); } } } diff --git a/pyniv/src/pyniv.hpp b/pyniv/src/pyniv.hpp index 45ab35c..8e4a5bc 100644 --- a/pyniv/src/pyniv.hpp +++ b/pyniv/src/pyniv.hpp @@ -38,6 +38,7 @@ using boost::python::def; using boost::python::init; using boost::python::no_init; using boost::python::pure_virtual; +using boost::python::scope; using boost::python::wrapper; namespace pyniv { diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 37ced33..28c3d0a 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -76,13 +76,18 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(AnyAttributesValuesOverloads, } // namespace testing +#ifndef EXPOSE_CONSTANT +#define EXPOSE_CONSTANT(a) scope().attr(#a) = niv::testing::a +#endif + template <> void expose() { - def("AnyAttribute", &niv::testing::AnyAttribute); - def("AnotherAttribute", &niv::testing::AnotherAttribute); - def("ThirdAttribute", &niv::testing::ThirdAttribute); - def("AnyTime", &niv::testing::AnyTime); - def("AnotherTime", &niv::testing::AnotherTime); + EXPOSE_CONSTANT(ANY_ATTRIBUTE); + EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE); + EXPOSE_CONSTANT(THIRD_ATTRIBUTE); + + EXPOSE_CONSTANT(ANY_TIME); + EXPOSE_CONSTANT(ANOTHER_TIME); def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, pyniv::testing::AnyAttributesValuesOverloads()); def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index b02d773..0875ba2 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -33,5 +33,5 @@ def test_consumer_device_lists_timesteps(): device.SetNode(any_data) timesteps = device.GetTimesteps() assert len(timesteps) == 2 - expected_timesteps = [pyniv.testing.AnyTime(), pyniv.testing.AnotherTime()] + expected_timesteps = [pyniv.testing.ANY_TIME, pyniv.testing.ANOTHER_TIME] assert np.isclose(timesteps, expected_timesteps).all() diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index 2350d98..4493007 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -37,12 +37,12 @@ def test_integration_consumer(): backend.Receive() - multimeter.SetTime(pyniv.testing.AnyTime()) + multimeter.SetTime(pyniv.testing.ANY_TIME) multimeter.Update() values_at_t0 = multimeter.GetValues() assert np.isclose(values_at_t0, pyniv.testing.AnyAttributesValues()).all() - multimeter.SetTime(pyniv.testing.AnotherTime()) + multimeter.SetTime(pyniv.testing.ANOTHER_TIME) multimeter.Update() values_at_t1 = multimeter.GetValues() - assert np.isclose(values_at_t1, pyniv.testing.AnyAttributesValues(pyniv.testing.AnotherTime())).all() + assert np.isclose(values_at_t1, pyniv.testing.AnyAttributesValues(pyniv.testing.ANOTHER_TIME)).all() diff --git a/pyniv/tests/src/consumer/test_multimeter.py b/pyniv/tests/src/consumer/test_multimeter.py index 84e3d2e..4a10632 100644 --- a/pyniv/tests/src/consumer/test_multimeter.py +++ b/pyniv/tests/src/consumer/test_multimeter.py @@ -26,7 +26,7 @@ def test_multimeter_provides_access_to_data_stored_in_a_conduit_node(): multimeter = pyniv.consumer.Multimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetNode(nest_data) - multimeter.SetTime(pyniv.testing.AnyTime()) + multimeter.SetTime(pyniv.testing.ANY_TIME) multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) multimeter.Update() From ef8525875eb19fe766ce21bda962a6f1022dd111 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 20 Feb 2018 16:53:13 +0100 Subject: [PATCH 10/82] Add required functionality to producer::ArborMultimeter --- niv/include/niv/producer/arbor_multimeter.hpp | 10 +++++++ niv/include/niv/producer/device.hpp | 3 ++ niv/src/producer/arbor_multimeter.cpp | 17 +++++++++++ niv/src/producer/device.cpp | 4 +++ .../src/producer/test_arbor_multimeter.cpp | 30 +++++++++++++++++++ 5 files changed, 64 insertions(+) diff --git a/niv/include/niv/producer/arbor_multimeter.hpp b/niv/include/niv/producer/arbor_multimeter.hpp index 754056b..0a922fe 100644 --- a/niv/include/niv/producer/arbor_multimeter.hpp +++ b/niv/include/niv/producer/arbor_multimeter.hpp @@ -33,6 +33,13 @@ namespace producer { class ArborMultimeter final : public Device { public: + struct Datum { + double time; + std::string attribute; + std::size_t id; + double value; + }; + ArborMultimeter(const std::string& name, const std::vector& value_names, conduit::Node* node); @@ -47,7 +54,10 @@ class ArborMultimeter final : public Device { const std::string& name, const std::vector& value_names, conduit::Node* node); + void Record(const Datum& datum); + private: + std::string CreatePath(const Datum& datum); std::vector value_names_; }; diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index 7d3c4fe..ec292ce 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -58,6 +58,9 @@ class Device { conduit::Node& GetTimestepNode(); + const std::string& GetName() { return name_; } + conduit::Node& GetNode(const std::string& path); + private: conduit::Node* node_{nullptr}; conduit::Node* timestep_node_{nullptr}; diff --git a/niv/src/producer/arbor_multimeter.cpp b/niv/src/producer/arbor_multimeter.cpp index 0fe714c..944c322 100644 --- a/niv/src/producer/arbor_multimeter.cpp +++ b/niv/src/producer/arbor_multimeter.cpp @@ -19,7 +19,10 @@ // limitations under the License. //------------------------------------------------------------------------------ +#include + #include +#include #include #include @@ -41,5 +44,19 @@ std::unique_ptr ArborMultimeter::New( return std::make_unique(name, value_names, node); } +void ArborMultimeter::Record(const ArborMultimeter::Datum& datum) { + const std::string path{CreatePath(datum)}; + GetNode(path) = datum.value; +} + +std::string ArborMultimeter::CreatePath(const ArborMultimeter::Datum& datum) { + std::stringstream path; + path << GetName() << '/'; + path << std::round(10.0 * datum.time) / 10.0 << '/'; + path << datum.attribute << '/'; + path << datum.id; + return path.str(); +} + } // namespace producer } // namespace niv diff --git a/niv/src/producer/device.cpp b/niv/src/producer/device.cpp index d4ec352..7f22d31 100644 --- a/niv/src/producer/device.cpp +++ b/niv/src/producer/device.cpp @@ -47,5 +47,9 @@ conduit::Node& Device::GetTimestepNode() { return *timestep_node_; } +conduit::Node& Device::GetNode(const std::string& path) { + return (*node_)[path]; +} + } // namespace producer } // namespace niv diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp index 55c6eec..4d76a3f 100644 --- a/niv/tests/src/producer/test_arbor_multimeter.cpp +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -20,11 +20,13 @@ //------------------------------------------------------------------------------ #include +#include #include #include #include "catch/catch.hpp" +#include "niv/nest_test_data.hpp" #include "niv/producer/arbor_multimeter.hpp" SCENARIO("A unique multimeter ptr can be constructed via its factory", @@ -36,3 +38,31 @@ SCENARIO("A unique multimeter ptr can be constructed via its factory", THEN("a pointer was obtained") { REQUIRE(multimeter.get() != nullptr); } } } + +SCENARIO("A multimeter records to a conduit node", + "[niv][niv::ArborMultimeter]") { + GIVEN("A conduit node and a multimeter") { + conduit::Node node; + niv::producer::ArborMultimeter multimeter{ + niv::testing::ANY_MULTIMETER_NAME, niv::testing::ANY_ATTRIBUTES, &node}; + + WHEN("recording data") { + niv::producer::ArborMultimeter::Datum datum{ + niv::testing::ANY_TIME + niv::testing::ANY_TIME_OFFSET, + std::string(niv::testing::ANY_ATTRIBUTE), niv::testing::ANY_ID, + niv::testing::ANY_VALUE}; + multimeter.Record(datum); + THEN("the data is recorded in the node") { + std::stringstream path; + path << niv::testing::ANY_MULTIMETER_NAME << '/'; + path << niv::testing::ANY_TIME << '/'; + path << niv::testing::ANY_ATTRIBUTE << '/'; + path << niv::testing::ANY_ID; + + REQUIRE(node[path.str()].as_double() == + Approx(niv::testing::ANY_VALUE)); + } + // id tag time value + } + } +} From 7950a5a21985f202c1c916fa5c0c10de3c224ca6 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 22 Feb 2018 07:55:08 +0100 Subject: [PATCH 11/82] Change test data's node ids to `string` to meet conduit requirements --- niv/include/niv/nest_test_data.hpp | 8 ++++---- niv/include/niv/producer/arbor_multimeter.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index a36c7a3..cdf7e0b 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -64,10 +64,10 @@ static const char* ANY_ATTRIBUTE{ANY_ATTRIBUTES[0].c_str()}; static const char* ANOTHER_ATTRIBUTE{ANY_ATTRIBUTES[1].c_str()}; static const char* THIRD_ATTRIBUTE{ANY_ATTRIBUTES[2].c_str()}; -static const std::vector ANY_IDS{1, 2, 3}; -static const std::size_t ANY_ID{ANY_IDS[0]}; -static const std::size_t ANOTHER_ID{ANY_IDS[0]}; -static const std::size_t THIRD_ID{ANY_IDS[0]}; +static const std::vector ANY_IDS{"1", "2", "3"}; +static const char* ANY_ID{ANY_IDS[0].c_str()}; +static const char* ANOTHER_ID{ANY_IDS[1].c_str()}; +static const char* THIRD_ID{ANY_IDS[2].c_str()}; // clang-format off static const std::vector ANY_VALUES{ diff --git a/niv/include/niv/producer/arbor_multimeter.hpp b/niv/include/niv/producer/arbor_multimeter.hpp index 0a922fe..d0a72e7 100644 --- a/niv/include/niv/producer/arbor_multimeter.hpp +++ b/niv/include/niv/producer/arbor_multimeter.hpp @@ -36,7 +36,7 @@ class ArborMultimeter final : public Device { struct Datum { double time; std::string attribute; - std::size_t id; + std::string id; double value; }; From 86b6ef6fe69b81abbe1801af537440f3a4de6b3a Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 22 Feb 2018 07:55:57 +0100 Subject: [PATCH 12/82] Add dump_to_stdout demo for arbor miniapp-niv --- demo/CMakeLists.txt | 3 +- demo/arbor_miniapp-niv/CMakeLists.txt | 30 +++++++++ demo/arbor_miniapp-niv/dump_to_stdout.py | 85 ++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 demo/arbor_miniapp-niv/CMakeLists.txt create mode 100644 demo/arbor_miniapp-niv/dump_to_stdout.py diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 84d5f99..024190f 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -19,5 +19,6 @@ # limitations under the License. #------------------------------------------------------------------------------- -add_subdirectory(nest_python_vis) +add_subdirectory(arbor_miniapp-niv) add_subdirectory(brunel_example) +add_subdirectory(nest_python_vis) diff --git a/demo/arbor_miniapp-niv/CMakeLists.txt b/demo/arbor_miniapp-niv/CMakeLists.txt new file mode 100644 index 0000000..bf930ca --- /dev/null +++ b/demo/arbor_miniapp-niv/CMakeLists.txt @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +set(ARBOR_PYTHON_DUMP_SOURCE dump_to_stdout.py) + +if(NOT CMAKE_MAKE_PROGRAM STREQUAL "/usr/bin/xcodebuild") + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_dump.sh + CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${ARBOR_PYTHON_DUMP_SOURCE}" + ) + +endif() diff --git a/demo/arbor_miniapp-niv/dump_to_stdout.py b/demo/arbor_miniapp-niv/dump_to_stdout.py new file mode 100644 index 0000000..cc8084e --- /dev/null +++ b/demo/arbor_miniapp-niv/dump_to_stdout.py @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +import sys + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns + +import pyniv + +from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout, QPushButton +from PyQt5.QtCore import QTimer + +class MainWindow: + def __init__(self): + self.SetupStreaming() + self.SetupWindow() + self.SetupUpdateTimer() + + def SetupStreaming(self): + self.receiver = pyniv.consumer.Receiver() + + self.multimeter = pyniv.consumer.Multimeter("multimeter") + self.multimeter.SetAttribute("v") + + self.backend = pyniv.consumer.Backend(); + self.backend.Connect(self.receiver); + self.backend.Connect(self.multimeter); + + def SetupWindow(self): + self.print_button = QPushButton("Print") + self.print_button.clicked.connect(self.PrintButtonClicked) + + def SetupUpdateTimer(self): + self.update_timer = QTimer() + self.update_timer.timeout.connect(self.Receive) + self.update_timer.start(1) + + def PrintButtonClicked(self): + self.multimeter.Print() + + def Show(self): + self.print_button.show() + button_geometry = self.print_button.geometry() + self.print_button.setGeometry( + 0, 0, + button_geometry.width(), + button_geometry.height()) + + def Receive(self): + self.backend.Receive() + + def Dump(self): + print("DUMP") + + +def main(argv): + app = QApplication(argv) + + w = MainWindow() + w.Show() + + return app.exec_() + +if __name__ == "__main__": + main(sys.argv) From c2c3f9fd19e645ad481d74e0c32516814662bc49 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 22 Feb 2018 15:59:45 +0100 Subject: [PATCH 13/82] Fix naming in arbor miniapp demo --- demo/arbor_miniapp-niv/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/arbor_miniapp-niv/CMakeLists.txt b/demo/arbor_miniapp-niv/CMakeLists.txt index bf930ca..6dd1275 100644 --- a/demo/arbor_miniapp-niv/CMakeLists.txt +++ b/demo/arbor_miniapp-niv/CMakeLists.txt @@ -19,12 +19,12 @@ # limitations under the License. #------------------------------------------------------------------------------- -set(ARBOR_PYTHON_DUMP_SOURCE dump_to_stdout.py) +set(PYTHON_DUMP_SOURCE dump_to_stdout.py) if(NOT CMAKE_MAKE_PROGRAM STREQUAL "/usr/bin/xcodebuild") file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_dump.sh - CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${ARBOR_PYTHON_DUMP_SOURCE}" + CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${PYTHON_DUMP_SOURCE}" ) endif() From 82173a0fc9802feeee779662a8338d0ae11e6581 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 22 Feb 2018 16:49:55 +0100 Subject: [PATCH 14/82] Minor fixes in consumer::Receiver --- niv/include/niv/consumer/receiver.hpp | 2 +- niv/tests/src/consumer/test_receiver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/niv/include/niv/consumer/receiver.hpp b/niv/include/niv/consumer/receiver.hpp index 9fe8206..e9bcc6b 100644 --- a/niv/include/niv/consumer/receiver.hpp +++ b/niv/include/niv/consumer/receiver.hpp @@ -44,8 +44,8 @@ class Receiver { virtual void Receive(); private: + conduit::Node* node_{nullptr}; exchange::RelaySharedMemory relay_; - conduit::Node* node_; }; } // namespace consumer diff --git a/niv/tests/src/consumer/test_receiver.cpp b/niv/tests/src/consumer/test_receiver.cpp index b66ed83..74b3919 100644 --- a/niv/tests/src/consumer/test_receiver.cpp +++ b/niv/tests/src/consumer/test_receiver.cpp @@ -29,7 +29,7 @@ SCENARIO("received data is aggregated in the consumer::Receiver", "[niv][niv::consumer][niv::consumer::Receiver]") { - GIVEN("A SchnchronizedAggregatingReceiver and a sending relay") { + GIVEN("A Receiver and a sending relay") { niv::consumer::Receiver receiver; conduit::Node receiving_node; receiver.SetNode(&receiving_node); From 73b548b55276a4b55dd72dfc1d3c997fe39aebaf Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 22 Feb 2018 16:50:02 +0100 Subject: [PATCH 15/82] Add producer::Sender --- niv/include/niv/producer/sender.hpp | 54 ++++++++++++++++++++++++++ niv/src/producer/sender.cpp | 30 ++++++++++++++ niv/tests/src/producer/test_sender.cpp | 49 +++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 niv/include/niv/producer/sender.hpp create mode 100644 niv/src/producer/sender.cpp create mode 100644 niv/tests/src/producer/test_sender.cpp diff --git a/niv/include/niv/producer/sender.hpp b/niv/include/niv/producer/sender.hpp new file mode 100644 index 0000000..0470db7 --- /dev/null +++ b/niv/include/niv/producer/sender.hpp @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_INCLUDE_NIV_PRODUCER_SENDER_HPP_ +#define NIV_INCLUDE_NIV_PRODUCER_SENDER_HPP_ + +#include "conduit/conduit_node.hpp" + +#include "niv/exchange/relay_shared_memory.hpp" + +namespace niv { +namespace producer { + +class Sender { + public: + Sender() = default; + Sender(const Sender&) = delete; + Sender(Sender&&) = default; + ~Sender() = default; + + Sender& operator=(const Sender&) = delete; + Sender& operator=(Sender&&) = default; + + void SetNode(conduit::Node* node) { node_ = node; } + + virtual void Send(); + + private: + conduit::Node* node_{nullptr}; + niv::exchange::RelaySharedMemory relay_; +}; + +} // namespace producer +} // namespace niv + +#endif // NIV_INCLUDE_NIV_PRODUCER_SENDER_HPP_ diff --git a/niv/src/producer/sender.cpp b/niv/src/producer/sender.cpp new file mode 100644 index 0000000..18f46d6 --- /dev/null +++ b/niv/src/producer/sender.cpp @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "niv/producer/sender.hpp" + +namespace niv { +namespace producer { + +void Sender::Send() { relay_.Send(*node_); } + +} // namespace producer +} // namespace niv diff --git a/niv/tests/src/producer/test_sender.cpp b/niv/tests/src/producer/test_sender.cpp new file mode 100644 index 0000000..9650076 --- /dev/null +++ b/niv/tests/src/producer/test_sender.cpp @@ -0,0 +1,49 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "catch/catch.hpp" + +#include "conduit/conduit_node.hpp" + +#include "niv/exchange/relay_shared_memory.hpp" +#include "niv/nest_test_data.hpp" +#include "niv/producer/sender.hpp" + +#include "conduit_node_helper.hpp" + +SCENARIO("data is sent via the producer::Sender", + "[niv][niv::producer::Sender]") { + GIVEN("sender and receiving relay") { + niv::producer::Sender sender; + conduit::Node sending_node{niv::testing::AnyNode()}; + sender.SetNode(&sending_node); + niv::exchange::RelaySharedMemory receiver; + + WHEN("data is sent and Receive is called on the relay") { + sender.Send(); + conduit::Node received_node = receiver.Receive(); + + THEN("data is received correctly") { + REQUIRE_THAT(received_node, Equals(niv::testing::AnyNode())); + } + } + } +} From 96e0de269064b1b0de268391deb874c0f2a0844f Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 23 Feb 2018 00:25:33 +0100 Subject: [PATCH 16/82] Change ArborMultimeter to suit arbor better --- niv/include/niv/producer/arbor_multimeter.hpp | 22 +++++--------- niv/src/producer/arbor_multimeter.cpp | 29 +++++++++---------- .../src/producer/test_arbor_multimeter.cpp | 21 ++++---------- 3 files changed, 26 insertions(+), 46 deletions(-) diff --git a/niv/include/niv/producer/arbor_multimeter.hpp b/niv/include/niv/producer/arbor_multimeter.hpp index d0a72e7..3f2e1df 100644 --- a/niv/include/niv/producer/arbor_multimeter.hpp +++ b/niv/include/niv/producer/arbor_multimeter.hpp @@ -22,16 +22,12 @@ #ifndef NIV_INCLUDE_NIV_PRODUCER_ARBOR_MULTIMETER_HPP_ #define NIV_INCLUDE_NIV_PRODUCER_ARBOR_MULTIMETER_HPP_ -#include #include -#include - -#include "niv/producer/device.hpp" namespace niv { namespace producer { -class ArborMultimeter final : public Device { +class ArborMultimeter final { public: struct Datum { double time; @@ -40,9 +36,7 @@ class ArborMultimeter final : public Device { double value; }; - ArborMultimeter(const std::string& name, - const std::vector& value_names, - conduit::Node* node); + explicit ArborMultimeter(const std::string& name); ArborMultimeter(const ArborMultimeter&) = default; ArborMultimeter(ArborMultimeter&&) = default; ~ArborMultimeter() = default; @@ -50,15 +44,13 @@ class ArborMultimeter final : public Device { ArborMultimeter& operator=(const ArborMultimeter&) = default; ArborMultimeter& operator=(ArborMultimeter&&) = default; - static std::unique_ptr New( - const std::string& name, const std::vector& value_names, - conduit::Node* node); - - void Record(const Datum& datum); + void Record(const Datum& datum, conduit::Node* node); private: - std::string CreatePath(const Datum& datum); - std::vector value_names_; + std::string ConstructPath(const Datum& datum); + double ConstructTimestep(const Datum& datum); + + std::string name_; }; } // namespace producer diff --git a/niv/src/producer/arbor_multimeter.cpp b/niv/src/producer/arbor_multimeter.cpp index 944c322..0d7ea64 100644 --- a/niv/src/producer/arbor_multimeter.cpp +++ b/niv/src/producer/arbor_multimeter.cpp @@ -33,30 +33,27 @@ namespace niv { namespace producer { -ArborMultimeter::ArborMultimeter(const std::string& name, - const std::vector& value_names, - conduit::Node* node) - : Device{name, node}, value_names_{value_names} {} - -std::unique_ptr ArborMultimeter::New( - const std::string& name, const std::vector& value_names, - conduit::Node* node) { - return std::make_unique(name, value_names, node); -} +ArborMultimeter::ArborMultimeter(const std::string& name) : name_{name} {} -void ArborMultimeter::Record(const ArborMultimeter::Datum& datum) { - const std::string path{CreatePath(datum)}; - GetNode(path) = datum.value; +void ArborMultimeter::Record(const ArborMultimeter::Datum& datum, + conduit::Node* node) { + const std::string path{ConstructPath(datum)}; + (*node)[path] = datum.value; } -std::string ArborMultimeter::CreatePath(const ArborMultimeter::Datum& datum) { +std::string ArborMultimeter::ConstructPath( + const ArborMultimeter::Datum& datum) { std::stringstream path; - path << GetName() << '/'; - path << std::round(10.0 * datum.time) / 10.0 << '/'; + path << name_ << '/'; + path << ConstructTimestep(datum) << '/'; path << datum.attribute << '/'; path << datum.id; return path.str(); } +double ArborMultimeter::ConstructTimestep(const ArborMultimeter::Datum& datum) { + return std::round(10.0 * datum.time) / 10.0; +} + } // namespace producer } // namespace niv diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp index 4d76a3f..44f2656 100644 --- a/niv/tests/src/producer/test_arbor_multimeter.cpp +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -26,33 +26,24 @@ #include "catch/catch.hpp" +#include "conduit/conduit.hpp" + #include "niv/nest_test_data.hpp" #include "niv/producer/arbor_multimeter.hpp" -SCENARIO("A unique multimeter ptr can be constructed via its factory", - "[niv][niv::ArborMultimeter]") { - WHEN("a multimeter is constructed") { - std::unique_ptr multimeter{ - niv::producer::ArborMultimeter::New("name", std::vector(), - nullptr)}; - THEN("a pointer was obtained") { REQUIRE(multimeter.get() != nullptr); } - } -} - SCENARIO("A multimeter records to a conduit node", "[niv][niv::ArborMultimeter]") { GIVEN("A conduit node and a multimeter") { conduit::Node node; niv::producer::ArborMultimeter multimeter{ - niv::testing::ANY_MULTIMETER_NAME, niv::testing::ANY_ATTRIBUTES, &node}; - + niv::testing::ANY_MULTIMETER_NAME}; WHEN("recording data") { niv::producer::ArborMultimeter::Datum datum{ niv::testing::ANY_TIME + niv::testing::ANY_TIME_OFFSET, - std::string(niv::testing::ANY_ATTRIBUTE), niv::testing::ANY_ID, + niv::testing::ANY_ATTRIBUTE, niv::testing::ANY_ID, niv::testing::ANY_VALUE}; - multimeter.Record(datum); - THEN("the data is recorded in the node") { + multimeter.Record(datum, &node); + THEN("the data is properly recorded") { std::stringstream path; path << niv::testing::ANY_MULTIMETER_NAME << '/'; path << niv::testing::ANY_TIME << '/'; From 2276b656b0afa8265cf25d3f839679181db13e9f Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Feb 2018 08:04:11 +0100 Subject: [PATCH 17/82] Towards a consumer::ArborMultimeter --- niv/include/niv/consumer/arbor_multimeter.hpp | 53 +++++++++++++++++++ niv/src/consumer/arbor_multimeter.cpp | 34 ++++++++++++ .../src/consumer/test_arbor_multimeter.cpp | 40 ++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 niv/include/niv/consumer/arbor_multimeter.hpp create mode 100644 niv/src/consumer/arbor_multimeter.cpp create mode 100644 niv/tests/src/consumer/test_arbor_multimeter.cpp diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp new file mode 100644 index 0000000..46ae822 --- /dev/null +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -0,0 +1,53 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_INCLUDE_NIV_CONSUMER_ARBOR_MULTIMETER_HPP_ +#define NIV_INCLUDE_NIV_CONSUMER_ARBOR_MULTIMETER_HPP_ + +#include +#include + +#include "niv/consumer/device.hpp" + +namespace niv { +namespace consumer { + +class ArborMultimeter : public niv::consumer::Device { + public: + ArborMultimeter() = default; + explicit ArborMultimeter(const std::string& name); + ArborMultimeter(const ArborMultimeter&) = default; + ArborMultimeter(ArborMultimeter&&) = default; + ~ArborMultimeter() = default; + + void Update() override; + + ArborMultimeter& operator=(const ArborMultimeter&) = default; + ArborMultimeter& operator=(ArborMultimeter&&) = default; + + private: + conduit::Node* GetAttributeNode(const std::string& attribute); +}; + +} // namespace consumer +} // namespace niv + +#endif // NIV_INCLUDE_NIV_CONSUMER_ARBOR_MULTIMETER_HPP_ diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp new file mode 100644 index 0000000..b24ab2e --- /dev/null +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include + +#include "niv/consumer/arbor_multimeter.hpp" + +namespace niv { +namespace consumer { + +ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} + +void ArborMultimeter::Update() { SetTimestepNode(); } + +} // namespace consumer +} // namespace niv diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp new file mode 100644 index 0000000..e72eab9 --- /dev/null +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "catch/Catch.hpp" + +#include "niv/consumer/arbor_multimeter.hpp" +#include "niv/nest_test_data.hpp" + +SCENARIO("An ArborMultimeter can list the stored node ids in a timestep", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + GIVEN("a multimeter providing access to some data") { + const conduit::Node nest_data{niv::testing::AnyNestData()}; + niv::consumer::ArborMultimeter multimeter( + niv::testing::AnyMultimeterName()); + multimeter.SetNode(&nest_data); + + WHEN("The time step is set") { + multimeter.SetTime(niv::testing::ANY_TIME); + multimeter.Update(); + } + } +} From 034c75d2c4c26a7598f63082d598af157f8dbef1 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Feb 2018 15:50:42 +0100 Subject: [PATCH 18/82] Verify conduit's data layout --- niv/tests/src/test_conduit.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index 965b705..f5563bb 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -288,16 +288,25 @@ SCENARIO("node updates into pre-allocated node with unexpected order", SCENARIO("conduit data layout", "[conduit]") { GIVEN("a compacted conduit node") { conduit::Node node; - niv::testing::AnyNode().compact_to(node); + niv::testing::UpdatedNode().compact_to(node); THEN("the node's data is contiguous") { REQUIRE(node.is_contiguous()); } WHEN("the node's data is accessed via ptr") { const double* data_ptr = reinterpret_cast(node.contiguous_data_ptr()); + std::cout << niv::testing::UpdatedNode().schema().to_json() << std::endl; + THEN("the leafs' data is accessible as an array") { - REQUIRE(data_ptr[0] == 3.1415); - REQUIRE(data_ptr[1] == 4.124); - REQUIRE(data_ptr[2] == 42.0); + REQUIRE(data_ptr[0] == + niv::testing::UpdatedNode()["A/B/C"].as_double()); + REQUIRE(data_ptr[1] == + niv::testing::UpdatedNode()["A/B/D"].as_double()); + REQUIRE(data_ptr[2] == + niv::testing::UpdatedNode()["A/B/F"].as_double()); + REQUIRE(data_ptr[3] == + niv::testing::UpdatedNode()["A/B/G"].as_double()); + REQUIRE(data_ptr[4] == niv::testing::UpdatedNode()["A/E"].as_double()); + REQUIRE(data_ptr[5] == niv::testing::UpdatedNode()["A/H"].as_double()); } } } From fe7ef10502690de295e87bc8e6824bc06c9ef772 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Feb 2018 16:23:44 +0100 Subject: [PATCH 19/82] Verify conduit's creation of nodes from a schema --- niv/tests/src/test_conduit.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index f5563bb..c5af887 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -294,7 +294,6 @@ SCENARIO("conduit data layout", "[conduit]") { WHEN("the node's data is accessed via ptr") { const double* data_ptr = reinterpret_cast(node.contiguous_data_ptr()); - std::cout << niv::testing::UpdatedNode().schema().to_json() << std::endl; THEN("the leafs' data is accessible as an array") { REQUIRE(data_ptr[0] == @@ -311,3 +310,30 @@ SCENARIO("conduit data layout", "[conduit]") { } } } + +SCENARIO("create conduit::Node from data ans schema", "[conduit]") { + GIVEN("a schema and data") { + const std::string schema{ + "{ \n" + " \"A\":{ \n" + " \"B\":{\"dtype\":\"float64\", \"number_of_elements\": 1, \n" + " \"offset\": 0, \"stride\": 8, \"element_bytes\": 8}, \n" + " \"C\":{\"dtype\":\"float64\", \"number_of_elements\": 1, \n" + " \"offset\": 8, \"stride\": 8, \"element_bytes\": 8} \n" + " }, \n" + " \"D\":{\"dtype\":\"float64\", \"number_of_elements\": 1, \n" + " \"offset\": 16, \"stride\": 8, \"element_bytes\": 8} \n" + "}"}; + std::vector data{1.23, 2.34, 3.45}; + + WHEN("a node is created from that") { + conduit::Node node(schema, reinterpret_cast(data.data()), true); + + THEN("it contains the expected data") { + REQUIRE(node["A/B"].as_double() == data[0]); + REQUIRE(node["A/C"].as_double() == data[1]); + REQUIRE(node["D"].as_double() == data[2]); + } + } + } +} From 2cd4c5ff8b14476b9834246ee47d7786ba38c921 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 00:21:19 +0100 Subject: [PATCH 20/82] Add conduit test verifying node creation from schema stringstream --- niv/include/niv/nest_test_data.hpp | 61 ++++++++++++++++++++++++++++++ niv/tests/src/test_conduit.cpp | 41 +++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index cdf7e0b..c3ae29e 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -48,11 +48,13 @@ namespace testing { #endif static const char* ANY_MULTIMETER_NAME{"multimeter A"}; +static const char* NOT_A_MULTIMETER_NAME{"NOT_A_MULTIMETER_NAME"}; static const std::vector ANY_TIMES{0.1, 0.2, 0.3}; static const double ANY_TIME{ANY_TIMES[0]}; static const double ANOTHER_TIME{ANY_TIMES[1]}; static const double THIRD_TIME{ANY_TIMES[2]}; +static const double NOT_A_TIME{ANY_TIMES.back() + 1.0}; static const std::vector ANY_TIME_OFFSETS{0.0123, 0.0234, 0.0345}; static const double ANY_TIME_OFFSET{ANY_TIME_OFFSETS[0]}; @@ -63,11 +65,13 @@ static const std::vector ANY_ATTRIBUTES{"V_m", "g_e", "g_i"}; static const char* ANY_ATTRIBUTE{ANY_ATTRIBUTES[0].c_str()}; static const char* ANOTHER_ATTRIBUTE{ANY_ATTRIBUTES[1].c_str()}; static const char* THIRD_ATTRIBUTE{ANY_ATTRIBUTES[2].c_str()}; +static const char* NOT_AN_ATTRIBUTE{"NOT_AN_ATTRIBUTE"}; static const std::vector ANY_IDS{"1", "2", "3"}; static const char* ANY_ID{ANY_IDS[0].c_str()}; static const char* ANOTHER_ID{ANY_IDS[1].c_str()}; static const char* THIRD_ID{ANY_IDS[2].c_str()}; +static const char* NOT_AN_ID{"NOT_AN_ID"}; // clang-format off static const std::vector ANY_VALUES{ @@ -77,6 +81,63 @@ static const std::vector ANY_VALUES{ // clang-format on static const double ANY_VALUE{ANY_VALUES[0]}; +template +inline std::string OpenTag(T tag) { + std::stringstream s; + s << '\"' << tag << '\"' << ":{ \n"; + return s.str(); +} + +inline std::string CloseTag() { return std::string("} \n"); } +inline std::string CloseTagNext() { return std::string("}, \n"); } + +inline std::string DoubleData(std::size_t offset) { + std::stringstream s; + s << "dtype:float64, "; + s << "number_of_elements:1, "; + s << "offset:" << offset << ", "; + s << "stride:8, "; + s << "element_bytes:8"; + s << "\n"; + return s.str(); +} + +inline void RemoveNextIndicator(std::stringstream* s) { + s->clear(); + s->seekp(s->str().size() - 3); + *s << " \n"; +} + +inline static const std::string AnyNestDataSchema() { + std::stringstream s; + std::size_t offset = 0; + const std::size_t datum_size = 8; + s << "{\n"; + s << " " << OpenTag(ANY_MULTIMETER_NAME); + for (auto time : ANY_TIMES) { + s << " " << OpenTag(time); + for (auto attribute : ANY_ATTRIBUTES) { + s << " " << OpenTag(attribute); + for (auto id : ANY_IDS) { + s << " " << OpenTag(id); + s << " " << DoubleData((offset++) * datum_size); + s << " " << CloseTagNext(); + } + RemoveNextIndicator(&s); + s << " " << CloseTagNext(); + } + RemoveNextIndicator(&s); + s << " " << CloseTagNext(); + } + RemoveNextIndicator(&s); + s << " " << CloseTag(); + s << "}"; + return s.str(); +} + +static conduit::Node ANY_NEST_DATA{ + AnyNestDataSchema(), const_cast(ANY_VALUES.data()), false}; + #if defined __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index c5af887..700e802 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -311,7 +311,7 @@ SCENARIO("conduit data layout", "[conduit]") { } } -SCENARIO("create conduit::Node from data ans schema", "[conduit]") { +SCENARIO("create conduit::Node from data and schema (string)", "[conduit]") { GIVEN("a schema and data") { const std::string schema{ "{ \n" @@ -337,3 +337,42 @@ SCENARIO("create conduit::Node from data ans schema", "[conduit]") { } } } + +namespace { + +const char* ANY_TAG{"A"}; + +} // namespace + +SCENARIO("create conduit::Node from data and schema (stringstream)", + "[conduit]") { + GIVEN("a schema and data") { + std::stringstream schema; + schema << "{\n"; + schema << " " << niv::testing::OpenTag(::ANY_TAG); + schema << " " << niv::testing::OpenTag("B"); + schema << " " << niv::testing::DoubleData(0); + schema << " " << niv::testing::CloseTagNext(); + schema << " " << niv::testing::OpenTag("C"); + schema << " " << niv::testing::DoubleData(8); + schema << " " << niv::testing::CloseTag(); + schema << " " << niv::testing::CloseTagNext(); + schema << " " << niv::testing::OpenTag("D"); + schema << " " << niv::testing::DoubleData(16); + schema << " " << niv::testing::CloseTag(); + schema << "}"; + + std::vector data{1.23, 2.34, 3.45}; + + WHEN("a node is created from that") { + conduit::Node node(schema.str(), reinterpret_cast(data.data()), + true); + + THEN("it contains the expected data") { + REQUIRE(node["A/B"].as_double() == data[0]); + REQUIRE(node["A/C"].as_double() == data[1]); + REQUIRE(node["D"].as_double() == data[2]); + } + } + } +} From 1396e66fdb309804a91ccb7d59479d328d10c82e Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 00:21:31 +0100 Subject: [PATCH 21/82] Add consumer::ArborMultimeter::GetIds --- niv/include/niv/consumer/arbor_multimeter.hpp | 3 ++ niv/include/niv/consumer/device.hpp | 3 ++ niv/src/consumer/arbor_multimeter.cpp | 34 +++++++++++++ niv/src/consumer/device.cpp | 4 ++ .../src/consumer/test_arbor_multimeter.cpp | 50 ++++++++++++++++--- 5 files changed, 87 insertions(+), 7 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 46ae822..06375f7 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -40,6 +40,9 @@ class ArborMultimeter : public niv::consumer::Device { void Update() override; + std::vector GetNodeIds(double time, + const std::string& attribute); + ArborMultimeter& operator=(const ArborMultimeter&) = default; ArborMultimeter& operator=(ArborMultimeter&&) = default; diff --git a/niv/include/niv/consumer/device.hpp b/niv/include/niv/consumer/device.hpp index 8fd4a46..fc09e18 100644 --- a/niv/include/niv/consumer/device.hpp +++ b/niv/include/niv/consumer/device.hpp @@ -56,6 +56,9 @@ class Device { void SetTimestepNode(); const conduit::Node* GetTimestepNode() const; + const conduit::Node* GetNode() const; + const std::string GetName() const; + private: const conduit::Node* node_{nullptr}; const conduit::Node* timestep_node_{nullptr}; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index b24ab2e..a1020b6 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -20,8 +20,12 @@ //------------------------------------------------------------------------------ #include +#include + +#include "conduit/conduit_node.hpp" #include "niv/consumer/arbor_multimeter.hpp" +#include "niv/nest_test_data.hpp" namespace niv { namespace consumer { @@ -30,5 +34,35 @@ ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} void ArborMultimeter::Update() { SetTimestepNode(); } +std::vector ArborMultimeter::GetNodeIds( + double time, const std::string& attribute) { + const conduit::Node* node{GetNode()}; + + const conduit::Node* device_node{nullptr}; + try { + device_node = &node->fetch_child(GetName()); + } catch (...) { + return std::vector(); + } + + std::stringstream time_stream; + time_stream << time; + const conduit::Node* timestep_node{nullptr}; + try { + timestep_node = &(device_node->fetch_child(time_stream.str())); + } catch (...) { + return std::vector(); + } + + const conduit::Node* attribute_node{nullptr}; + try { + attribute_node = &(timestep_node->fetch_child(attribute)); + } catch (...) { + return std::vector(); + } + + return attribute_node->child_names(); +} + } // namespace consumer } // namespace niv diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index 4713c7f..add5abc 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -80,5 +80,9 @@ void Device::Print() const { const conduit::Node* Device::GetTimestepNode() const { return timestep_node_; } +const conduit::Node* Device::GetNode() const { return node_; } + +const std::string Device::GetName() const { return name_; } + } // namespace consumer } // namespace niv diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index e72eab9..3d6e2e2 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -24,17 +24,53 @@ #include "niv/consumer/arbor_multimeter.hpp" #include "niv/nest_test_data.hpp" -SCENARIO("An ArborMultimeter can list the stored node ids in a timestep", +SCENARIO( + "ArborMultimeter lists the node ids stored for an attribute in a timestep", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("node ids are requested") { + auto ids{multimeter.GetNodeIds(niv::testing::ANY_TIME, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter provides the ids") { + REQUIRE(ids == niv::testing::ANY_IDS); + } + } + } +} + +SCENARIO("ArborMultimeter reports no ids if these cannot be found", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("node ids are requested") { + auto ids{multimeter.GetNodeIds(niv::testing::ANY_TIME, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } + } + } + GIVEN("a multimeter providing access to some data") { - const conduit::Node nest_data{niv::testing::AnyNestData()}; niv::consumer::ArborMultimeter multimeter( - niv::testing::AnyMultimeterName()); - multimeter.SetNode(&nest_data); + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("node ids are requested for an invalid timestep") { + auto ids{multimeter.GetNodeIds(niv::testing::NOT_A_TIME, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } + } - WHEN("The time step is set") { - multimeter.SetTime(niv::testing::ANY_TIME); - multimeter.Update(); + WHEN("node ids are requested for an invalid attribute") { + auto ids{multimeter.GetNodeIds(niv::testing::ANY_TIME, + niv::testing::NOT_AN_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } } } From 8becc49c9799369eaeceba47f0b259ad6b66cb83 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 00:55:16 +0100 Subject: [PATCH 22/82] Refactor ArborMultimeter::GetNodeIds to ArborMultimeter::GetNeuronIds --- niv/include/niv/consumer/arbor_multimeter.hpp | 7 ++- niv/src/consumer/arbor_multimeter.cpp | 44 ++++++++++++------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 06375f7..611eca2 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -47,7 +47,12 @@ class ArborMultimeter : public niv::consumer::Device { ArborMultimeter& operator=(ArborMultimeter&&) = default; private: - conduit::Node* GetAttributeNode(const std::string& attribute); + static std::string TimeToString(double time); + + static const conduit::Node* GetChildNode(const conduit::Node* parent, + const std::string& child_name); + + static std::vector GetChildNames(const conduit::Node* node); }; } // namespace consumer diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index a1020b6..5a2d2ce 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -36,32 +36,42 @@ void ArborMultimeter::Update() { SetTimestepNode(); } std::vector ArborMultimeter::GetNodeIds( double time, const std::string& attribute) { - const conduit::Node* node{GetNode()}; + const conduit::Node* const root_node{GetNode()}; + const conduit::Node* const device_node{GetChildNode(root_node, GetName())}; + const conduit::Node* const timestep_node{ + GetChildNode(device_node, TimeToString(time))}; + const conduit::Node* const attribute_node{ + GetChildNode(timestep_node, attribute)}; - const conduit::Node* device_node{nullptr}; - try { - device_node = &node->fetch_child(GetName()); - } catch (...) { - return std::vector(); + return GetChildNames(attribute_node); +} + +std::string ArborMultimeter::TimeToString(double time) { + std::stringstream s; + s << time; + return s.str(); +} + +const conduit::Node* ArborMultimeter::GetChildNode( + const conduit::Node* parent, const std::string& child_name) { + if (parent == nullptr) { + return nullptr; } - std::stringstream time_stream; - time_stream << time; - const conduit::Node* timestep_node{nullptr}; + const conduit::Node* child{nullptr}; try { - timestep_node = &(device_node->fetch_child(time_stream.str())); + child = &parent->fetch_child(child_name); } catch (...) { - return std::vector(); } + return child; +} - const conduit::Node* attribute_node{nullptr}; - try { - attribute_node = &(timestep_node->fetch_child(attribute)); - } catch (...) { +std::vector ArborMultimeter::GetChildNames( + const conduit::Node* node) { + if (node == nullptr) { return std::vector(); } - - return attribute_node->child_names(); + return node->child_names(); } } // namespace consumer From 1220d713290c018eafd3d9f2284e863aa228268c Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 00:55:33 +0100 Subject: [PATCH 23/82] continue the previous commit --- niv/include/niv/consumer/arbor_multimeter.hpp | 4 +-- niv/src/consumer/arbor_multimeter.cpp | 2 +- .../src/consumer/test_arbor_multimeter.cpp | 29 ++++++++++--------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 611eca2..968b832 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -40,8 +40,8 @@ class ArborMultimeter : public niv::consumer::Device { void Update() override; - std::vector GetNodeIds(double time, - const std::string& attribute); + std::vector GetNeuronIds(double time, + const std::string& attribute); ArborMultimeter& operator=(const ArborMultimeter&) = default; ArborMultimeter& operator=(ArborMultimeter&&) = default; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 5a2d2ce..d0dbe78 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -34,7 +34,7 @@ ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} void ArborMultimeter::Update() { SetTimestepNode(); } -std::vector ArborMultimeter::GetNodeIds( +std::vector ArborMultimeter::GetNeuronIds( double time, const std::string& attribute) { const conduit::Node* const root_node{GetNode()}; const conduit::Node* const device_node{GetChildNode(root_node, GetName())}; diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 3d6e2e2..f4a8f58 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -25,16 +25,17 @@ #include "niv/nest_test_data.hpp" SCENARIO( - "ArborMultimeter lists the node ids stored for an attribute in a timestep", + "ArborMultimeter lists the neuron ids stored for an attribute in a " + "timestep", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { GIVEN("a multimeter providing access to some data") { niv::consumer::ArborMultimeter multimeter( niv::testing::ANY_MULTIMETER_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - WHEN("node ids are requested") { - auto ids{multimeter.GetNodeIds(niv::testing::ANY_TIME, - niv::testing::ANY_ATTRIBUTE)}; + WHEN("neuron ids are requested") { + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, + niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter provides the ids") { REQUIRE(ids == niv::testing::ANY_IDS); } @@ -42,16 +43,16 @@ SCENARIO( } } -SCENARIO("ArborMultimeter reports no ids if these cannot be found", +SCENARIO("ArborMultimeter reports no neuron ids if these cannot be found", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { GIVEN("a multimeter with an incorrect name providing access to some data") { niv::consumer::ArborMultimeter multimeter( niv::testing::NOT_A_MULTIMETER_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - WHEN("node ids are requested") { - auto ids{multimeter.GetNodeIds(niv::testing::ANY_TIME, - niv::testing::ANY_ATTRIBUTE)}; + WHEN("neuron ids are requested") { + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, + niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } } @@ -61,15 +62,15 @@ SCENARIO("ArborMultimeter reports no ids if these cannot be found", niv::testing::ANY_MULTIMETER_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - WHEN("node ids are requested for an invalid timestep") { - auto ids{multimeter.GetNodeIds(niv::testing::NOT_A_TIME, - niv::testing::ANY_ATTRIBUTE)}; + WHEN("neuron ids are requested for an invalid timestep") { + auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME, + niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } - WHEN("node ids are requested for an invalid attribute") { - auto ids{multimeter.GetNodeIds(niv::testing::ANY_TIME, - niv::testing::NOT_AN_ATTRIBUTE)}; + WHEN("neuron ids are requested for an invalid attribute") { + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, + niv::testing::NOT_AN_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } } From 70a21a5c4e8e792aeadb06a8cca506c67366067e Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 09:30:05 +0100 Subject: [PATCH 24/82] Add test verifying intended conduit::Node::fetch_child behaviour --- niv/tests/src/test_conduit.cpp | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index 700e802..71f2068 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -376,3 +376,51 @@ SCENARIO("create conduit::Node from data and schema (stringstream)", } } } + +SCENARIO("conduit::Node::getch_child(path) behaves as intended", "[conduit]") { + GIVEN("a const ptr to a node with some data") { + conduit::Node node; + node["A/B/C"] = niv::testing::ANY_VALUE; + const conduit::Node* const node_ptr{&node}; + + WHEN("fetch_child is called with a correct path") { + THEN("it does not throw and yield the correct datum") { + const conduit::Node* retrieved_node_ptr{nullptr}; + REQUIRE_NOTHROW(retrieved_node_ptr = &node_ptr->fetch_child("A/B/C")); + REQUIRE(retrieved_node_ptr->as_double() == niv::testing::ANY_VALUE); + } + } + + WHEN("fetch_child is called with an incorrect path; completely off") { + THEN("it throws") { + const conduit::Node* retrieved_node_ptr{nullptr}; + REQUIRE_THROWS(retrieved_node_ptr = + &node_ptr->fetch_child("FOO/BAR/FOOBAR")); + } + } + + WHEN("fetch_child is called with an incorrect path; error at front") { + THEN("it throws") { + const conduit::Node* retrieved_node_ptr{nullptr}; + REQUIRE_THROWS(retrieved_node_ptr = + &node_ptr->fetch_child("ERROR/B/C")); + } + } + + WHEN("fetch_child is called with an incorrect path; error at middle") { + THEN("it throws") { + const conduit::Node* retrieved_node_ptr{nullptr}; + REQUIRE_THROWS(retrieved_node_ptr = + &node_ptr->fetch_child("A/ERROR/C")); + } + } + + WHEN("fetch_child is called with an incorrect path; error at end") { + THEN("it throws") { + const conduit::Node* retrieved_node_ptr{nullptr}; + REQUIRE_THROWS(retrieved_node_ptr = + &node_ptr->fetch_child("A/B/ERROR")); + } + } + } +} From f8beb510852c22a1986a35355b58bbc9396ed1d3 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 09:37:26 +0100 Subject: [PATCH 25/82] Add consumer::ArborMultimeter::GetDatum --- niv/include/niv/consumer/arbor_multimeter.hpp | 7 ++- niv/include/niv/consumer/device.hpp | 2 +- niv/src/consumer/arbor_multimeter.cpp | 32 +++++++++++++- niv/src/consumer/device.cpp | 2 +- .../src/consumer/test_arbor_multimeter.cpp | 44 +++++++++++++++++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 968b832..1ee12d5 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -41,7 +41,9 @@ class ArborMultimeter : public niv::consumer::Device { void Update() override; std::vector GetNeuronIds(double time, - const std::string& attribute); + const std::string& attribute) const; + double GetDatum(double time, const std::string& attribute, + const std::string& neuron_id) const; ArborMultimeter& operator=(const ArborMultimeter&) = default; ArborMultimeter& operator=(ArborMultimeter&&) = default; @@ -53,6 +55,9 @@ class ArborMultimeter : public niv::consumer::Device { const std::string& child_name); static std::vector GetChildNames(const conduit::Node* node); + + std::string ConstructPath(double time, const std::string& attribute, + const std::string& neuron_id) const; }; } // namespace consumer diff --git a/niv/include/niv/consumer/device.hpp b/niv/include/niv/consumer/device.hpp index fc09e18..9eeb05b 100644 --- a/niv/include/niv/consumer/device.hpp +++ b/niv/include/niv/consumer/device.hpp @@ -56,7 +56,7 @@ class Device { void SetTimestepNode(); const conduit::Node* GetTimestepNode() const; - const conduit::Node* GetNode() const; + const conduit::Node* GetRootNode() const; const std::string GetName() const; private: diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index d0dbe78..9b916b2 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -19,6 +19,8 @@ // limitations under the License. //------------------------------------------------------------------------------ +#include + #include #include @@ -35,8 +37,8 @@ ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} void ArborMultimeter::Update() { SetTimestepNode(); } std::vector ArborMultimeter::GetNeuronIds( - double time, const std::string& attribute) { - const conduit::Node* const root_node{GetNode()}; + double time, const std::string& attribute) const { + const conduit::Node* const root_node{GetRootNode()}; const conduit::Node* const device_node{GetChildNode(root_node, GetName())}; const conduit::Node* const timestep_node{ GetChildNode(device_node, TimeToString(time))}; @@ -74,5 +76,31 @@ std::vector ArborMultimeter::GetChildNames( return node->child_names(); } +double ArborMultimeter::GetDatum(double time, const std::string& attribute, + const std::string& neuron_id) const { + const std::string path{ConstructPath(time, attribute, neuron_id)}; + + const conduit::Node* const root_node{GetRootNode()}; + const conduit::Node* data_node{nullptr}; + try { + data_node = &root_node->fetch_child(path); + } catch (...) { + return std::nan(""); + } + + return data_node->as_double(); +} + +std::string ArborMultimeter::ConstructPath(double time, + const std::string& attribute, + const std::string& neuron_id) const { + std::stringstream path; + path << GetName() << "/"; + path << time << "/"; + path << attribute << "/"; + path << neuron_id; + return path.str(); +} + } // namespace consumer } // namespace niv diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index add5abc..25db0a0 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -80,7 +80,7 @@ void Device::Print() const { const conduit::Node* Device::GetTimestepNode() const { return timestep_node_; } -const conduit::Node* Device::GetNode() const { return node_; } +const conduit::Node* Device::GetRootNode() const { return node_; } const std::string Device::GetName() const { return name_; } diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index f4a8f58..239038a 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -75,3 +75,47 @@ SCENARIO("ArborMultimeter reports no neuron ids if these cannot be found", } } } + +SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting data") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID); + THEN("it is correct") { + const std::size_t ANY_TIME_OFFSET{0 * 9}; + const std::size_t ANOTHER_ATTRIBUTE_OFFSET{1 * 3}; + const std::size_t THIRD_ID_OFFSET{2}; + const std::size_t DATUM_OFFSET{ + ANY_TIME_OFFSET + ANOTHER_ATTRIBUTE_OFFSET + THIRD_ID_OFFSET}; + REQUIRE(datum == Approx(niv::testing::ANY_VALUES[DATUM_OFFSET])); + } + } + + WHEN("requesting datum at an invalid time") { + const double datum = multimeter.GetDatum(niv::testing::NOT_A_TIME, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID); + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + + WHEN("requesting datum for an invalid attribute") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + niv::testing::NOT_AN_ATTRIBUTE, + niv::testing::THIRD_ID); + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + + WHEN("requesting datum for an invalid neuron id") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::NOT_AN_ID); + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + } +} From 46280cd91b68d521eff8855c1b337b8f1eb1104c Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 09:53:59 +0100 Subject: [PATCH 26/82] Refactor consumer::ArborMultimeter: remove code duplication --- niv/include/niv/consumer/arbor_multimeter.hpp | 11 ++- niv/src/consumer/arbor_multimeter.cpp | 72 ++++++++----------- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 1ee12d5..14529f3 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -49,15 +49,14 @@ class ArborMultimeter : public niv::consumer::Device { ArborMultimeter& operator=(ArborMultimeter&&) = default; private: - static std::string TimeToString(double time); + std::string ConstructPath(double time, const std::string& attribute, + const std::string& neuron_id) const; + std::string ConstructPath(double time, const std::string& attribute) const; - static const conduit::Node* GetChildNode(const conduit::Node* parent, - const std::string& child_name); + const conduit::Node* GetNode(const std::string& path) const; static std::vector GetChildNames(const conduit::Node* node); - - std::string ConstructPath(double time, const std::string& attribute, - const std::string& neuron_id) const; + static double GetValue(const conduit::Node* node); }; } // namespace consumer diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 9b916b2..2c75f88 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -38,34 +38,43 @@ void ArborMultimeter::Update() { SetTimestepNode(); } std::vector ArborMultimeter::GetNeuronIds( double time, const std::string& attribute) const { - const conduit::Node* const root_node{GetRootNode()}; - const conduit::Node* const device_node{GetChildNode(root_node, GetName())}; - const conduit::Node* const timestep_node{ - GetChildNode(device_node, TimeToString(time))}; - const conduit::Node* const attribute_node{ - GetChildNode(timestep_node, attribute)}; + const std::string path{ConstructPath(time, attribute)}; + const conduit::Node* node{GetNode(path)}; + return GetChildNames(node); +} - return GetChildNames(attribute_node); +double ArborMultimeter::GetDatum(double time, const std::string& attribute, + const std::string& neuron_id) const { + const std::string path{ConstructPath(time, attribute, neuron_id)}; + const conduit::Node* node{GetNode(path)}; + return GetValue(node); } -std::string ArborMultimeter::TimeToString(double time) { - std::stringstream s; - s << time; - return s.str(); +std::string ArborMultimeter::ConstructPath(double time, + const std::string& attribute, + const std::string& neuron_id) const { + std::stringstream path; + path << ConstructPath(time, attribute) << "/"; + path << neuron_id; + return path.str(); } -const conduit::Node* ArborMultimeter::GetChildNode( - const conduit::Node* parent, const std::string& child_name) { - if (parent == nullptr) { - return nullptr; - } +std::string ArborMultimeter::ConstructPath(double time, + const std::string& attribute) const { + std::stringstream path; + path << GetName() << "/"; + path << time << "/"; + path << attribute; + return path.str(); +} - const conduit::Node* child{nullptr}; +const conduit::Node* ArborMultimeter::GetNode(const std::string& path) const { + const conduit::Node* node{nullptr}; try { - child = &parent->fetch_child(child_name); + node = &GetRootNode()->fetch_child(path); } catch (...) { } - return child; + return node; } std::vector ArborMultimeter::GetChildNames( @@ -76,30 +85,11 @@ std::vector ArborMultimeter::GetChildNames( return node->child_names(); } -double ArborMultimeter::GetDatum(double time, const std::string& attribute, - const std::string& neuron_id) const { - const std::string path{ConstructPath(time, attribute, neuron_id)}; - - const conduit::Node* const root_node{GetRootNode()}; - const conduit::Node* data_node{nullptr}; - try { - data_node = &root_node->fetch_child(path); - } catch (...) { +double ArborMultimeter::GetValue(const conduit::Node* node) { + if (node == nullptr) { return std::nan(""); } - - return data_node->as_double(); -} - -std::string ArborMultimeter::ConstructPath(double time, - const std::string& attribute, - const std::string& neuron_id) const { - std::stringstream path; - path << GetName() << "/"; - path << time << "/"; - path << attribute << "/"; - path << neuron_id; - return path.str(); + return node->as_double(); } } // namespace consumer From 3f85a0427b2e61f65242b0fd8fad970b41668b03 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 09:54:54 +0100 Subject: [PATCH 27/82] Make ArborMultimeter::Update() a nop --- niv/src/consumer/arbor_multimeter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 2c75f88..7752879 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -34,7 +34,7 @@ namespace consumer { ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} -void ArborMultimeter::Update() { SetTimestepNode(); } +void ArborMultimeter::Update() {} std::vector ArborMultimeter::GetNeuronIds( double time, const std::string& attribute) const { From 131817d89accdc0aaac67722c6400010823f8609 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 10:03:04 +0100 Subject: [PATCH 28/82] Combine tests for consumer::ArborMultimeter::GetNeuronIds --- .../src/consumer/test_arbor_multimeter.cpp | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 239038a..69aeb89 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -40,37 +40,28 @@ SCENARIO( REQUIRE(ids == niv::testing::ANY_IDS); } } - } -} -SCENARIO("ArborMultimeter reports no neuron ids if these cannot be found", - "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { - GIVEN("a multimeter with an incorrect name providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::NOT_A_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + WHEN("neuron ids are requested for an invalid timestep") { + auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } + } - WHEN("neuron ids are requested") { + WHEN("neuron ids are requested for an invalid attribute") { auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, - niv::testing::ANY_ATTRIBUTE)}; + niv::testing::NOT_AN_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } } - GIVEN("a multimeter providing access to some data") { + GIVEN("a multimeter with an incorrect name providing access to some data") { niv::consumer::ArborMultimeter multimeter( - niv::testing::ANY_MULTIMETER_NAME); + niv::testing::NOT_A_MULTIMETER_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - WHEN("neuron ids are requested for an invalid timestep") { - auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME, - niv::testing::ANY_ATTRIBUTE)}; - THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } - } - - WHEN("neuron ids are requested for an invalid attribute") { + WHEN("neuron ids are requested") { auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, - niv::testing::NOT_AN_ATTRIBUTE)}; + niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } } From cccb14319b68f37930aa81965998a7b76e73b887 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 11:33:28 +0100 Subject: [PATCH 29/82] Add consumer::ArborMultimeter::GetTimestepsString() --- niv/include/niv/consumer/arbor_multimeter.hpp | 3 ++ niv/include/niv/nest_test_data.hpp | 9 ++++++ niv/src/consumer/arbor_multimeter.cpp | 14 ++++++++- .../src/consumer/test_arbor_multimeter.cpp | 29 +++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 14529f3..b1d0222 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -40,6 +40,8 @@ class ArborMultimeter : public niv::consumer::Device { void Update() override; + std::vector GetTimestepsString() const; + std::vector GetNeuronIds(double time, const std::string& attribute) const; double GetDatum(double time, const std::string& attribute, @@ -52,6 +54,7 @@ class ArborMultimeter : public niv::consumer::Device { std::string ConstructPath(double time, const std::string& attribute, const std::string& neuron_id) const; std::string ConstructPath(double time, const std::string& attribute) const; + std::string ConstructPath() const; const conduit::Node* GetNode(const std::string& path) const; diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index c3ae29e..86c3796 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -51,6 +51,15 @@ static const char* ANY_MULTIMETER_NAME{"multimeter A"}; static const char* NOT_A_MULTIMETER_NAME{"NOT_A_MULTIMETER_NAME"}; static const std::vector ANY_TIMES{0.1, 0.2, 0.3}; +inline std::vector AnyTimesString() { + std::vector retval; + for (auto time : ANY_TIMES) { + std::stringstream s; + s << time; + retval.push_back(s.str()); + } + return retval; +} static const double ANY_TIME{ANY_TIMES[0]}; static const double ANOTHER_TIME{ANY_TIMES[1]}; static const double THIRD_TIME{ANY_TIMES[2]}; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 7752879..956e11e 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -36,6 +36,12 @@ ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} void ArborMultimeter::Update() {} +std::vector ArborMultimeter::GetTimestepsString() const { + const std::string path{ConstructPath()}; + const conduit::Node* node{GetNode(path)}; + return GetChildNames(node); +} + std::vector ArborMultimeter::GetNeuronIds( double time, const std::string& attribute) const { const std::string path{ConstructPath(time, attribute)}; @@ -62,12 +68,18 @@ std::string ArborMultimeter::ConstructPath(double time, std::string ArborMultimeter::ConstructPath(double time, const std::string& attribute) const { std::stringstream path; - path << GetName() << "/"; + path << ConstructPath() << "/"; path << time << "/"; path << attribute; return path.str(); } +std::string ArborMultimeter::ConstructPath() const { + std::stringstream path; + path << GetName(); + return path.str(); +} + const conduit::Node* ArborMultimeter::GetNode(const std::string& path) const { const conduit::Node* node{nullptr}; try { diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 69aeb89..5d061c6 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -24,6 +24,35 @@ #include "niv/consumer/arbor_multimeter.hpp" #include "niv/nest_test_data.hpp" +SCENARIO("ArborMultimeter lists the timesteps", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("timesteps are requested") { + auto timesteps{multimeter.GetTimestepsString()}; + THEN("they are correct") { + REQUIRE(timesteps == niv::testing::AnyTimesString()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("timesteps are requested") { + auto timesteps{multimeter.GetTimestepsString()}; + THEN("the multimeter does not provide timesteps") { + REQUIRE(timesteps.empty()); + } + } + } +} + SCENARIO( "ArborMultimeter lists the neuron ids stored for an attribute in a " "timestep", From e4d73a5eb4416f36e989ad3cff0723b86399a1d6 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 11:35:01 +0100 Subject: [PATCH 30/82] Clean-up tests for consumer::ArborMultimeter::GetTimestepsString() --- niv/tests/src/consumer/test_arbor_multimeter.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 5d061c6..b7498d8 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -31,11 +31,9 @@ SCENARIO("ArborMultimeter lists the timesteps", niv::testing::ANY_MULTIMETER_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - WHEN("timesteps are requested") { - auto timesteps{multimeter.GetTimestepsString()}; - THEN("they are correct") { - REQUIRE(timesteps == niv::testing::AnyTimesString()); - } + THEN("the multimeter provides correct timesteps") { + REQUIRE(multimeter.GetTimestepsString() == + niv::testing::AnyTimesString()); } } @@ -44,11 +42,8 @@ SCENARIO("ArborMultimeter lists the timesteps", niv::testing::NOT_A_MULTIMETER_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - WHEN("timesteps are requested") { - auto timesteps{multimeter.GetTimestepsString()}; - THEN("the multimeter does not provide timesteps") { - REQUIRE(timesteps.empty()); - } + THEN("the multimeter does not provide timesteps") { + REQUIRE(multimeter.GetTimestepsString().empty()); } } } From 1bd5919703f9bce700b5e1e3a04a10b52084f51c Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 11:44:17 +0100 Subject: [PATCH 31/82] Add consumer::ArborMultimeter::GetAttributes() --- niv/include/niv/consumer/arbor_multimeter.hpp | 3 ++ niv/src/consumer/arbor_multimeter.cpp | 19 ++++++---- .../src/consumer/test_arbor_multimeter.cpp | 36 +++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index b1d0222..247121a 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -42,6 +42,8 @@ class ArborMultimeter : public niv::consumer::Device { std::vector GetTimestepsString() const; + std::vector GetAttributes(double time) const; + std::vector GetNeuronIds(double time, const std::string& attribute) const; double GetDatum(double time, const std::string& attribute, @@ -54,6 +56,7 @@ class ArborMultimeter : public niv::consumer::Device { std::string ConstructPath(double time, const std::string& attribute, const std::string& neuron_id) const; std::string ConstructPath(double time, const std::string& attribute) const; + std::string ConstructPath(double time) const; std::string ConstructPath() const; const conduit::Node* GetNode(const std::string& path) const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 956e11e..8b417fe 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -42,6 +42,12 @@ std::vector ArborMultimeter::GetTimestepsString() const { return GetChildNames(node); } +std::vector ArborMultimeter::GetAttributes(double time) const { + const std::string path{ConstructPath(time)}; + const conduit::Node* node{GetNode(path)}; + return GetChildNames(node); +} + std::vector ArborMultimeter::GetNeuronIds( double time, const std::string& attribute) const { const std::string path{ConstructPath(time, attribute)}; @@ -60,26 +66,25 @@ std::string ArborMultimeter::ConstructPath(double time, const std::string& attribute, const std::string& neuron_id) const { std::stringstream path; - path << ConstructPath(time, attribute) << "/"; - path << neuron_id; + path << ConstructPath(time, attribute) << "/" << neuron_id; return path.str(); } std::string ArborMultimeter::ConstructPath(double time, const std::string& attribute) const { std::stringstream path; - path << ConstructPath() << "/"; - path << time << "/"; - path << attribute; + path << ConstructPath(time) << "/" << attribute; return path.str(); } -std::string ArborMultimeter::ConstructPath() const { +std::string ArborMultimeter::ConstructPath(double time) const { std::stringstream path; - path << GetName(); + path << ConstructPath() << "/" << time; return path.str(); } +std::string ArborMultimeter::ConstructPath() const { return GetName(); } + const conduit::Node* ArborMultimeter::GetNode(const std::string& path) const { const conduit::Node* node{nullptr}; try { diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index b7498d8..cd7abbb 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -48,6 +48,42 @@ SCENARIO("ArborMultimeter lists the timesteps", } } +SCENARIO("ArborMultimeter lists attributes for a timestep", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("attributes are requested") { + auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME)}; + THEN("the multimeter provides the attributes") { + REQUIRE(attributes == niv::testing::ANY_ATTRIBUTES); + } + } + + WHEN("attributes are requested for an invalid timestep") { + auto attributes{multimeter.GetAttributes(niv::testing::NOT_A_TIME)}; + THEN("the multimeter does not provide attributes") { + REQUIRE(attributes.empty()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("attributes are requested") { + auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME)}; + THEN("the multimeter does not provide attributes") { + REQUIRE(attributes.empty()); + } + } + } +} + SCENARIO( "ArborMultimeter lists the neuron ids stored for an attribute in a " "timestep", From 2afdedbba52efe277536ab6432baa4c5d24a5b92 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 11:51:24 +0100 Subject: [PATCH 32/82] Refactor consumer::ArborMultimeter --- niv/include/niv/consumer/arbor_multimeter.hpp | 6 +-- niv/src/consumer/arbor_multimeter.cpp | 42 +++++++------------ 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 247121a..0af2b97 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -59,10 +59,10 @@ class ArborMultimeter : public niv::consumer::Device { std::string ConstructPath(double time) const; std::string ConstructPath() const; - const conduit::Node* GetNode(const std::string& path) const; + std::vector GetChildNames(const std::string& path) const; + double GetValue(const std::string& path) const; - static std::vector GetChildNames(const conduit::Node* node); - static double GetValue(const conduit::Node* node); + const conduit::Node* GetNode(const std::string& path) const; }; } // namespace consumer diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 8b417fe..15ed555 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -37,29 +37,21 @@ ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} void ArborMultimeter::Update() {} std::vector ArborMultimeter::GetTimestepsString() const { - const std::string path{ConstructPath()}; - const conduit::Node* node{GetNode(path)}; - return GetChildNames(node); + return GetChildNames(ConstructPath()); } std::vector ArborMultimeter::GetAttributes(double time) const { - const std::string path{ConstructPath(time)}; - const conduit::Node* node{GetNode(path)}; - return GetChildNames(node); + return GetChildNames(ConstructPath(time)); } std::vector ArborMultimeter::GetNeuronIds( double time, const std::string& attribute) const { - const std::string path{ConstructPath(time, attribute)}; - const conduit::Node* node{GetNode(path)}; - return GetChildNames(node); + return GetChildNames(ConstructPath(time, attribute)); } double ArborMultimeter::GetDatum(double time, const std::string& attribute, const std::string& neuron_id) const { - const std::string path{ConstructPath(time, attribute, neuron_id)}; - const conduit::Node* node{GetNode(path)}; - return GetValue(node); + return GetValue(ConstructPath(time, attribute, neuron_id)); } std::string ArborMultimeter::ConstructPath(double time, @@ -85,6 +77,17 @@ std::string ArborMultimeter::ConstructPath(double time) const { std::string ArborMultimeter::ConstructPath() const { return GetName(); } +std::vector ArborMultimeter::GetChildNames( + const std::string& path) const { + const conduit::Node* node{GetNode(path)}; + return (node != nullptr) ? node->child_names() : std::vector(); +} + +double ArborMultimeter::GetValue(const std::string& path) const { + const conduit::Node* node{GetNode(path)}; + return (node != nullptr) ? node->as_double() : std::nan(""); +} + const conduit::Node* ArborMultimeter::GetNode(const std::string& path) const { const conduit::Node* node{nullptr}; try { @@ -94,20 +97,5 @@ const conduit::Node* ArborMultimeter::GetNode(const std::string& path) const { return node; } -std::vector ArborMultimeter::GetChildNames( - const conduit::Node* node) { - if (node == nullptr) { - return std::vector(); - } - return node->child_names(); -} - -double ArborMultimeter::GetValue(const conduit::Node* node) { - if (node == nullptr) { - return std::nan(""); - } - return node->as_double(); -} - } // namespace consumer } // namespace niv From b099a3556419fc628824f80e92fa53dd11c2c75e Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Feb 2018 12:44:30 +0100 Subject: [PATCH 33/82] Add consumer::ArborMultimeter::GetTimeSeries() --- niv/include/niv/consumer/arbor_multimeter.hpp | 8 ++ niv/include/niv/nest_test_data.hpp | 3 + niv/src/consumer/arbor_multimeter.cpp | 24 +++++ .../src/consumer/test_arbor_multimeter.cpp | 93 ++++++++++++++++++- 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 0af2b97..cc9d2ab 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -46,13 +46,21 @@ class ArborMultimeter : public niv::consumer::Device { std::vector GetNeuronIds(double time, const std::string& attribute) const; + std::vector GetTimeSeries(const std::string& attribute, + const std::string& neuron_id) const; + double GetDatum(double time, const std::string& attribute, const std::string& neuron_id) const; + double GetDatum(const std::string& time, const std::string& attribute, + const std::string& neuron_id) const; ArborMultimeter& operator=(const ArborMultimeter&) = default; ArborMultimeter& operator=(ArborMultimeter&&) = default; private: + std::string ConstructPath(const std::string& time, + const std::string& attribute, + const std::string& neuron_id) const; std::string ConstructPath(double time, const std::string& attribute, const std::string& neuron_id) const; std::string ConstructPath(double time, const std::string& attribute) const; diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index 86c3796..c88af5d 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -89,6 +89,9 @@ static const std::vector ANY_VALUES{ 0.311, 0.312, 0.313, 0.321, 0.322, 0.323, 0.331, 0.332, 0.333}; // clang-format on static const double ANY_VALUE{ANY_VALUES[0]}; +static const std::size_t TIME_STRIDE{9}; +static const std::size_t ATTRIBUTE_STRIDE{3}; +static const std::size_t ID_STRIDE{1}; template inline std::string OpenTag(T tag) { diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 15ed555..8f52676 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -49,11 +49,29 @@ std::vector ArborMultimeter::GetNeuronIds( return GetChildNames(ConstructPath(time, attribute)); } +std::vector ArborMultimeter::GetTimeSeries( + const std::string& attribute, const std::string& neuron_id) const { + std::vector retval; + const auto timesteps = GetTimestepsString(); + retval.reserve(timesteps.size()); + for (auto time : timesteps) { + retval.push_back(GetDatum(time, attribute, neuron_id)); + } + return retval; +} + double ArborMultimeter::GetDatum(double time, const std::string& attribute, const std::string& neuron_id) const { return GetValue(ConstructPath(time, attribute, neuron_id)); } +double ArborMultimeter::GetDatum(const std::string& time, + const std::string& attribute, + const std::string& neuron_id) const { + std::cout << ConstructPath(time, attribute, neuron_id) << std::endl; + return GetValue(ConstructPath(time, attribute, neuron_id)); +} + std::string ArborMultimeter::ConstructPath(double time, const std::string& attribute, const std::string& neuron_id) const { @@ -62,6 +80,12 @@ std::string ArborMultimeter::ConstructPath(double time, return path.str(); } +std::string ArborMultimeter::ConstructPath(const std::string& time, + const std::string& attribute, + const std::string& neuron_id) const { + return ConstructPath() + "/" + time + "/" + attribute + "/" + neuron_id; +} + std::string ArborMultimeter::ConstructPath(double time, const std::string& attribute) const { std::stringstream path; diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index cd7abbb..3225f7b 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -19,11 +19,34 @@ // limitations under the License. //------------------------------------------------------------------------------ +#include +#include + #include "catch/Catch.hpp" #include "niv/consumer/arbor_multimeter.hpp" #include "niv/nest_test_data.hpp" +namespace Catch { +namespace Matchers { + +class VectorAllNan : public Catch::MatcherBase> { + public: + bool match(const std::vector& values) const override { + bool retval = true; + for (double v : values) { + retval &= std::isnan(v); + } + return retval; + } + std::string describe() const override { return ""; } +}; + +} // namespace Matchers +} // namespace Catch + +using Catch::Matchers::VectorAllNan; + SCENARIO("ArborMultimeter lists the timesteps", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { GIVEN("a multimeter providing access to some data") { @@ -139,9 +162,10 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID); THEN("it is correct") { - const std::size_t ANY_TIME_OFFSET{0 * 9}; - const std::size_t ANOTHER_ATTRIBUTE_OFFSET{1 * 3}; - const std::size_t THIRD_ID_OFFSET{2}; + const std::size_t ANY_TIME_OFFSET{0 * niv::testing::TIME_STRIDE}; + const std::size_t ANOTHER_ATTRIBUTE_OFFSET{ + 1 * niv::testing::ATTRIBUTE_STRIDE}; + const std::size_t THIRD_ID_OFFSET{2 * niv::testing::ID_STRIDE}; const std::size_t DATUM_OFFSET{ ANY_TIME_OFFSET + ANOTHER_ATTRIBUTE_OFFSET + THIRD_ID_OFFSET}; REQUIRE(datum == Approx(niv::testing::ANY_VALUES[DATUM_OFFSET])); @@ -170,3 +194,66 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", } } } + +SCENARIO("ArborMultimeter provides time series data", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + std::vector expected; + for (std::size_t i = 0; i < niv::testing::ANY_TIMES.size(); ++i) { + const auto TIME_OFFSET{i * niv::testing::TIME_STRIDE}; + const auto ATTRIBUTE_OFFSET{1 * niv::testing::ATTRIBUTE_STRIDE}; + const auto ID_OFFSET{2 * niv::testing::ID_STRIDE}; + const auto DATUM_INDEX{TIME_OFFSET + ATTRIBUTE_OFFSET + ID_OFFSET}; + expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + } + const std::vector nans(niv::testing::ANY_TIMES.size(), std::nan("")); + + GIVEN("a multimeter providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time series data for an attribute and a neuron id") { + const std::vector values{multimeter.GetTimeSeries( + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID)}; + + THEN("the time series is correct") { REQUIRE(values == expected); } + } + + WHEN( + "requesting time series data for an invalid attribute and a neuron " + "id") { + const std::vector values{multimeter.GetTimeSeries( + niv::testing::NOT_AN_ATTRIBUTE, niv::testing::THIRD_ID)}; + + THEN("the time series is all nans") { + REQUIRE_THAT(values, VectorAllNan()); + } + } + + WHEN( + "requesting time series data for an attribute and an invalid neuron " + "id") { + const std::vector values{multimeter.GetTimeSeries( + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::NOT_AN_ID)}; + + THEN("the time series is all nans") { + REQUIRE_THAT(values, VectorAllNan()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time series data for an attribute and a neuron id") { + const std::vector values{multimeter.GetTimeSeries( + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID)}; + + THEN("the time series is all nans") { + REQUIRE_THAT(values, VectorAllNan()); + } + } + } +} From c47d84465a35206a1bd436ba4bd745806b9ad3fc Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 13 Mar 2018 17:26:32 +0100 Subject: [PATCH 34/82] Add consumer::ArborMultimeter::GetTimestepData() --- niv/include/niv/consumer/arbor_multimeter.hpp | 8 +- niv/src/consumer/arbor_multimeter.cpp | 13 ++- .../src/consumer/test_arbor_multimeter.cpp | 83 ++++++++++++++++--- 3 files changed, 88 insertions(+), 16 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index cc9d2ab..db3253a 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -46,8 +46,12 @@ class ArborMultimeter : public niv::consumer::Device { std::vector GetNeuronIds(double time, const std::string& attribute) const; - std::vector GetTimeSeries(const std::string& attribute, - const std::string& neuron_id) const; + + std::vector GetTimestepData(double time, + const std::string& attribute) const; + + std::vector GetTimeSeriesData(const std::string& attribute, + const std::string& neuron_id) const; double GetDatum(double time, const std::string& attribute, const std::string& neuron_id) const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 8f52676..b03f62b 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -49,7 +49,17 @@ std::vector ArborMultimeter::GetNeuronIds( return GetChildNames(ConstructPath(time, attribute)); } -std::vector ArborMultimeter::GetTimeSeries( +std::vector ArborMultimeter::GetTimestepData( + double time, const std::string& attribute) const { + std::vector retval; + const auto neuron_ids{GetNeuronIds(time, attribute)}; + for (auto curr_neuron_id : neuron_ids) { + retval.push_back(GetDatum(time, attribute, curr_neuron_id)); + } + return retval; +} + +std::vector ArborMultimeter::GetTimeSeriesData( const std::string& attribute, const std::string& neuron_id) const { std::vector retval; const auto timesteps = GetTimestepsString(); @@ -68,7 +78,6 @@ double ArborMultimeter::GetDatum(double time, const std::string& attribute, double ArborMultimeter::GetDatum(const std::string& time, const std::string& attribute, const std::string& neuron_id) const { - std::cout << ConstructPath(time, attribute, neuron_id) << std::endl; return GetValue(ConstructPath(time, attribute, neuron_id)); } diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 3225f7b..4138b22 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -30,7 +30,7 @@ namespace Catch { namespace Matchers { -class VectorAllNan : public Catch::MatcherBase> { +class VectorAllNanOrEmpty : public Catch::MatcherBase> { public: bool match(const std::vector& values) const override { bool retval = true; @@ -45,7 +45,7 @@ class VectorAllNan : public Catch::MatcherBase> { } // namespace Matchers } // namespace Catch -using Catch::Matchers::VectorAllNan; +using Catch::Matchers::VectorAllNanOrEmpty; SCENARIO("ArborMultimeter lists the timesteps", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { @@ -213,7 +213,7 @@ SCENARIO("ArborMultimeter provides time series data", multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("requesting time series data for an attribute and a neuron id") { - const std::vector values{multimeter.GetTimeSeries( + const std::vector values{multimeter.GetTimeSeriesData( niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID)}; THEN("the time series is correct") { REQUIRE(values == expected); } @@ -222,22 +222,22 @@ SCENARIO("ArborMultimeter provides time series data", WHEN( "requesting time series data for an invalid attribute and a neuron " "id") { - const std::vector values{multimeter.GetTimeSeries( + const std::vector values{multimeter.GetTimeSeriesData( niv::testing::NOT_AN_ATTRIBUTE, niv::testing::THIRD_ID)}; - THEN("the time series is all nans") { - REQUIRE_THAT(values, VectorAllNan()); + THEN("the time series is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); } } WHEN( "requesting time series data for an attribute and an invalid neuron " "id") { - const std::vector values{multimeter.GetTimeSeries( + const std::vector values{multimeter.GetTimeSeriesData( niv::testing::ANOTHER_ATTRIBUTE, niv::testing::NOT_AN_ID)}; - THEN("the time series is all nans") { - REQUIRE_THAT(values, VectorAllNan()); + THEN("the time series is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); } } } @@ -248,11 +248,70 @@ SCENARIO("ArborMultimeter provides time series data", multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("requesting time series data for an attribute and a neuron id") { - const std::vector values{multimeter.GetTimeSeries( + const std::vector values{multimeter.GetTimeSeriesData( niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID)}; - THEN("the time series is all nans") { - REQUIRE_THAT(values, VectorAllNan()); + THEN("the time series is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + } +} + +SCENARIO("ArborMultimeter provides time step data for all neurons", + "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { + std::vector expected; + const auto THIRD_TIME{niv::testing::THIRD_TIME}; + const auto TIME_OFFSET{2 * niv::testing::TIME_STRIDE}; + const auto ATTRIBUTE_OFFSET{1 * niv::testing::ATTRIBUTE_STRIDE}; + for (std::size_t i = 0; i < niv::testing::ANY_IDS.size(); ++i) { + const auto ID_OFFSET{i * niv::testing::ID_STRIDE}; + const auto DATUM_INDEX{TIME_OFFSET + ATTRIBUTE_OFFSET + ID_OFFSET}; + expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + } + + GIVEN("a multimeter providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time step data for an attribute") { + const std::vector values{multimeter.GetTimestepData( + THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + + THEN("the time step data is correct") { REQUIRE(values == expected); } + } + + WHEN("requesting time step data for an invalid time step") { + const std::vector values{multimeter.GetTimestepData( + niv::testing::NOT_A_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + + THEN("the time step data is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + + WHEN("requesting time step data for an invalid attribute") { + const std::vector values{multimeter.GetTimestepData( + THIRD_TIME, niv::testing::NOT_AN_ATTRIBUTE)}; + + THEN("the time step data is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time step data for an attribute") { + const std::vector values{multimeter.GetTimestepData( + THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + + THEN("the time step data is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); } } } From 999b11f3f02c75167f6775faba6a59b6c6e00626 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 13 Mar 2018 17:59:11 +0100 Subject: [PATCH 35/82] Rename consumer::Multimeter to consumer::NestMultimeter --- demo/arbor_miniapp-niv/dump_to_stdout.py | 2 +- demo/brunel_example/dump_to_stdout.py | 2 +- demo/brunel_example/nest_python_vis.py | 2 +- demo/nest_python_vis/nest_python_vis.py | 4 ++-- .../{multimeter.hpp => nest_multimeter.hpp} | 22 +++++++++---------- .../{multimeter.cpp => nest_multimeter.cpp} | 13 ++++++----- niv/tests/src/consumer/test_integration.cpp | 4 ++-- ...ultimeter.cpp => test_nest_multimeter.cpp} | 4 ++-- pyniv/src/consumer/consumer.cpp | 4 ++-- .../{multimeter.cpp => nest_multimeter.cpp} | 18 +++++++-------- pyniv/tests/src/consumer/test_integration.py | 2 +- pyniv/tests/src/consumer/test_multimeter.py | 2 +- 12 files changed, 40 insertions(+), 39 deletions(-) rename niv/include/niv/consumer/{multimeter.hpp => nest_multimeter.hpp} (72%) rename niv/src/consumer/{multimeter.cpp => nest_multimeter.cpp} (81%) rename niv/tests/src/consumer/{test_multimeter.cpp => test_nest_multimeter.cpp} (96%) rename pyniv/src/consumer/{multimeter.cpp => nest_multimeter.cpp} (77%) diff --git a/demo/arbor_miniapp-niv/dump_to_stdout.py b/demo/arbor_miniapp-niv/dump_to_stdout.py index cc8084e..5e2a1c4 100644 --- a/demo/arbor_miniapp-niv/dump_to_stdout.py +++ b/demo/arbor_miniapp-niv/dump_to_stdout.py @@ -39,7 +39,7 @@ def __init__(self): def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - self.multimeter = pyniv.consumer.Multimeter("multimeter") + self.multimeter = pyniv.consumer.NestMultimeter("multimeter") self.multimeter.SetAttribute("v") self.backend = pyniv.consumer.Backend(); diff --git a/demo/brunel_example/dump_to_stdout.py b/demo/brunel_example/dump_to_stdout.py index 2d4a4ae..65c1443 100644 --- a/demo/brunel_example/dump_to_stdout.py +++ b/demo/brunel_example/dump_to_stdout.py @@ -39,7 +39,7 @@ def __init__(self): def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - self.multimeter = pyniv.consumer.Multimeter("recordingNode51") + self.multimeter = pyniv.consumer.NestMultimeter("recordingNode51") self.multimeter.SetAttribute("V_m") self.backend = pyniv.consumer.Backend(); diff --git a/demo/brunel_example/nest_python_vis.py b/demo/brunel_example/nest_python_vis.py index 7602051..58e0f1b 100644 --- a/demo/brunel_example/nest_python_vis.py +++ b/demo/brunel_example/nest_python_vis.py @@ -40,7 +40,7 @@ def __init__(self): def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - self.multimeter = pyniv.consumer.Multimeter("recordingNode51") + self.multimeter = pyniv.consumer.NestMultimeter("recordingNode51") self.multimeter.SetAttribute("V_m") self.backend = pyniv.consumer.Backend(); diff --git a/demo/nest_python_vis/nest_python_vis.py b/demo/nest_python_vis/nest_python_vis.py index 4d48750..30da077 100644 --- a/demo/nest_python_vis/nest_python_vis.py +++ b/demo/nest_python_vis/nest_python_vis.py @@ -40,10 +40,10 @@ def __init__(self): def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - self.multimeter_a = pyniv.consumer.Multimeter("multimeter A") + self.multimeter_a = pyniv.consumer.NestMultimeter("multimeter A") self.multimeter_a.SetAttribute("V_m") - self.multimeter_b = pyniv.consumer.Multimeter("multimeter B") + self.multimeter_b = pyniv.consumer.NestMultimeter("multimeter B") self.multimeter_b.SetAttribute("V_m") self.backend = pyniv.consumer.Backend(); diff --git a/niv/include/niv/consumer/multimeter.hpp b/niv/include/niv/consumer/nest_multimeter.hpp similarity index 72% rename from niv/include/niv/consumer/multimeter.hpp rename to niv/include/niv/consumer/nest_multimeter.hpp index cf72564..41fd408 100644 --- a/niv/include/niv/consumer/multimeter.hpp +++ b/niv/include/niv/consumer/nest_multimeter.hpp @@ -19,8 +19,8 @@ // limitations under the License. //------------------------------------------------------------------------------ -#ifndef NIV_INCLUDE_NIV_CONSUMER_MULTIMETER_HPP_ -#define NIV_INCLUDE_NIV_CONSUMER_MULTIMETER_HPP_ +#ifndef NIV_INCLUDE_NIV_CONSUMER_NEST_MULTIMETER_HPP_ +#define NIV_INCLUDE_NIV_CONSUMER_NEST_MULTIMETER_HPP_ #include #include @@ -32,16 +32,16 @@ namespace niv { namespace consumer { -class Multimeter : public consumer::Device { +class NestMultimeter : public consumer::Device { public: - Multimeter() = delete; - explicit Multimeter(const std::string& name); - Multimeter(const Multimeter&) = default; - Multimeter(Multimeter&&) = default; - ~Multimeter() = default; + NestMultimeter() = delete; + explicit NestMultimeter(const std::string& name); + NestMultimeter(const NestMultimeter&) = default; + NestMultimeter(NestMultimeter&&) = default; + ~NestMultimeter() = default; - Multimeter& operator=(const Multimeter&) = default; - Multimeter& operator=(Multimeter&&) = default; + NestMultimeter& operator=(const NestMultimeter&) = default; + NestMultimeter& operator=(NestMultimeter&&) = default; void SetAttribute(const std::string& attribute); @@ -59,4 +59,4 @@ class Multimeter : public consumer::Device { } // namespace consumer } // namespace niv -#endif // NIV_INCLUDE_NIV_CONSUMER_MULTIMETER_HPP_ +#endif // NIV_INCLUDE_NIV_CONSUMER_NEST_MULTIMETER_HPP_ diff --git a/niv/src/consumer/multimeter.cpp b/niv/src/consumer/nest_multimeter.cpp similarity index 81% rename from niv/src/consumer/multimeter.cpp rename to niv/src/consumer/nest_multimeter.cpp index 924b62b..1e4df39 100644 --- a/niv/src/consumer/multimeter.cpp +++ b/niv/src/consumer/nest_multimeter.cpp @@ -19,7 +19,7 @@ // limitations under the License. //------------------------------------------------------------------------------ -#include "niv/consumer/multimeter.hpp" +#include "niv/consumer/nest_multimeter.hpp" #include #include @@ -27,18 +27,19 @@ namespace niv { namespace consumer { -Multimeter::Multimeter(const std::string& name) : consumer::Device{name} {} +NestMultimeter::NestMultimeter(const std::string& name) + : consumer::Device{name} {} -void Multimeter::SetAttribute(const std::string& attribute) { +void NestMultimeter::SetAttribute(const std::string& attribute) { attribute_ = attribute; } -void Multimeter::Update() { +void NestMultimeter::Update() { SetTimestepNode(); SetValues(); } -void Multimeter::SetValues() { +void NestMultimeter::SetValues() { values_.clear(); if (GetTimestepNode() == nullptr) { return; @@ -53,7 +54,7 @@ void Multimeter::SetValues() { } } -const std::vector& Multimeter::GetValues() const { return values_; } +const std::vector& NestMultimeter::GetValues() const { return values_; } } // namespace consumer } // namespace niv diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index aca8b1f..9f769a0 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -24,7 +24,7 @@ #include "catch/catch.hpp" #include "niv/consumer/backend.hpp" -#include "niv/consumer/multimeter.hpp" +#include "niv/consumer/nest_multimeter.hpp" #include "niv/consumer/receiver.hpp" #include "niv/nest_test_data.hpp" @@ -35,7 +35,7 @@ SCENARIO("Consumer integration", "[niv][integration]") { niv::consumer::Receiver receiver; backend.Connect(&receiver); - niv::consumer::Multimeter multimeter(niv::testing::AnyMultimeterName()); + niv::consumer::NestMultimeter multimeter(niv::testing::AnyMultimeterName()); multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); backend.Connect(&multimeter); diff --git a/niv/tests/src/consumer/test_multimeter.cpp b/niv/tests/src/consumer/test_nest_multimeter.cpp similarity index 96% rename from niv/tests/src/consumer/test_multimeter.cpp rename to niv/tests/src/consumer/test_nest_multimeter.cpp index 7147c31..1c433ce 100644 --- a/niv/tests/src/consumer/test_multimeter.cpp +++ b/niv/tests/src/consumer/test_nest_multimeter.cpp @@ -25,14 +25,14 @@ #include "conduit/conduit_node.hpp" -#include "niv/consumer/multimeter.hpp" +#include "niv/consumer/nest_multimeter.hpp" #include "niv/nest_test_data.hpp" SCENARIO("a Multimeter provides access to data stored in a conduit node", "[niv][niv::consumer][niv::consumer::Multimeter]") { GIVEN("A Multimeter with some data") { const conduit::Node nest_data{niv::testing::AnyNestData()}; - niv::consumer::Multimeter multimeter(niv::testing::AnyMultimeterName()); + niv::consumer::NestMultimeter multimeter(niv::testing::AnyMultimeterName()); multimeter.SetNode(&nest_data); WHEN("The time step is set") { diff --git a/pyniv/src/consumer/consumer.cpp b/pyniv/src/consumer/consumer.cpp index 01149e5..a27293f 100644 --- a/pyniv/src/consumer/consumer.cpp +++ b/pyniv/src/consumer/consumer.cpp @@ -23,7 +23,7 @@ #include "niv/consumer/backend.hpp" #include "niv/consumer/device.hpp" -#include "niv/consumer/multimeter.hpp" +#include "niv/consumer/nest_multimeter.hpp" #include "niv/consumer/receiver.hpp" namespace pyniv { @@ -32,7 +32,7 @@ BOOST_PYTHON_MODULE(_consumer) { pyniv::expose(); pyniv::expose(); pyniv::expose(); - pyniv::expose(); + pyniv::expose(); } } // namespace pyniv diff --git a/pyniv/src/consumer/multimeter.cpp b/pyniv/src/consumer/nest_multimeter.cpp similarity index 77% rename from pyniv/src/consumer/multimeter.cpp rename to pyniv/src/consumer/nest_multimeter.cpp index 39efc40..ee5a3cc 100644 --- a/pyniv/src/consumer/multimeter.cpp +++ b/pyniv/src/consumer/nest_multimeter.cpp @@ -30,15 +30,15 @@ SUPPRESS_WARNINGS_BEGIN SUPPRESS_WARNINGS_END #include "niv/consumer/device.hpp" -#include "niv/consumer/multimeter.hpp" +#include "niv/consumer/nest_multimeter.hpp" namespace pyniv { namespace consumer { boost::python::numpy::ndarray GetValues( - const niv::consumer::Multimeter& multimeter); + const niv::consumer::NestMultimeter& multimeter); boost::python::numpy::ndarray GetValues( - const niv::consumer::Multimeter& multimeter) { + const niv::consumer::NestMultimeter& multimeter) { const auto& values{multimeter.GetValues()}; return boost::python::numpy::from_data( @@ -50,13 +50,13 @@ boost::python::numpy::ndarray GetValues( } // namespace consumer template <> -void expose() { - class_>( - "Multimeter", init()) +void expose() { + class_>( + "NestMultimeter", init()) .def("GetValues", &pyniv::consumer::GetValues) - .def("SetAttribute", &niv::consumer::Multimeter::SetAttribute) - .def("Update", &niv::consumer::Multimeter::Update) - .def("Print", &niv::consumer::Multimeter::Print); + .def("SetAttribute", &niv::consumer::NestMultimeter::SetAttribute) + .def("Update", &niv::consumer::NestMultimeter::Update) + .def("Print", &niv::consumer::NestMultimeter::Print); } } // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index 4493007..032db38 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -29,7 +29,7 @@ def test_integration_consumer(): receiver = pyniv.consumer.Receiver() backend.Connect(receiver) - multimeter = pyniv.consumer.Multimeter(pyniv.testing.AnyMultimeterName()) + multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) backend.Connect(multimeter) diff --git a/pyniv/tests/src/consumer/test_multimeter.py b/pyniv/tests/src/consumer/test_multimeter.py index 4a10632..ae936c6 100644 --- a/pyniv/tests/src/consumer/test_multimeter.py +++ b/pyniv/tests/src/consumer/test_multimeter.py @@ -23,7 +23,7 @@ def test_multimeter_provides_access_to_data_stored_in_a_conduit_node(): nest_data = pyniv.testing.AnyNestData() - multimeter = pyniv.consumer.Multimeter(pyniv.testing.AnyMultimeterName()) + multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetNode(nest_data) multimeter.SetTime(pyniv.testing.ANY_TIME) From 76563647a2013e2ab53d882071985dd38f532713 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 13 Mar 2018 18:14:16 +0100 Subject: [PATCH 36/82] Rename producer::Multimeter to producer::NestMultimeter --- niv/include/niv/nest_test_data.hpp | 2 +- .../{multimeter.hpp => nest_multimeter.hpp} | 25 ++++++++++--------- niv/src/nest_test_data.cpp | 4 +-- .../{multimeter.cpp => nest_multimeter.cpp} | 22 ++++++++-------- niv/tests/src/producer/test_multimeter.cpp | 10 ++++---- 5 files changed, 32 insertions(+), 31 deletions(-) rename niv/include/niv/producer/{multimeter.hpp => nest_multimeter.hpp} (70%) rename niv/src/producer/{multimeter.cpp => nest_multimeter.cpp} (71%) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index c88af5d..4a146fb 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -25,7 +25,7 @@ #include #include -#include "niv/producer/multimeter.hpp" +#include "niv/producer/nest_multimeter.hpp" namespace niv { diff --git a/niv/include/niv/producer/multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp similarity index 70% rename from niv/include/niv/producer/multimeter.hpp rename to niv/include/niv/producer/nest_multimeter.hpp index ed4d5bb..08b4ed5 100644 --- a/niv/include/niv/producer/multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -19,8 +19,8 @@ // limitations under the License. //------------------------------------------------------------------------------ -#ifndef NIV_INCLUDE_NIV_PRODUCER_MULTIMETER_HPP_ -#define NIV_INCLUDE_NIV_PRODUCER_MULTIMETER_HPP_ +#ifndef NIV_INCLUDE_NIV_PRODUCER_NEST_MULTIMETER_HPP_ +#define NIV_INCLUDE_NIV_PRODUCER_NEST_MULTIMETER_HPP_ #include #include @@ -32,20 +32,21 @@ namespace niv { namespace producer { -class Multimeter final : public Device { +class NestMultimeter final : public Device { public: - Multimeter(const std::string& name, - const std::vector& value_names, conduit::Node* node); - Multimeter(const Multimeter&) = default; - Multimeter(Multimeter&&) = default; - virtual ~Multimeter() = default; + NestMultimeter(const std::string& name, + const std::vector& value_names, + conduit::Node* node); + NestMultimeter(const NestMultimeter&) = default; + NestMultimeter(NestMultimeter&&) = default; + virtual ~NestMultimeter() = default; void Record(std::size_t id, const std::vector& values) override; - Multimeter& operator=(const Multimeter&) = default; - Multimeter& operator=(Multimeter&&) = default; + NestMultimeter& operator=(const NestMultimeter&) = default; + NestMultimeter& operator=(NestMultimeter&&) = default; - static std::unique_ptr New( + static std::unique_ptr New( const std::string& name, const std::vector& value_names, conduit::Node* node); @@ -60,4 +61,4 @@ class Multimeter final : public Device { } // namespace producer } // namespace niv -#endif // NIV_INCLUDE_NIV_PRODUCER_MULTIMETER_HPP_ +#endif // NIV_INCLUDE_NIV_PRODUCER_NEST_MULTIMETER_HPP_ diff --git a/niv/src/nest_test_data.cpp b/niv/src/nest_test_data.cpp index 502557c..b7b66e2 100644 --- a/niv/src/nest_test_data.cpp +++ b/niv/src/nest_test_data.cpp @@ -61,8 +61,8 @@ std::string AnyMultimeterName() { return "multimeter A"; } conduit::Node AnyNestData() { conduit::Node node; - niv::producer::Multimeter multimeter(AnyMultimeterName(), AnyValueNames(), - &node); + niv::producer::NestMultimeter multimeter(AnyMultimeterName(), AnyValueNames(), + &node); multimeter.SetRecordingTime(ANY_TIME); for (auto i = 0u; i < AnyAttributesValues().size(); ++i) { multimeter.Record(i, std::vector{AnyAttributesValues()[i], diff --git a/niv/src/producer/multimeter.cpp b/niv/src/producer/nest_multimeter.cpp similarity index 71% rename from niv/src/producer/multimeter.cpp rename to niv/src/producer/nest_multimeter.cpp index 53f92e9..b26904b 100644 --- a/niv/src/producer/multimeter.cpp +++ b/niv/src/producer/nest_multimeter.cpp @@ -23,41 +23,41 @@ #include #include -#include "niv/producer/multimeter.hpp" +#include "niv/producer/nest_multimeter.hpp" namespace niv { namespace producer { -Multimeter::Multimeter(const std::string& name, - const std::vector& value_names, - conduit::Node* node) +NestMultimeter::NestMultimeter(const std::string& name, + const std::vector& value_names, + conduit::Node* node) : Device{name, node}, value_names_{value_names} {} -void Multimeter::Record(std::size_t id, const std::vector& values) { +void NestMultimeter::Record(std::size_t id, const std::vector& values) { const std::string id_string{IdString(id)}; for (std::size_t i = 0; i < value_names_.size(); ++i) { RecordValue(id_string, values, i); } } -void Multimeter::RecordValue(std::string id_string, - const std::vector values, - std::size_t value_index) { +void NestMultimeter::RecordValue(std::string id_string, + const std::vector values, + std::size_t value_index) { const std::string& value_name = value_names_[value_index]; const double value = values[value_index]; GetTimestepNode()[value_name][id_string] = value; } -std::string Multimeter::IdString(std::size_t id) const { +std::string NestMultimeter::IdString(std::size_t id) const { std::stringstream id_stream; id_stream << id; return id_stream.str(); } -std::unique_ptr Multimeter::New( +std::unique_ptr NestMultimeter::New( const std::string& name, const std::vector& value_names, conduit::Node* node) { - return std::make_unique(name, value_names, node); + return std::make_unique(name, value_names, node); } } // namespace producer diff --git a/niv/tests/src/producer/test_multimeter.cpp b/niv/tests/src/producer/test_multimeter.cpp index e36813d..86ee5e6 100644 --- a/niv/tests/src/producer/test_multimeter.cpp +++ b/niv/tests/src/producer/test_multimeter.cpp @@ -27,14 +27,14 @@ #include "conduit/conduit_node.hpp" -#include "niv/producer/multimeter.hpp" +#include "niv/producer/nest_multimeter.hpp" SCENARIO("A unique multimeter ptr can be constructed via its factory", "[niv][niv::Multimeter]") { WHEN("a new multimeter is constructed") { - std::unique_ptr multimeter{ - niv::producer::Multimeter::New("name", std::vector(), - nullptr)}; + std::unique_ptr multimeter{ + niv::producer::NestMultimeter::New("name", std::vector(), + nullptr)}; THEN("a pointer was obtained") { REQUIRE(multimeter.get() != nullptr); } } } @@ -50,7 +50,7 @@ SCENARIO("A multimeter records to a conduit node", "[niv][niv::Multimeter]") { GIVEN("a conduit node and a multimeter") { conduit::Node node; - niv::producer::Multimeter multimeter(any_name, any_value_names, &node); + niv::producer::NestMultimeter multimeter(any_name, any_value_names, &node); WHEN("setting the recording time") { multimeter.SetRecordingTime(any_time); From 1093dffb04d76d9923e68e806833ba31c04b8f9c Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 07:45:16 +0100 Subject: [PATCH 37/82] Refine and export test data --- niv/include/niv/nest_test_data.hpp | 15 +++++++++++---- pyniv/src/testing/__init__.py | 11 +++++++++++ pyniv/src/testing/nest_test_data.cpp | 28 ++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index 4a146fb..c72e4ee 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -51,6 +51,11 @@ static const char* ANY_MULTIMETER_NAME{"multimeter A"}; static const char* NOT_A_MULTIMETER_NAME{"NOT_A_MULTIMETER_NAME"}; static const std::vector ANY_TIMES{0.1, 0.2, 0.3}; +static const double ANY_TIME{ANY_TIMES[0]}; +static const double ANOTHER_TIME{ANY_TIMES[1]}; +static const double THIRD_TIME{ANY_TIMES[2]}; +static const double NOT_A_TIME{ANY_TIMES.back() + 1.0}; + inline std::vector AnyTimesString() { std::vector retval; for (auto time : ANY_TIMES) { @@ -60,10 +65,12 @@ inline std::vector AnyTimesString() { } return retval; } -static const double ANY_TIME{ANY_TIMES[0]}; -static const double ANOTHER_TIME{ANY_TIMES[1]}; -static const double THIRD_TIME{ANY_TIMES[2]}; -static const double NOT_A_TIME{ANY_TIMES.back() + 1.0}; +static const std::vector ANY_TIMES_STRING{ + AnyTimesString()[0], AnyTimesString()[1], AnyTimesString()[2]}; +static const char* ANY_TIME_STRING{ANY_TIMES_STRING[0].c_str()}; +static const char* ANOTHER_TIME_STRING{ANY_TIMES_STRING[1].c_str()}; +static const char* THIRD_TIME_STRING{ANY_TIMES_STRING[2].c_str()}; +static const char* NOT_A_TIME_STRING{"NOT_A_TIME"}; static const std::vector ANY_TIME_OFFSETS{0.0123, 0.0234, 0.0345}; static const double ANY_TIME_OFFSET{ANY_TIME_OFFSETS[0]}; diff --git a/pyniv/src/testing/__init__.py b/pyniv/src/testing/__init__.py index 47b82d6..782902b 100644 --- a/pyniv/src/testing/__init__.py +++ b/pyniv/src/testing/__init__.py @@ -20,3 +20,14 @@ #------------------------------------------------------------------------------- from _testing import * + +import numpy as np + +ANY_TIMES = [ANY_TIME, ANOTHER_TIME, THIRD_TIME]; +ANY_TIMES_STRING = [ANY_TIME_STRING, ANOTHER_TIME_STRING, THIRD_TIME_STRING]; +ANY_ATTRIBUTES = [ANY_ATTRIBUTE, ANOTHER_ATTRIBUTE, THIRD_ATTRIBUTE]; +ANY_IDS = [ANY_ID, ANOTHER_ID, THIRD_ID]; +ANY_VALUES = np.array([ + 0.111, 0.112, 0.113, 0.121, 0.122, 0.123, 0.131, 0.132, 0.133, + 0.211, 0.212, 0.213, 0.221, 0.222, 0.223, 0.231, 0.232, 0.233, + 0.311, 0.312, 0.313, 0.321, 0.322, 0.323, 0.331, 0.332, 0.333]) diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 28c3d0a..05e9d96 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -82,12 +82,36 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(AnyAttributesValuesOverloads, template <> void expose() { + EXPOSE_CONSTANT(ANY_MULTIMETER_NAME); + EXPOSE_CONSTANT(NOT_A_MULTIMETER_NAME); + + EXPOSE_CONSTANT(ANY_TIME); + EXPOSE_CONSTANT(ANOTHER_TIME); + EXPOSE_CONSTANT(THIRD_TIME); + EXPOSE_CONSTANT(NOT_A_TIME); + + EXPOSE_CONSTANT(ANY_TIME_STRING); + EXPOSE_CONSTANT(ANOTHER_TIME_STRING); + EXPOSE_CONSTANT(THIRD_TIME_STRING); + EXPOSE_CONSTANT(NOT_A_TIME_STRING); + EXPOSE_CONSTANT(ANY_ATTRIBUTE); EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE); EXPOSE_CONSTANT(THIRD_ATTRIBUTE); + EXPOSE_CONSTANT(NOT_AN_ATTRIBUTE); + + EXPOSE_CONSTANT(ANY_ID); + EXPOSE_CONSTANT(ANOTHER_ID); + EXPOSE_CONSTANT(THIRD_ID); + EXPOSE_CONSTANT(NOT_AN_ID); + + EXPOSE_CONSTANT(ANY_NEST_DATA); + + EXPOSE_CONSTANT(ANY_VALUE); + EXPOSE_CONSTANT(TIME_STRIDE); + EXPOSE_CONSTANT(ATTRIBUTE_STRIDE); + EXPOSE_CONSTANT(ID_STRIDE); - EXPOSE_CONSTANT(ANY_TIME); - EXPOSE_CONSTANT(ANOTHER_TIME); def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, pyniv::testing::AnyAttributesValuesOverloads()); def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); From 7e3f312f5a44ab931a59be08b3834c1c499dcb47 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 07:46:22 +0100 Subject: [PATCH 38/82] Rename pyniv.consumer.Multimeter to pyniv.consumer.NestMultimeter --- .../consumer/{test_multimeter.py => test_nest_multimeter.py} | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename pyniv/tests/src/consumer/{test_multimeter.py => test_nest_multimeter.py} (95%) diff --git a/pyniv/tests/src/consumer/test_multimeter.py b/pyniv/tests/src/consumer/test_nest_multimeter.py similarity index 95% rename from pyniv/tests/src/consumer/test_multimeter.py rename to pyniv/tests/src/consumer/test_nest_multimeter.py index ae936c6..e899c35 100644 --- a/pyniv/tests/src/consumer/test_multimeter.py +++ b/pyniv/tests/src/consumer/test_nest_multimeter.py @@ -21,7 +21,7 @@ import pyniv -def test_multimeter_provides_access_to_data_stored_in_a_conduit_node(): +def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): nest_data = pyniv.testing.AnyNestData() multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetNode(nest_data) @@ -37,3 +37,4 @@ def test_multimeter_provides_access_to_data_stored_in_a_conduit_node(): multimeter.Update() result = multimeter.GetValues() assert (result == pyniv.testing.AnotherAttributesValues()).all() + From 1a8ff8bef9cc158bd0711e4aac5d2d30d532148a Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 07:46:55 +0100 Subject: [PATCH 39/82] Expose to python ArborMultimeter: ctor, GetTimestepsString() --- pyniv/src/consumer/arbor_multimeter.cpp | 54 +++++++++++++++++++ pyniv/src/consumer/consumer.cpp | 2 + .../src/consumer/test_arbor_multimeter.py | 38 +++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 pyniv/src/consumer/arbor_multimeter.cpp create mode 100644 pyniv/tests/src/consumer/test_arbor_multimeter.py diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp new file mode 100644 index 0000000..ca86bb2 --- /dev/null +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "pyniv.hpp" + +#include // NOLINT + +#include "niv/consumer/arbor_multimeter.hpp" + +namespace pyniv { + +namespace consumer { +namespace arbor_multimeter { + +boost::python::list GetTimestepsString( + const niv::consumer::ArborMultimeter& multimeter) { + boost::python::list retval; + const auto timesteps = multimeter.GetTimestepsString(); + for (auto t : timesteps) { + retval.append(t); + } + return retval; +} + +} // namespace arbor_multimeter +} // namespace consumer + +template <> +void expose() { + class_>( + "ArborMultimeter", init()) + .def("GetTimestepsString", + &pyniv::consumer::arbor_multimeter::GetTimestepsString); +} + +} // namespace pyniv diff --git a/pyniv/src/consumer/consumer.cpp b/pyniv/src/consumer/consumer.cpp index a27293f..378fd92 100644 --- a/pyniv/src/consumer/consumer.cpp +++ b/pyniv/src/consumer/consumer.cpp @@ -21,6 +21,7 @@ #include "pyniv.hpp" +#include "niv/consumer/arbor_multimeter.hpp" #include "niv/consumer/backend.hpp" #include "niv/consumer/device.hpp" #include "niv/consumer/nest_multimeter.hpp" @@ -29,6 +30,7 @@ namespace pyniv { BOOST_PYTHON_MODULE(_consumer) { + pyniv::expose(); pyniv::expose(); pyniv::expose(); pyniv::expose(); diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py new file mode 100644 index 0000000..c1889f8 --- /dev/null +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +import pyniv + +def setup_multimeter(name = pyniv.testing.ANY_MULTIMETER_NAME, + data = pyniv.testing.ANY_NEST_DATA): + multimeter = pyniv.consumer.ArborMultimeter(name) + multimeter.SetNode(data) + return multimeter, data + +def test_arbor_multimeter_lists_the_timesteps(): + multimeter, nest_data = setup_multimeter() + timesteps = multimeter.GetTimestepsString(); + assert timesteps == pyniv.testing.ANY_TIMES_STRING + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + timesteps = multimeter.GetTimestepsString(); + assert timesteps == [] From b565cce8bfc995ef1735eb894a53048c9a8306de Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 07:52:45 +0100 Subject: [PATCH 40/82] Expose to python ArborMultimeter::GetAttributes() --- pyniv/src/consumer/arbor_multimeter.cpp | 13 ++++++++++++- pyniv/tests/src/consumer/test_arbor_multimeter.py | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index ca86bb2..2b1cb5e 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -40,6 +40,16 @@ boost::python::list GetTimestepsString( return retval; } +boost::python::list GetAttributes( + const niv::consumer::ArborMultimeter& multimeter, double time) { + boost::python::list retval; + const auto attributes = multimeter.GetAttributes(time); + for (auto a : attributes) { + retval.append(a); + } + return retval; +} + } // namespace arbor_multimeter } // namespace consumer @@ -48,7 +58,8 @@ void expose() { class_>( "ArborMultimeter", init()) .def("GetTimestepsString", - &pyniv::consumer::arbor_multimeter::GetTimestepsString); + &pyniv::consumer::arbor_multimeter::GetTimestepsString) + .def("GetAttributes", &pyniv::consumer::arbor_multimeter::GetAttributes); } } // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index c1889f8..e84bc88 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -36,3 +36,16 @@ def test_arbor_multimeter_lists_the_timesteps(): name = pyniv.testing.NOT_A_MULTIMETER_NAME) timesteps = multimeter.GetTimestepsString(); assert timesteps == [] + +def test_arbor_multimeter_lists_attributes_for_a_timestep(): + multimeter, nest_data = setup_multimeter() + attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME) + assert attributes == pyniv.testing.ANY_ATTRIBUTES + + attributes = multimeter.GetAttributes(pyniv.testing.NOT_A_TIME) + assert attributes == [] + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME) + assert attributes == [] From 09ef07952e16e2a8c8fe2047a9773f8cbc7c5b60 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 07:59:39 +0100 Subject: [PATCH 41/82] Expose to python ArborMultimeter::GetNeuronIds() --- pyniv/src/consumer/arbor_multimeter.cpp | 14 ++++++++++++- .../src/consumer/test_arbor_multimeter.py | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 2b1cb5e..6211901 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -50,6 +50,17 @@ boost::python::list GetAttributes( return retval; } +boost::python::list GetNeuronIds( + const niv::consumer::ArborMultimeter& multimeter, double time, + const std::string& attribute) { + boost::python::list retval; + const auto ids = multimeter.GetNeuronIds(time, attribute); + for (auto i : ids) { + retval.append(i); + } + return retval; +} + } // namespace arbor_multimeter } // namespace consumer @@ -59,7 +70,8 @@ void expose() { "ArborMultimeter", init()) .def("GetTimestepsString", &pyniv::consumer::arbor_multimeter::GetTimestepsString) - .def("GetAttributes", &pyniv::consumer::arbor_multimeter::GetAttributes); + .def("GetAttributes", &pyniv::consumer::arbor_multimeter::GetAttributes) + .def("GetNeuronIds", &pyniv::consumer::arbor_multimeter::GetNeuronIds); } } // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index e84bc88..6eae049 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -49,3 +49,24 @@ def test_arbor_multimeter_lists_attributes_for_a_timestep(): name = pyniv.testing.NOT_A_MULTIMETER_NAME) attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME) assert attributes == [] + +def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): + multimeter, nest_data = setup_multimeter() + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, + pyniv.testing.ANY_ATTRIBUTE) + assert ids == pyniv.testing.ANY_IDS + + + ids = multimeter.GetNeuronIds(pyniv.testing.NOT_A_TIME, + pyniv.testing.ANY_ATTRIBUTE) + assert ids == [] + + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, + pyniv.testing.NOT_AN_ATTRIBUTE) + assert ids == [] + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, + pyniv.testing.ANY_ATTRIBUTE) + assert ids == [] From 444f7a52d1bb3c4483e33a690a0908df49a44e54 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 15:54:56 +0100 Subject: [PATCH 42/82] Move some computation from test into test data --- niv/include/niv/nest_test_data.hpp | 10 +++++----- niv/tests/src/consumer/test_arbor_multimeter.cpp | 9 +++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index c72e4ee..dd35e9d 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -72,11 +72,6 @@ static const char* ANOTHER_TIME_STRING{ANY_TIMES_STRING[1].c_str()}; static const char* THIRD_TIME_STRING{ANY_TIMES_STRING[2].c_str()}; static const char* NOT_A_TIME_STRING{"NOT_A_TIME"}; -static const std::vector ANY_TIME_OFFSETS{0.0123, 0.0234, 0.0345}; -static const double ANY_TIME_OFFSET{ANY_TIME_OFFSETS[0]}; -static const double ANOTHER_TIME_OFFSET{ANY_TIME_OFFSETS[1]}; -static const double THIRD_TIME_OFFSET{ANY_TIME_OFFSETS[2]}; - static const std::vector ANY_ATTRIBUTES{"V_m", "g_e", "g_i"}; static const char* ANY_ATTRIBUTE{ANY_ATTRIBUTES[0].c_str()}; static const char* ANOTHER_ATTRIBUTE{ANY_ATTRIBUTES[1].c_str()}; @@ -100,6 +95,11 @@ static const std::size_t TIME_STRIDE{9}; static const std::size_t ATTRIBUTE_STRIDE{3}; static const std::size_t ID_STRIDE{1}; +static const std::size_t ANY_TIME_OFFSET{0 * niv::testing::TIME_STRIDE}; +static const std::size_t ANOTHER_ATTRIBUTE_OFFSET{ + 1 * niv::testing::ATTRIBUTE_STRIDE}; +static const std::size_t THIRD_ID_OFFSET{2 * niv::testing::ID_STRIDE}; + template inline std::string OpenTag(T tag) { std::stringstream s; diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 4138b22..1530455 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -162,12 +162,9 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID); THEN("it is correct") { - const std::size_t ANY_TIME_OFFSET{0 * niv::testing::TIME_STRIDE}; - const std::size_t ANOTHER_ATTRIBUTE_OFFSET{ - 1 * niv::testing::ATTRIBUTE_STRIDE}; - const std::size_t THIRD_ID_OFFSET{2 * niv::testing::ID_STRIDE}; - const std::size_t DATUM_OFFSET{ - ANY_TIME_OFFSET + ANOTHER_ATTRIBUTE_OFFSET + THIRD_ID_OFFSET}; + const std::size_t DATUM_OFFSET{niv::testing::ANY_TIME_OFFSET + + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + + niv::testing::THIRD_ID_OFFSET}; REQUIRE(datum == Approx(niv::testing::ANY_VALUES[DATUM_OFFSET])); } } From dea9ab591d8a72d78054678ef25f900b3793b7ca Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 15:55:57 +0100 Subject: [PATCH 43/82] Complete niv::consumer::ArborMultimeter test --- niv/tests/src/consumer/test_arbor_multimeter.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 1530455..54c75e0 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -190,6 +190,20 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::ArborMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting data") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID); + + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + } } SCENARIO("ArborMultimeter provides time series data", From 4140c643a6af5db77a5f431e7ddc39ca027cb335 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 15:56:22 +0100 Subject: [PATCH 44/82] Expose to python ArborMultimeter::GetDatum() --- pyniv/src/consumer/arbor_multimeter.cpp | 6 +++- pyniv/src/testing/nest_test_data.cpp | 4 +++ .../src/consumer/test_arbor_multimeter.py | 34 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 6211901..0beb7a6 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -71,7 +71,11 @@ void expose() { .def("GetTimestepsString", &pyniv::consumer::arbor_multimeter::GetTimestepsString) .def("GetAttributes", &pyniv::consumer::arbor_multimeter::GetAttributes) - .def("GetNeuronIds", &pyniv::consumer::arbor_multimeter::GetNeuronIds); + .def("GetNeuronIds", &pyniv::consumer::arbor_multimeter::GetNeuronIds) + .def("GetDatum", + static_cast( + &niv::consumer::ArborMultimeter::GetDatum)); } } // namespace pyniv diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 05e9d96..63614df 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -112,6 +112,10 @@ void expose() { EXPOSE_CONSTANT(ATTRIBUTE_STRIDE); EXPOSE_CONSTANT(ID_STRIDE); + EXPOSE_CONSTANT(ANY_TIME_OFFSET); + EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE_OFFSET); + EXPOSE_CONSTANT(THIRD_ID_OFFSET); + def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, pyniv::testing::AnyAttributesValuesOverloads()); def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index 6eae049..5bc374e 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -21,6 +21,8 @@ import pyniv +import numpy as np + def setup_multimeter(name = pyniv.testing.ANY_MULTIMETER_NAME, data = pyniv.testing.ANY_NEST_DATA): multimeter = pyniv.consumer.ArborMultimeter(name) @@ -70,3 +72,35 @@ def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, pyniv.testing.ANY_ATTRIBUTE) assert ids == [] + +def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): + multimeter, nest_data = setup_multimeter() + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID) + datum_offset = (pyniv.testing.ANY_TIME_OFFSET + + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + + pyniv.testing.THIRD_ID_OFFSET); + assert np.isclose(datum, pyniv.testing.ANY_VALUES[datum_offset]) + + datum = multimeter.GetDatum(pyniv.testing.NOT_A_TIME, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID) + assert np.isnan(datum) + + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + pyniv.testing.NOT_AN_ATTRIBUTE, + pyniv.testing.THIRD_ID) + assert np.isnan(datum) + + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.NOT_AN_ID) + assert np.isnan(datum) + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID) + assert np.isnan(datum) From 7b692d522431e8aa8145148f5782e3854e0b1efd Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 16:02:00 +0100 Subject: [PATCH 45/82] Move some computation from test into test data --- niv/include/niv/nest_test_data.hpp | 4 ++++ niv/tests/src/consumer/test_arbor_multimeter.cpp | 9 ++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index dd35e9d..deffbb0 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -96,6 +96,10 @@ static const std::size_t ATTRIBUTE_STRIDE{3}; static const std::size_t ID_STRIDE{1}; static const std::size_t ANY_TIME_OFFSET{0 * niv::testing::TIME_STRIDE}; +static const std::size_t ANOTHER_TIME_OFFSET{1 * niv::testing::TIME_STRIDE}; +static const std::size_t THIRD_TIME_OFFSET{2 * niv::testing::TIME_STRIDE}; +static const std::vector TIME_OFFSETS{ + ANY_TIME_OFFSET, ANOTHER_TIME_OFFSET, THIRD_TIME_OFFSET}; static const std::size_t ANOTHER_ATTRIBUTE_OFFSET{ 1 * niv::testing::ATTRIBUTE_STRIDE}; static const std::size_t THIRD_ID_OFFSET{2 * niv::testing::ID_STRIDE}; diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 54c75e0..890c70c 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -209,11 +209,10 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", SCENARIO("ArborMultimeter provides time series data", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { std::vector expected; - for (std::size_t i = 0; i < niv::testing::ANY_TIMES.size(); ++i) { - const auto TIME_OFFSET{i * niv::testing::TIME_STRIDE}; - const auto ATTRIBUTE_OFFSET{1 * niv::testing::ATTRIBUTE_STRIDE}; - const auto ID_OFFSET{2 * niv::testing::ID_STRIDE}; - const auto DATUM_INDEX{TIME_OFFSET + ATTRIBUTE_OFFSET + ID_OFFSET}; + for (auto time_offset : niv::testing::TIME_OFFSETS) { + const auto DATUM_INDEX{time_offset + + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + + niv::testing::THIRD_ID_OFFSET}; expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); } const std::vector nans(niv::testing::ANY_TIMES.size(), std::nan("")); From abe8ba5e377b75d4e7a7730ff779017e2ef9245a Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 16:22:52 +0100 Subject: [PATCH 46/82] Expose to python ArborMultimeter::GetTimeSeriesData() --- pyniv/src/consumer/arbor_multimeter.cpp | 14 +++++++++- pyniv/src/testing/nest_test_data.cpp | 9 +++++++ .../src/consumer/test_arbor_multimeter.py | 26 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 0beb7a6..5079279 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -61,6 +61,16 @@ boost::python::list GetNeuronIds( return retval; } +boost::python::list GetTimeSeriesData( + const niv::consumer::ArborMultimeter& multimeter, + const std::string& attribute, const std::string& neuron_id) { + boost::python::list ret_val; + for (auto v : multimeter.GetTimeSeriesData(attribute, neuron_id)) { + ret_val.append(v); + } + return ret_val; +} + } // namespace arbor_multimeter } // namespace consumer @@ -75,7 +85,9 @@ void expose() { .def("GetDatum", static_cast( - &niv::consumer::ArborMultimeter::GetDatum)); + &niv::consumer::ArborMultimeter::GetDatum)) + .def("GetTimeSeriesData", + &pyniv::consumer::arbor_multimeter::GetTimeSeriesData); } } // namespace pyniv diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 63614df..45d4015 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -74,6 +74,14 @@ boost::python::numpy::ndarray AnotherAttributesValues() { BOOST_PYTHON_FUNCTION_OVERLOADS(AnyAttributesValuesOverloads, AnyAttributesValues, 0, 1) +boost::python::list TimeOffsets() { + boost::python::list ret_val; + for (auto t : niv::testing::TIME_OFFSETS) { + ret_val.append(t); + } + return ret_val; +} + } // namespace testing #ifndef EXPOSE_CONSTANT @@ -116,6 +124,7 @@ void expose() { EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE_OFFSET); EXPOSE_CONSTANT(THIRD_ID_OFFSET); + def("TIME_OFFSETS", &pyniv::testing::TimeOffsets); def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, pyniv::testing::AnyAttributesValuesOverloads()); def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index 5bc374e..2b5cdc9 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -104,3 +104,29 @@ def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): pyniv.testing.ANOTHER_ATTRIBUTE, pyniv.testing.THIRD_ID) assert np.isnan(datum) + +def test_arbor_multimeter_provides_time_series_data(): + data_offsets = [(time_offset + + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + + pyniv.testing.THIRD_ID_OFFSET) + for time_offset in pyniv.testing.TIME_OFFSETS()] + expected = np.array([pyniv.testing.ANY_VALUES[o] for o in data_offsets]) + + multimeter, nest_data = setup_multimeter() + values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID) + assert (values == expected).all() + + values = multimeter.GetTimeSeriesData(pyniv.testing.NOT_AN_ATTRIBUTE, + pyniv.testing.THIRD_ID) + assert np.isnan(values).all() + + values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.NOT_AN_ID) + assert np.isnan(values).all() + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID) + assert np.isnan(values).all() From 1c994d5426aa9f2e5e1f5cee89d5a4ed1865354e Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 16:29:22 +0100 Subject: [PATCH 47/82] Move some computation from test into test data --- niv/tests/src/consumer/test_arbor_multimeter.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 890c70c..542d493 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -271,12 +271,10 @@ SCENARIO("ArborMultimeter provides time series data", SCENARIO("ArborMultimeter provides time step data for all neurons", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { std::vector expected; - const auto THIRD_TIME{niv::testing::THIRD_TIME}; - const auto TIME_OFFSET{2 * niv::testing::TIME_STRIDE}; - const auto ATTRIBUTE_OFFSET{1 * niv::testing::ATTRIBUTE_STRIDE}; for (std::size_t i = 0; i < niv::testing::ANY_IDS.size(); ++i) { const auto ID_OFFSET{i * niv::testing::ID_STRIDE}; - const auto DATUM_INDEX{TIME_OFFSET + ATTRIBUTE_OFFSET + ID_OFFSET}; + const auto DATUM_INDEX{niv::testing::THIRD_TIME_OFFSET + + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + ID_OFFSET}; expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); } @@ -287,7 +285,7 @@ SCENARIO("ArborMultimeter provides time step data for all neurons", WHEN("requesting time step data for an attribute") { const std::vector values{multimeter.GetTimestepData( - THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + niv::testing::THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; THEN("the time step data is correct") { REQUIRE(values == expected); } } @@ -303,7 +301,7 @@ SCENARIO("ArborMultimeter provides time step data for all neurons", WHEN("requesting time step data for an invalid attribute") { const std::vector values{multimeter.GetTimestepData( - THIRD_TIME, niv::testing::NOT_AN_ATTRIBUTE)}; + niv::testing::THIRD_TIME, niv::testing::NOT_AN_ATTRIBUTE)}; THEN("the time step data is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); @@ -318,7 +316,7 @@ SCENARIO("ArborMultimeter provides time step data for all neurons", WHEN("requesting time step data for an attribute") { const std::vector values{multimeter.GetTimestepData( - THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + niv::testing::THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; THEN("the time step data is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); From 9f418c283636c70090c4cae507a03f1b0c176b64 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 15 Mar 2018 16:43:57 +0100 Subject: [PATCH 48/82] Expose to python ArborMultimeter::GetTimestepData() --- niv/include/niv/nest_test_data.hpp | 6 +++++ .../src/consumer/test_arbor_multimeter.cpp | 2 +- pyniv/src/consumer/arbor_multimeter.cpp | 14 ++++++++++- pyniv/src/testing/nest_test_data.cpp | 12 +++++++++ .../src/consumer/test_arbor_multimeter.py | 25 +++++++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index deffbb0..5951c37 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -100,9 +100,15 @@ static const std::size_t ANOTHER_TIME_OFFSET{1 * niv::testing::TIME_STRIDE}; static const std::size_t THIRD_TIME_OFFSET{2 * niv::testing::TIME_STRIDE}; static const std::vector TIME_OFFSETS{ ANY_TIME_OFFSET, ANOTHER_TIME_OFFSET, THIRD_TIME_OFFSET}; + static const std::size_t ANOTHER_ATTRIBUTE_OFFSET{ 1 * niv::testing::ATTRIBUTE_STRIDE}; + +static const std::size_t ANY_ID_OFFSET{0 * niv::testing::ID_STRIDE}; +static const std::size_t ANOTHER_ID_OFFSET{1 * niv::testing::ID_STRIDE}; static const std::size_t THIRD_ID_OFFSET{2 * niv::testing::ID_STRIDE}; +static const std::vector ID_OFFSETS{ + ANY_ID_OFFSET, ANOTHER_ID_OFFSET, THIRD_ID_OFFSET}; template inline std::string OpenTag(T tag) { diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 542d493..3ca47da 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -268,7 +268,7 @@ SCENARIO("ArborMultimeter provides time series data", } } -SCENARIO("ArborMultimeter provides time step data for all neurons", +SCENARIO("ArborMultimeter provides timestep data for all neurons", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { std::vector expected; for (std::size_t i = 0; i < niv::testing::ANY_IDS.size(); ++i) { diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 5079279..62f5aac 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -71,6 +71,16 @@ boost::python::list GetTimeSeriesData( return ret_val; } +boost::python::list GetTimestepData( + const niv::consumer::ArborMultimeter& multimeter, double time, + const std::string& attribute) { + boost::python::list ret_val; + for (auto v : multimeter.GetTimestepData(time, attribute)) { + ret_val.append(v); + } + return ret_val; +} + } // namespace arbor_multimeter } // namespace consumer @@ -87,7 +97,9 @@ void expose() { double, const std::string&, const std::string&) const>( &niv::consumer::ArborMultimeter::GetDatum)) .def("GetTimeSeriesData", - &pyniv::consumer::arbor_multimeter::GetTimeSeriesData); + &pyniv::consumer::arbor_multimeter::GetTimeSeriesData) + .def("GetTimestepData", + &pyniv::consumer::arbor_multimeter::GetTimestepData); } } // namespace pyniv diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 45d4015..7e60731 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -82,6 +82,14 @@ boost::python::list TimeOffsets() { return ret_val; } +boost::python::list IdOffsets() { + boost::python::list ret_val; + for (auto i : niv::testing::ID_OFFSETS) { + ret_val.append(i); + } + return ret_val; +} + } // namespace testing #ifndef EXPOSE_CONSTANT @@ -121,10 +129,14 @@ void expose() { EXPOSE_CONSTANT(ID_STRIDE); EXPOSE_CONSTANT(ANY_TIME_OFFSET); + EXPOSE_CONSTANT(ANOTHER_TIME_OFFSET); + EXPOSE_CONSTANT(THIRD_TIME_OFFSET); + EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE_OFFSET); EXPOSE_CONSTANT(THIRD_ID_OFFSET); def("TIME_OFFSETS", &pyniv::testing::TimeOffsets); + def("ID_OFFSETS", &pyniv::testing::IdOffsets); def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, pyniv::testing::AnyAttributesValuesOverloads()); def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index 2b5cdc9..018e1a5 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -130,3 +130,28 @@ def test_arbor_multimeter_provides_time_series_data(): values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, pyniv.testing.THIRD_ID) assert np.isnan(values).all() + +def test_arbor_multimeter_provides_timestep_data_for_all_neurons(): + data_offsets = [(pyniv.testing.THIRD_TIME_OFFSET + + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + + id_offset) for id_offset in pyniv.testing.ID_OFFSETS()] + expected = np.array([pyniv.testing.ANY_VALUES[o] for o in data_offsets]) + + multimeter, nest_data = setup_multimeter() + values = multimeter.GetTimestepData( + pyniv.testing.THIRD_TIME, pyniv.testing.ANOTHER_ATTRIBUTE) + assert (values == expected).all() + + values = multimeter.GetTimestepData( + pyniv.testing.NOT_A_TIME, pyniv.testing.ANOTHER_ATTRIBUTE) + assert np.isnan(values).all() + + values = multimeter.GetTimestepData( + pyniv.testing.THIRD_TIME, pyniv.testing.NOT_AN_ATTRIBUTE) + assert np.isnan(values).all() + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + values = multimeter.GetTimestepData( + pyniv.testing.THIRD_TIME, pyniv.testing.ANOTHER_ATTRIBUTE) + assert np.isnan(values).all() From 369a44ee8fefc2cf4538ca6b1926a4e3c012f591 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 05:59:02 +0100 Subject: [PATCH 49/82] Fix "base wrapper has not been created" bug in pyniv --- pyniv/src/consumer/consumer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyniv/src/consumer/consumer.cpp b/pyniv/src/consumer/consumer.cpp index 378fd92..b0127a8 100644 --- a/pyniv/src/consumer/consumer.cpp +++ b/pyniv/src/consumer/consumer.cpp @@ -30,10 +30,11 @@ namespace pyniv { BOOST_PYTHON_MODULE(_consumer) { - pyniv::expose(); pyniv::expose(); - pyniv::expose(); pyniv::expose(); + + pyniv::expose(); + pyniv::expose(); pyniv::expose(); } From 12b4921825228b2421fa0c77c3c576156bd609be Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 05:59:57 +0100 Subject: [PATCH 50/82] Make ArborMultimeter::GetAttributes take a time string --- niv/include/niv/consumer/arbor_multimeter.hpp | 3 ++- niv/src/consumer/arbor_multimeter.cpp | 7 ++++++- niv/tests/src/consumer/test_arbor_multimeter.cpp | 7 ++++--- pyniv/src/consumer/arbor_multimeter.cpp | 2 +- pyniv/tests/src/consumer/test_arbor_multimeter.py | 6 +++--- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index db3253a..60a1a81 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -42,7 +42,7 @@ class ArborMultimeter : public niv::consumer::Device { std::vector GetTimestepsString() const; - std::vector GetAttributes(double time) const; + std::vector GetAttributes(const std::string& time) const; std::vector GetNeuronIds(double time, const std::string& attribute) const; @@ -69,6 +69,7 @@ class ArborMultimeter : public niv::consumer::Device { const std::string& neuron_id) const; std::string ConstructPath(double time, const std::string& attribute) const; std::string ConstructPath(double time) const; + std::string ConstructPath(const std::string& time) const; std::string ConstructPath() const; std::vector GetChildNames(const std::string& path) const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index b03f62b..2a15cf3 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -40,7 +40,8 @@ std::vector ArborMultimeter::GetTimestepsString() const { return GetChildNames(ConstructPath()); } -std::vector ArborMultimeter::GetAttributes(double time) const { +std::vector ArborMultimeter::GetAttributes( + const std::string& time) const { return GetChildNames(ConstructPath(time)); } @@ -108,6 +109,10 @@ std::string ArborMultimeter::ConstructPath(double time) const { return path.str(); } +std::string ArborMultimeter::ConstructPath(const std::string& time) const { + return ConstructPath() + '/' + time; +} + std::string ArborMultimeter::ConstructPath() const { return GetName(); } std::vector ArborMultimeter::GetChildNames( diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 3ca47da..1d2158f 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -79,14 +79,15 @@ SCENARIO("ArborMultimeter lists attributes for a timestep", multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("attributes are requested") { - auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME)}; + auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME_STRING)}; THEN("the multimeter provides the attributes") { REQUIRE(attributes == niv::testing::ANY_ATTRIBUTES); } } WHEN("attributes are requested for an invalid timestep") { - auto attributes{multimeter.GetAttributes(niv::testing::NOT_A_TIME)}; + auto attributes{ + multimeter.GetAttributes(niv::testing::NOT_A_TIME_STRING)}; THEN("the multimeter does not provide attributes") { REQUIRE(attributes.empty()); } @@ -99,7 +100,7 @@ SCENARIO("ArborMultimeter lists attributes for a timestep", multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("attributes are requested") { - auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME)}; + auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME_STRING)}; THEN("the multimeter does not provide attributes") { REQUIRE(attributes.empty()); } diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 62f5aac..34d4d8d 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -41,7 +41,7 @@ boost::python::list GetTimestepsString( } boost::python::list GetAttributes( - const niv::consumer::ArborMultimeter& multimeter, double time) { + const niv::consumer::ArborMultimeter& multimeter, const std::string& time) { boost::python::list retval; const auto attributes = multimeter.GetAttributes(time); for (auto a : attributes) { diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index 018e1a5..4a5aa2e 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -41,15 +41,15 @@ def test_arbor_multimeter_lists_the_timesteps(): def test_arbor_multimeter_lists_attributes_for_a_timestep(): multimeter, nest_data = setup_multimeter() - attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME) + attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME_STRING) assert attributes == pyniv.testing.ANY_ATTRIBUTES - attributes = multimeter.GetAttributes(pyniv.testing.NOT_A_TIME) + attributes = multimeter.GetAttributes(pyniv.testing.NOT_A_TIME_STRING) assert attributes == [] multimeter, nest_data = setup_multimeter( name = pyniv.testing.NOT_A_MULTIMETER_NAME) - attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME) + attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME_STRING) assert attributes == [] def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): From d4a8f9205dc4f179322a7fb09cc531946f9d0096 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 06:09:42 +0100 Subject: [PATCH 51/82] Make c::AM::GetNeuronIds, GetTimeStepData take time strings --- niv/include/niv/consumer/arbor_multimeter.hpp | 6 ++++-- niv/src/consumer/arbor_multimeter.cpp | 9 +++++++-- niv/tests/src/consumer/test_arbor_multimeter.cpp | 16 ++++++++-------- pyniv/src/consumer/arbor_multimeter.cpp | 4 ++-- .../tests/src/consumer/test_arbor_multimeter.py | 16 ++++++++-------- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 60a1a81..2267de8 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -44,10 +44,10 @@ class ArborMultimeter : public niv::consumer::Device { std::vector GetAttributes(const std::string& time) const; - std::vector GetNeuronIds(double time, + std::vector GetNeuronIds(const std::string& time, const std::string& attribute) const; - std::vector GetTimestepData(double time, + std::vector GetTimestepData(const std::string& time, const std::string& attribute) const; std::vector GetTimeSeriesData(const std::string& attribute, @@ -69,6 +69,8 @@ class ArborMultimeter : public niv::consumer::Device { const std::string& neuron_id) const; std::string ConstructPath(double time, const std::string& attribute) const; std::string ConstructPath(double time) const; + std::string ConstructPath(const std::string& time, + const std::string& attribute) const; std::string ConstructPath(const std::string& time) const; std::string ConstructPath() const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 2a15cf3..bf1c946 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -46,12 +46,12 @@ std::vector ArborMultimeter::GetAttributes( } std::vector ArborMultimeter::GetNeuronIds( - double time, const std::string& attribute) const { + const std::string& time, const std::string& attribute) const { return GetChildNames(ConstructPath(time, attribute)); } std::vector ArborMultimeter::GetTimestepData( - double time, const std::string& attribute) const { + const std::string& time, const std::string& attribute) const { std::vector retval; const auto neuron_ids{GetNeuronIds(time, attribute)}; for (auto curr_neuron_id : neuron_ids) { @@ -103,6 +103,11 @@ std::string ArborMultimeter::ConstructPath(double time, return path.str(); } +std::string ArborMultimeter::ConstructPath(const std::string& time, + const std::string& attribute) const { + return ConstructPath(time) + '/' + attribute; +} + std::string ArborMultimeter::ConstructPath(double time) const { std::stringstream path; path << ConstructPath() << "/" << time; diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 1d2158f..a36293f 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -118,7 +118,7 @@ SCENARIO( multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("neuron ids are requested") { - auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter provides the ids") { REQUIRE(ids == niv::testing::ANY_IDS); @@ -126,13 +126,13 @@ SCENARIO( } WHEN("neuron ids are requested for an invalid timestep") { - auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME, + auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME_STRING, niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } WHEN("neuron ids are requested for an invalid attribute") { - auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, niv::testing::NOT_AN_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } @@ -144,7 +144,7 @@ SCENARIO( multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("neuron ids are requested") { - auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME, + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } } @@ -286,14 +286,14 @@ SCENARIO("ArborMultimeter provides timestep data for all neurons", WHEN("requesting time step data for an attribute") { const std::vector values{multimeter.GetTimestepData( - niv::testing::THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + niv::testing::THIRD_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE)}; THEN("the time step data is correct") { REQUIRE(values == expected); } } WHEN("requesting time step data for an invalid time step") { const std::vector values{multimeter.GetTimestepData( - niv::testing::NOT_A_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + niv::testing::NOT_A_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE)}; THEN("the time step data is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); @@ -302,7 +302,7 @@ SCENARIO("ArborMultimeter provides timestep data for all neurons", WHEN("requesting time step data for an invalid attribute") { const std::vector values{multimeter.GetTimestepData( - niv::testing::THIRD_TIME, niv::testing::NOT_AN_ATTRIBUTE)}; + niv::testing::THIRD_TIME_STRING, niv::testing::NOT_AN_ATTRIBUTE)}; THEN("the time step data is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); @@ -317,7 +317,7 @@ SCENARIO("ArborMultimeter provides timestep data for all neurons", WHEN("requesting time step data for an attribute") { const std::vector values{multimeter.GetTimestepData( - niv::testing::THIRD_TIME, niv::testing::ANOTHER_ATTRIBUTE)}; + niv::testing::THIRD_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE)}; THEN("the time step data is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 34d4d8d..28efaf9 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -51,7 +51,7 @@ boost::python::list GetAttributes( } boost::python::list GetNeuronIds( - const niv::consumer::ArborMultimeter& multimeter, double time, + const niv::consumer::ArborMultimeter& multimeter, const std::string& time, const std::string& attribute) { boost::python::list retval; const auto ids = multimeter.GetNeuronIds(time, attribute); @@ -72,7 +72,7 @@ boost::python::list GetTimeSeriesData( } boost::python::list GetTimestepData( - const niv::consumer::ArborMultimeter& multimeter, double time, + const niv::consumer::ArborMultimeter& multimeter, const std::string& time, const std::string& attribute) { boost::python::list ret_val; for (auto v : multimeter.GetTimestepData(time, attribute)) { diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index 4a5aa2e..2307d92 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -54,22 +54,22 @@ def test_arbor_multimeter_lists_attributes_for_a_timestep(): def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): multimeter, nest_data = setup_multimeter() - ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANY_ATTRIBUTE) assert ids == pyniv.testing.ANY_IDS - ids = multimeter.GetNeuronIds(pyniv.testing.NOT_A_TIME, + ids = multimeter.GetNeuronIds(pyniv.testing.NOT_A_TIME_STRING, pyniv.testing.ANY_ATTRIBUTE) assert ids == [] - ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, pyniv.testing.NOT_AN_ATTRIBUTE) assert ids == [] multimeter, nest_data = setup_multimeter( name = pyniv.testing.NOT_A_MULTIMETER_NAME) - ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME, + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANY_ATTRIBUTE) assert ids == [] @@ -139,19 +139,19 @@ def test_arbor_multimeter_provides_timestep_data_for_all_neurons(): multimeter, nest_data = setup_multimeter() values = multimeter.GetTimestepData( - pyniv.testing.THIRD_TIME, pyniv.testing.ANOTHER_ATTRIBUTE) + pyniv.testing.THIRD_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE) assert (values == expected).all() values = multimeter.GetTimestepData( - pyniv.testing.NOT_A_TIME, pyniv.testing.ANOTHER_ATTRIBUTE) + pyniv.testing.NOT_A_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE) assert np.isnan(values).all() values = multimeter.GetTimestepData( - pyniv.testing.THIRD_TIME, pyniv.testing.NOT_AN_ATTRIBUTE) + pyniv.testing.THIRD_TIME_STRING, pyniv.testing.NOT_AN_ATTRIBUTE) assert np.isnan(values).all() multimeter, nest_data = setup_multimeter( name = pyniv.testing.NOT_A_MULTIMETER_NAME) values = multimeter.GetTimestepData( - pyniv.testing.THIRD_TIME, pyniv.testing.ANOTHER_ATTRIBUTE) + pyniv.testing.THIRD_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE) assert np.isnan(values).all() From 62e3f7e82d652bfc2a1621b80059da73edd360f4 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 06:14:10 +0100 Subject: [PATCH 52/82] Remove consumer::ArborMultimeter::GetDatum taking time double --- niv/include/niv/consumer/arbor_multimeter.hpp | 2 -- niv/src/consumer/arbor_multimeter.cpp | 5 ----- niv/tests/src/consumer/test_arbor_multimeter.cpp | 13 +++++++------ pyniv/src/consumer/arbor_multimeter.cpp | 5 +---- pyniv/tests/src/consumer/test_arbor_multimeter.py | 10 +++++----- 5 files changed, 13 insertions(+), 22 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 2267de8..ef771da 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -53,8 +53,6 @@ class ArborMultimeter : public niv::consumer::Device { std::vector GetTimeSeriesData(const std::string& attribute, const std::string& neuron_id) const; - double GetDatum(double time, const std::string& attribute, - const std::string& neuron_id) const; double GetDatum(const std::string& time, const std::string& attribute, const std::string& neuron_id) const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index bf1c946..7f4cb90 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -71,11 +71,6 @@ std::vector ArborMultimeter::GetTimeSeriesData( return retval; } -double ArborMultimeter::GetDatum(double time, const std::string& attribute, - const std::string& neuron_id) const { - return GetValue(ConstructPath(time, attribute, neuron_id)); -} - double ArborMultimeter::GetDatum(const std::string& time, const std::string& attribute, const std::string& neuron_id) const { diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index a36293f..0d2eb67 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -159,7 +159,7 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("requesting data") { - const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID); THEN("it is correct") { @@ -171,21 +171,21 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", } WHEN("requesting datum at an invalid time") { - const double datum = multimeter.GetDatum(niv::testing::NOT_A_TIME, + const double datum = multimeter.GetDatum(niv::testing::NOT_A_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } WHEN("requesting datum for an invalid attribute") { - const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::NOT_AN_ATTRIBUTE, niv::testing::THIRD_ID); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } WHEN("requesting datum for an invalid neuron id") { - const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, niv::testing::NOT_AN_ID); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } @@ -198,7 +198,7 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", multimeter.SetNode(&niv::testing::ANY_NEST_DATA); WHEN("requesting data") { - const double datum = multimeter.GetDatum(niv::testing::ANY_TIME, + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID); @@ -216,7 +216,8 @@ SCENARIO("ArborMultimeter provides time series data", niv::testing::THIRD_ID_OFFSET}; expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); } - const std::vector nans(niv::testing::ANY_TIMES.size(), std::nan("")); + const std::vector nans(niv::testing::ANY_TIMES_STRING.size(), + std::nan("")); GIVEN("a multimeter providing access to some data") { niv::consumer::ArborMultimeter multimeter( diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 28efaf9..939e0a8 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -92,10 +92,7 @@ void expose() { &pyniv::consumer::arbor_multimeter::GetTimestepsString) .def("GetAttributes", &pyniv::consumer::arbor_multimeter::GetAttributes) .def("GetNeuronIds", &pyniv::consumer::arbor_multimeter::GetNeuronIds) - .def("GetDatum", - static_cast( - &niv::consumer::ArborMultimeter::GetDatum)) + .def("GetDatum", &niv::consumer::ArborMultimeter::GetDatum) .def("GetTimeSeriesData", &pyniv::consumer::arbor_multimeter::GetTimeSeriesData) .def("GetTimestepData", diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index 2307d92..e8a77d4 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -75,7 +75,7 @@ def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): multimeter, nest_data = setup_multimeter() - datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, pyniv.testing.THIRD_ID) datum_offset = (pyniv.testing.ANY_TIME_OFFSET + @@ -83,24 +83,24 @@ def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): pyniv.testing.THIRD_ID_OFFSET); assert np.isclose(datum, pyniv.testing.ANY_VALUES[datum_offset]) - datum = multimeter.GetDatum(pyniv.testing.NOT_A_TIME, + datum = multimeter.GetDatum(pyniv.testing.NOT_A_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, pyniv.testing.THIRD_ID) assert np.isnan(datum) - datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.NOT_AN_ATTRIBUTE, pyniv.testing.THIRD_ID) assert np.isnan(datum) - datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, pyniv.testing.NOT_AN_ID) assert np.isnan(datum) multimeter, nest_data = setup_multimeter( name = pyniv.testing.NOT_A_MULTIMETER_NAME) - datum = multimeter.GetDatum(pyniv.testing.ANY_TIME, + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, pyniv.testing.THIRD_ID) assert np.isnan(datum) From 469e80763aeedde50aaaa1d069ada5f32148b2d5 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 06:18:05 +0100 Subject: [PATCH 53/82] Remove consumer::ArborMultimeter::ConstructPath that take time double --- niv/include/niv/consumer/arbor_multimeter.hpp | 4 ---- niv/src/consumer/arbor_multimeter.cpp | 21 ------------------- 2 files changed, 25 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index ef771da..39e618f 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -63,10 +63,6 @@ class ArborMultimeter : public niv::consumer::Device { std::string ConstructPath(const std::string& time, const std::string& attribute, const std::string& neuron_id) const; - std::string ConstructPath(double time, const std::string& attribute, - const std::string& neuron_id) const; - std::string ConstructPath(double time, const std::string& attribute) const; - std::string ConstructPath(double time) const; std::string ConstructPath(const std::string& time, const std::string& attribute) const; std::string ConstructPath(const std::string& time) const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 7f4cb90..92845d0 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -77,38 +77,17 @@ double ArborMultimeter::GetDatum(const std::string& time, return GetValue(ConstructPath(time, attribute, neuron_id)); } -std::string ArborMultimeter::ConstructPath(double time, - const std::string& attribute, - const std::string& neuron_id) const { - std::stringstream path; - path << ConstructPath(time, attribute) << "/" << neuron_id; - return path.str(); -} - std::string ArborMultimeter::ConstructPath(const std::string& time, const std::string& attribute, const std::string& neuron_id) const { return ConstructPath() + "/" + time + "/" + attribute + "/" + neuron_id; } -std::string ArborMultimeter::ConstructPath(double time, - const std::string& attribute) const { - std::stringstream path; - path << ConstructPath(time) << "/" << attribute; - return path.str(); -} - std::string ArborMultimeter::ConstructPath(const std::string& time, const std::string& attribute) const { return ConstructPath(time) + '/' + attribute; } -std::string ArborMultimeter::ConstructPath(double time) const { - std::stringstream path; - path << ConstructPath() << "/" << time; - return path.str(); -} - std::string ArborMultimeter::ConstructPath(const std::string& time) const { return ConstructPath() + '/' + time; } From 829c9740c45fa23ba851634681da71b3e777edcb Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 06:31:57 +0100 Subject: [PATCH 54/82] Update demo/arbor_miniapp-niv to use consumer::ArborMultimeter --- demo/arbor_miniapp-niv/dump_to_stdout.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/demo/arbor_miniapp-niv/dump_to_stdout.py b/demo/arbor_miniapp-niv/dump_to_stdout.py index 5e2a1c4..148a9dc 100644 --- a/demo/arbor_miniapp-niv/dump_to_stdout.py +++ b/demo/arbor_miniapp-niv/dump_to_stdout.py @@ -39,8 +39,7 @@ def __init__(self): def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - self.multimeter = pyniv.consumer.NestMultimeter("multimeter") - self.multimeter.SetAttribute("v") + self.multimeter = pyniv.consumer.ArborMultimeter("multimeter") self.backend = pyniv.consumer.Backend(); self.backend.Connect(self.receiver); @@ -56,7 +55,15 @@ def SetupUpdateTimer(self): self.update_timer.start(1) def PrintButtonClicked(self): - self.multimeter.Print() + print 60 * '=' + timesteps = self.multimeter.GetTimestepsString() + for t in timesteps: + print 't = {}'.format(t) + attributes = self.multimeter.GetAttributes(t) + for a in attributes: + values = self.multimeter.GetTimestepData(t, a) + print a + ': ' + ', '.join(['{}'.format(v) for v in values]) + print 40 * '-' def Show(self): self.print_button.show() From 05227223fe6a5615a8d2ac94b4949408261af89d Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 16 Mar 2018 07:04:45 +0100 Subject: [PATCH 55/82] Add demo/arbor-miniapp-niv/vis --- demo/arbor_miniapp-niv/CMakeLists.txt | 5 ++ demo/arbor_miniapp-niv/vis.py | 125 ++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 demo/arbor_miniapp-niv/vis.py diff --git a/demo/arbor_miniapp-niv/CMakeLists.txt b/demo/arbor_miniapp-niv/CMakeLists.txt index 6dd1275..a2d3f6d 100644 --- a/demo/arbor_miniapp-niv/CMakeLists.txt +++ b/demo/arbor_miniapp-niv/CMakeLists.txt @@ -20,6 +20,7 @@ #------------------------------------------------------------------------------- set(PYTHON_DUMP_SOURCE dump_to_stdout.py) +set(PYTHON_VIS_SOURCE vis.py) if(NOT CMAKE_MAKE_PROGRAM STREQUAL "/usr/bin/xcodebuild") @@ -27,4 +28,8 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_dump.sh CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${PYTHON_DUMP_SOURCE}" ) +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/run_vis.sh + CONTENT "PYTHONPATH=${PYNIV_OUTPUT_DIR}/..:$ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${PYTHON_VIS_SOURCE}" + ) + endif() diff --git a/demo/arbor_miniapp-niv/vis.py b/demo/arbor_miniapp-niv/vis.py new file mode 100644 index 0000000..6b5b80f --- /dev/null +++ b/demo/arbor_miniapp-niv/vis.py @@ -0,0 +1,125 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +import sys + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns + +import pyniv + +from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout, QPushButton +from PyQt5.QtCore import QTimer + +class MainWindow: + def __init__(self): + self.SetupStreaming() + self.SetupWindow() + self.SetupPlot() + self.SetupUpdateTimer() + + def SetupStreaming(self): + self.receiver = pyniv.consumer.Receiver() + + self.multimeter = pyniv.consumer.ArborMultimeter("multimeter") + + self.backend = pyniv.consumer.Backend(); + self.backend.Connect(self.receiver); + self.backend.Connect(self.multimeter); + + def SetupWindow(self): + self.visualize_button = QPushButton("Visualize") + self.visualize_button.clicked.connect(self.VisualizeButtonClicked) + + def SetupUpdateTimer(self): + self.update_timer = QTimer() + self.update_timer.timeout.connect(self.Visualize) + + def SetupPlot(self): + sns.set_style("darkgrid") + self.fig = plt.figure() + self.ax1 = self.fig.add_subplot(1,1,1) + + + def VisualizeButtonClicked(self): + self.visualize_button.setEnabled(False) + self.update_timer.start(0.5) + self.Visualize() + + def Show(self): + self.visualize_button.show() + button_geometry = self.visualize_button.geometry() + self.visualize_button.setGeometry( + 0, 0, + button_geometry.width(), + button_geometry.height()) + + def Visualize(self): + self.backend.Receive() + self.Plot(); + + def GetValues(self, multimeter): + ts = multimeter.GetTimesteps() + plot_ts = [] + plot_vs = [] + for t in ts: + multimeter.SetTime(t) + multimeter.Update() + vs = multimeter.GetValues() + if len(vs) > 0: + plot_ts.append(t.tolist()) + plot_vs.append(vs.tolist()) + return plot_ts, plot_vs + + def Plot(self): + timesteps = self.multimeter.GetTimestepsString() + attribute = 'v' + neuron_ids = [] + if len(timesteps) > 0: + neuron_ids = self.multimeter.GetNeuronIds(timesteps[0], attribute) + + self.ax1.clear() + + for neuron_id in neuron_ids: + values = self.multimeter.GetTimeSeriesData(attribute, neuron_id) + times = [float(t) for t in timesteps] + self.ax1.plot(times, values) + + self.ax1.set_title("Arbor Miniapp Niv Example") + self.ax1.set_xlabel("Time") + self.ax1.set_ylabel("v") + self.ax1.set_ylim([-80,50]) + + plt.show(block=False) + self.fig.canvas.draw() + + +def main(argv): + app = QApplication(argv) + + w = MainWindow() + w.Show() + + return app.exec_() + +if __name__ == "__main__": + main(sys.argv) From 840a42b42df2544c43f4b158a605ea09daf621e9 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 20 Mar 2018 07:52:48 +0100 Subject: [PATCH 56/82] Rename test for producer::NestMultimeter --- .../producer/{test_multimeter.cpp => test_nest_multimeter.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename niv/tests/src/producer/{test_multimeter.cpp => test_nest_multimeter.cpp} (100%) diff --git a/niv/tests/src/producer/test_multimeter.cpp b/niv/tests/src/producer/test_nest_multimeter.cpp similarity index 100% rename from niv/tests/src/producer/test_multimeter.cpp rename to niv/tests/src/producer/test_nest_multimeter.cpp From ad335e1d4cba0f7956bc247fbc05ac969b31e57b Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Mar 2018 16:30:41 +0200 Subject: [PATCH 57/82] Update test_data --- niv/include/niv/nest_test_data.hpp | 76 ++++++++++++++----- niv/src/nest_test_data.cpp | 22 ------ niv/tests/src/consumer/test_device.cpp | 6 +- niv/tests/src/consumer/test_integration.cpp | 31 ++++++-- .../src/consumer/test_nest_multimeter.cpp | 64 ++++++++++++---- pyniv/src/testing/nest_test_data.cpp | 20 ++++- pyniv/tests/src/consumer/test_device.py | 7 +- pyniv/tests/src/consumer/test_integration.py | 26 ++++++- .../src/consumer/test_nest_multimeter.py | 30 ++++++-- 9 files changed, 202 insertions(+), 80 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index 5951c37..1892e40 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -50,10 +50,27 @@ namespace testing { static const char* ANY_MULTIMETER_NAME{"multimeter A"}; static const char* NOT_A_MULTIMETER_NAME{"NOT_A_MULTIMETER_NAME"}; +static const std::size_t ANY_INDEX{0}; +static const std::size_t ANOTHER_INDEX{1}; +static const std::size_t THIRD_INDEX{2}; + +static const std::size_t ANY_TIME_INDEX{ANY_INDEX}; +static const std::size_t ANOTHER_TIME_INDEX{ANOTHER_INDEX}; +static const std::size_t THIRD_TIME_INDEX{THIRD_INDEX}; + +static const std::size_t ANY_ATTRIBUTE_INDEX{ANY_INDEX}; +static const std::size_t ANOTHER_ATTRIBUTE_INDEX{ANOTHER_INDEX}; +static const std::size_t THIRD_ATTRIBUTE_INDEX{THIRD_INDEX}; + +static const std::size_t ANY_ID_INDEX{ANY_INDEX}; +static const std::size_t ANOTHER_ID_INDEX{ANOTHER_INDEX}; +static const std::size_t THIRD_ID_INDEX{THIRD_INDEX}; + static const std::vector ANY_TIMES{0.1, 0.2, 0.3}; -static const double ANY_TIME{ANY_TIMES[0]}; -static const double ANOTHER_TIME{ANY_TIMES[1]}; -static const double THIRD_TIME{ANY_TIMES[2]}; + +static const double ANY_TIME{ANY_TIMES[ANY_TIME_INDEX]}; +static const double ANOTHER_TIME{ANY_TIMES[ANOTHER_TIME_INDEX]}; +static const double THIRD_TIME{ANY_TIMES[THIRD_TIME_INDEX]}; static const double NOT_A_TIME{ANY_TIMES.back() + 1.0}; inline std::vector AnyTimesString() { @@ -66,22 +83,27 @@ inline std::vector AnyTimesString() { return retval; } static const std::vector ANY_TIMES_STRING{ - AnyTimesString()[0], AnyTimesString()[1], AnyTimesString()[2]}; -static const char* ANY_TIME_STRING{ANY_TIMES_STRING[0].c_str()}; -static const char* ANOTHER_TIME_STRING{ANY_TIMES_STRING[1].c_str()}; -static const char* THIRD_TIME_STRING{ANY_TIMES_STRING[2].c_str()}; + AnyTimesString()[ANY_INDEX], AnyTimesString()[ANOTHER_INDEX], + AnyTimesString()[THIRD_INDEX]}; +static const char* ANY_TIME_STRING{ANY_TIMES_STRING[ANY_TIME_INDEX].c_str()}; +static const char* ANOTHER_TIME_STRING{ + ANY_TIMES_STRING[ANOTHER_TIME_INDEX].c_str()}; +static const char* THIRD_TIME_STRING{ + ANY_TIMES_STRING[THIRD_TIME_INDEX].c_str()}; static const char* NOT_A_TIME_STRING{"NOT_A_TIME"}; static const std::vector ANY_ATTRIBUTES{"V_m", "g_e", "g_i"}; -static const char* ANY_ATTRIBUTE{ANY_ATTRIBUTES[0].c_str()}; -static const char* ANOTHER_ATTRIBUTE{ANY_ATTRIBUTES[1].c_str()}; -static const char* THIRD_ATTRIBUTE{ANY_ATTRIBUTES[2].c_str()}; +static const char* ANY_ATTRIBUTE{ANY_ATTRIBUTES[ANY_ATTRIBUTE_INDEX].c_str()}; +static const char* ANOTHER_ATTRIBUTE{ + ANY_ATTRIBUTES[ANOTHER_ATTRIBUTE_INDEX].c_str()}; +static const char* THIRD_ATTRIBUTE{ + ANY_ATTRIBUTES[THIRD_ATTRIBUTE_INDEX].c_str()}; static const char* NOT_AN_ATTRIBUTE{"NOT_AN_ATTRIBUTE"}; static const std::vector ANY_IDS{"1", "2", "3"}; -static const char* ANY_ID{ANY_IDS[0].c_str()}; -static const char* ANOTHER_ID{ANY_IDS[1].c_str()}; -static const char* THIRD_ID{ANY_IDS[2].c_str()}; +static const char* ANY_ID{ANY_IDS[ANY_ID_INDEX].c_str()}; +static const char* ANOTHER_ID{ANY_IDS[ANOTHER_ID_INDEX].c_str()}; +static const char* THIRD_ID{ANY_IDS[THIRD_ID_INDEX].c_str()}; static const char* NOT_AN_ID{"NOT_AN_ID"}; // clang-format off @@ -91,22 +113,36 @@ static const std::vector ANY_VALUES{ 0.311, 0.312, 0.313, 0.321, 0.322, 0.323, 0.331, 0.332, 0.333}; // clang-format on static const double ANY_VALUE{ANY_VALUES[0]}; +static const std::vector ANY_VALUES_FOR_ATTRIBUTES{ + ANY_VALUES[0], ANY_VALUES[3], ANY_VALUES[6]}; + static const std::size_t TIME_STRIDE{9}; static const std::size_t ATTRIBUTE_STRIDE{3}; static const std::size_t ID_STRIDE{1}; -static const std::size_t ANY_TIME_OFFSET{0 * niv::testing::TIME_STRIDE}; -static const std::size_t ANOTHER_TIME_OFFSET{1 * niv::testing::TIME_STRIDE}; -static const std::size_t THIRD_TIME_OFFSET{2 * niv::testing::TIME_STRIDE}; +inline double ValueAt(std::size_t time_id, std::size_t attribute_id, + std::size_t neuron_id) { + const std::size_t index = time_id * TIME_STRIDE + + attribute_id * ATTRIBUTE_STRIDE + + neuron_id * ID_STRIDE; + return ANY_VALUES[index]; +} + +static const std::size_t ANY_TIME_OFFSET{ANY_INDEX * niv::testing::TIME_STRIDE}; +static const std::size_t ANOTHER_TIME_OFFSET{ANOTHER_INDEX * + niv::testing::TIME_STRIDE}; +static const std::size_t THIRD_TIME_OFFSET{THIRD_INDEX * + niv::testing::TIME_STRIDE}; static const std::vector TIME_OFFSETS{ ANY_TIME_OFFSET, ANOTHER_TIME_OFFSET, THIRD_TIME_OFFSET}; static const std::size_t ANOTHER_ATTRIBUTE_OFFSET{ 1 * niv::testing::ATTRIBUTE_STRIDE}; -static const std::size_t ANY_ID_OFFSET{0 * niv::testing::ID_STRIDE}; -static const std::size_t ANOTHER_ID_OFFSET{1 * niv::testing::ID_STRIDE}; -static const std::size_t THIRD_ID_OFFSET{2 * niv::testing::ID_STRIDE}; +static const std::size_t ANY_ID_OFFSET{ANY_INDEX * niv::testing::ID_STRIDE}; +static const std::size_t ANOTHER_ID_OFFSET{ANOTHER_INDEX * + niv::testing::ID_STRIDE}; +static const std::size_t THIRD_ID_OFFSET{THIRD_INDEX * niv::testing::ID_STRIDE}; static const std::vector ID_OFFSETS{ ANY_ID_OFFSET, ANOTHER_ID_OFFSET, THIRD_ID_OFFSET}; @@ -179,8 +215,6 @@ std::vector AnyValueNames(); std::string AnyMultimeterName(); -conduit::Node AnyNestData(); - void Send(const conduit::Node& node); conduit::Node AnyNode(); diff --git a/niv/src/nest_test_data.cpp b/niv/src/nest_test_data.cpp index b7b66e2..07a8bd8 100644 --- a/niv/src/nest_test_data.cpp +++ b/niv/src/nest_test_data.cpp @@ -59,28 +59,6 @@ std::vector ThirdAttributesValues(double time) { std::string AnyMultimeterName() { return "multimeter A"; } -conduit::Node AnyNestData() { - conduit::Node node; - niv::producer::NestMultimeter multimeter(AnyMultimeterName(), AnyValueNames(), - &node); - multimeter.SetRecordingTime(ANY_TIME); - for (auto i = 0u; i < AnyAttributesValues().size(); ++i) { - multimeter.Record(i, std::vector{AnyAttributesValues()[i], - AnotherAttributesValues()[i], - ThirdAttributesValues()[i]}); - } - - multimeter.SetRecordingTime(ANOTHER_TIME); - for (auto i = 0u; i < AnyAttributesValues().size(); ++i) { - multimeter.Record( - i, std::vector{AnyAttributesValues(ANOTHER_TIME)[i], - AnotherAttributesValues(ANOTHER_TIME)[i], - ThirdAttributesValues(ANOTHER_TIME)[i]}); - } - - return node; -} - void Send(const conduit::Node& node) { exchange::RelaySharedMemory relay; relay.Send(node); diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index 69ff838..f2d9890 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -80,15 +80,15 @@ Vector::EqualsApproxMatcher EqualsApprox(std::vector const& comparator) { SCENARIO("A consumer::Device can list its timesteps", "[niv][niv::consumer][niv::consumer::Device]") { GIVEN("A device accessing a node") { - conduit::Node any_data{niv::testing::AnyNestData()}; + conduit::Node any_data{niv::testing::ANY_NEST_DATA}; ::Device device(niv::testing::AnyMultimeterName()); device.SetNode(&any_data); WHEN("The device is asked for the timesteps") { auto timesteps(device.GetTimesteps()); THEN("the list of timesteps is correct") { REQUIRE_THAT(timesteps, - Catch::Matchers::EqualsApprox(std::vector{ - niv::testing::ANY_TIME, niv::testing::ANOTHER_TIME})); + Catch::Matchers::EqualsApprox( + std::vector{niv::testing::ANY_TIMES})); } } } diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index 9f769a0..f001795 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -35,12 +35,12 @@ SCENARIO("Consumer integration", "[niv][integration]") { niv::consumer::Receiver receiver; backend.Connect(&receiver); - niv::consumer::NestMultimeter multimeter(niv::testing::AnyMultimeterName()); - multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); + niv::consumer::NestMultimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetAttribute(niv::testing::ANY_ATTRIBUTE); backend.Connect(&multimeter); WHEN("The data producer sends data") { - niv::testing::Send(niv::testing::AnyNestData()); + niv::testing::Send(niv::testing::ANY_NEST_DATA); WHEN("the consuming side receives") { backend.Receive(); @@ -55,9 +55,28 @@ SCENARIO("Consumer integration", "[niv][integration]") { std::vector values_at_t1{multimeter.GetValues()}; THEN("the received values are correct") { - REQUIRE(values_at_t0 == niv::testing::AnyAttributesValues()); - REQUIRE(values_at_t1 == niv::testing::AnyAttributesValues( - niv::testing::ANOTHER_TIME)); + const std::vector expected_at_t0{ + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANOTHER_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::THIRD_ID_INDEX)}; + REQUIRE(values_at_t0 == expected_at_t0); + const std::vector expected_at_t1{ + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANOTHER_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::THIRD_ID_INDEX)}; + REQUIRE(values_at_t1 == expected_at_t1); } } } diff --git a/niv/tests/src/consumer/test_nest_multimeter.cpp b/niv/tests/src/consumer/test_nest_multimeter.cpp index 1c433ce..4460464 100644 --- a/niv/tests/src/consumer/test_nest_multimeter.cpp +++ b/niv/tests/src/consumer/test_nest_multimeter.cpp @@ -31,53 +31,87 @@ SCENARIO("a Multimeter provides access to data stored in a conduit node", "[niv][niv::consumer][niv::consumer::Multimeter]") { GIVEN("A Multimeter with some data") { - const conduit::Node nest_data{niv::testing::AnyNestData()}; + const conduit::Node nest_data{niv::testing::ANY_NEST_DATA}; niv::consumer::NestMultimeter multimeter(niv::testing::AnyMultimeterName()); multimeter.SetNode(&nest_data); WHEN("The time step is set") { multimeter.SetTime(niv::testing::ANY_TIME); WHEN("one attribute is queried") { - multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); + multimeter.SetAttribute(niv::testing::ANY_ATTRIBUTE); multimeter.Update(); auto result = multimeter.GetValues(); THEN("the result is correct") { - REQUIRE_THAT(result, Catch::Matchers::Equals( - niv::testing::AnyAttributesValues())); + const std::vector expected{ + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANOTHER_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::THIRD_ID_INDEX)}; + REQUIRE(result == expected); } } WHEN("another attribute is queried") { - multimeter.SetAttribute(niv::testing::AnyValueNames()[1]); + multimeter.SetAttribute(niv::testing::ANOTHER_ATTRIBUTE); multimeter.Update(); auto result = multimeter.GetValues(); THEN("the result is correct") { - REQUIRE_THAT(result, Catch::Matchers::Equals( - niv::testing::AnotherAttributesValues())); + const std::vector expected{ + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::ANOTHER_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::THIRD_ID_INDEX)}; + REQUIRE(result == expected); } } WHEN("The time step is set to another value") { multimeter.SetTime(niv::testing::ANOTHER_TIME); WHEN("one attribute is queried") { - multimeter.SetAttribute(niv::testing::AnyValueNames()[0]); + multimeter.SetAttribute(niv::testing::ANY_ATTRIBUTE); multimeter.Update(); auto result = multimeter.GetValues(); THEN("the result is correct") { - REQUIRE_THAT(result, Catch::Matchers::Equals( - niv::testing::AnyAttributesValues( - niv::testing::ANOTHER_TIME))); + const std::vector expected{ + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANOTHER_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::THIRD_ID_INDEX)}; + REQUIRE(result == expected); } } WHEN("another attribute is queried") { - multimeter.SetAttribute(niv::testing::AnyValueNames()[1]); + multimeter.SetAttribute(niv::testing::ANOTHER_ATTRIBUTE); multimeter.Update(); auto result = multimeter.GetValues(); THEN("the result is correct") { - REQUIRE_THAT(result, Catch::Matchers::Equals( - niv::testing::AnotherAttributesValues( - niv::testing::ANOTHER_TIME))); + const std::vector expected{ + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::ANOTHER_ID_INDEX), + niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::THIRD_ID_INDEX)}; + REQUIRE(result == expected); } } } diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 7e60731..2e74fbe 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -101,6 +101,22 @@ void expose() { EXPOSE_CONSTANT(ANY_MULTIMETER_NAME); EXPOSE_CONSTANT(NOT_A_MULTIMETER_NAME); + EXPOSE_CONSTANT(ANY_INDEX); + EXPOSE_CONSTANT(ANOTHER_INDEX); + EXPOSE_CONSTANT(THIRD_INDEX); + + EXPOSE_CONSTANT(ANY_TIME_INDEX); + EXPOSE_CONSTANT(ANOTHER_TIME_INDEX); + EXPOSE_CONSTANT(THIRD_TIME_INDEX); + + EXPOSE_CONSTANT(ANY_ATTRIBUTE_INDEX); + EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE_INDEX); + EXPOSE_CONSTANT(THIRD_ATTRIBUTE_INDEX); + + EXPOSE_CONSTANT(ANY_ID_INDEX); + EXPOSE_CONSTANT(ANOTHER_ID_INDEX); + EXPOSE_CONSTANT(THIRD_ID_INDEX); + EXPOSE_CONSTANT(ANY_TIME); EXPOSE_CONSTANT(ANOTHER_TIME); EXPOSE_CONSTANT(THIRD_TIME); @@ -135,6 +151,8 @@ void expose() { EXPOSE_CONSTANT(ANOTHER_ATTRIBUTE_OFFSET); EXPOSE_CONSTANT(THIRD_ID_OFFSET); + EXPOSE_CONSTANT(ANY_NEST_DATA); + def("TIME_OFFSETS", &pyniv::testing::TimeOffsets); def("ID_OFFSETS", &pyniv::testing::IdOffsets); def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, @@ -143,7 +161,6 @@ void expose() { def("ThirdAttributesValues", &niv::testing::ThirdAttributesValues); def("AnyValueNames", &pyniv::testing::AnyValueNames); def("AnyMultimeterName", &niv::testing::AnyMultimeterName); - def("AnyNestData", &niv::testing::AnyNestData); def("Send", &niv::testing::Send); def("AnyNode", &niv::testing::AnyNode); def("AnotherNode", &niv::testing::AnotherNode); @@ -151,6 +168,7 @@ void expose() { def("UpdatedNode", &niv::testing::UpdatedNode); def("ADifferentNode", &niv::testing::ADifferentNode); def("Equal", &pyniv::testing::Equal); + def("ValueAt", &niv::testing::ValueAt); } } // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index 0875ba2..dd1ce85 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -28,10 +28,9 @@ def __init__(self, name): pyniv.consumer.Device.__init__(self, name) def test_consumer_device_lists_timesteps(): - any_data = pyniv.testing.AnyNestData() + any_data = pyniv.testing.ANY_NEST_DATA device = Device(pyniv.testing.AnyMultimeterName()) device.SetNode(any_data) timesteps = device.GetTimesteps() - assert len(timesteps) == 2 - expected_timesteps = [pyniv.testing.ANY_TIME, pyniv.testing.ANOTHER_TIME] - assert np.isclose(timesteps, expected_timesteps).all() + assert len(timesteps) == len(pyniv.testing.ANY_TIMES) + assert np.isclose(timesteps, pyniv.testing.ANY_TIMES).all() diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index 032db38..06ec921 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -33,16 +33,36 @@ def test_integration_consumer(): multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) backend.Connect(multimeter) - pyniv.testing.Send(pyniv.testing.AnyNestData()) + pyniv.testing.Send(pyniv.testing.ANY_NEST_DATA) backend.Receive() multimeter.SetTime(pyniv.testing.ANY_TIME) multimeter.Update() values_at_t0 = multimeter.GetValues() - assert np.isclose(values_at_t0, pyniv.testing.AnyAttributesValues()).all() + expected_at_t0 = [ + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.ANY_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.ANOTHER_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.THIRD_ID_INDEX)] + assert np.isclose(values_at_t0, expected_at_t0).all() multimeter.SetTime(pyniv.testing.ANOTHER_TIME) multimeter.Update() values_at_t1 = multimeter.GetValues() - assert np.isclose(values_at_t1, pyniv.testing.AnyAttributesValues(pyniv.testing.ANOTHER_TIME)).all() + expected_at_t1 = [ + pyniv.testing.ValueAt(pyniv.testing.ANOTHER_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.ANY_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANOTHER_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.ANOTHER_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANOTHER_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.THIRD_ID_INDEX)] + assert np.isclose(values_at_t0, expected_at_t1).all() diff --git a/pyniv/tests/src/consumer/test_nest_multimeter.py b/pyniv/tests/src/consumer/test_nest_multimeter.py index e899c35..2d8e24a 100644 --- a/pyniv/tests/src/consumer/test_nest_multimeter.py +++ b/pyniv/tests/src/consumer/test_nest_multimeter.py @@ -22,19 +22,39 @@ import pyniv def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): - nest_data = pyniv.testing.AnyNestData() + nest_data = pyniv.testing.ANY_NEST_DATA multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetNode(nest_data) multimeter.SetTime(pyniv.testing.ANY_TIME) - multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) + multimeter.SetAttribute(pyniv.testing.ANY_ATTRIBUTE) multimeter.Update() result = multimeter.GetValues() - assert (result == pyniv.testing.AnyAttributesValues()).all() + expected = [ + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.ANY_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.ANOTHER_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANY_ATTRIBUTE_INDEX, + pyniv.testing.THIRD_ID_INDEX)] + assert (result == expected).all() - multimeter.SetAttribute(pyniv.testing.AnyValueNames(1)) + multimeter.SetAttribute(pyniv.testing.ANOTHER_ATTRIBUTE) multimeter.Update() result = multimeter.GetValues() - assert (result == pyniv.testing.AnotherAttributesValues()).all() + expected = [ + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANOTHER_ATTRIBUTE_INDEX, + pyniv.testing.ANY_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANOTHER_ATTRIBUTE_INDEX, + pyniv.testing.ANOTHER_ID_INDEX), + pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, + pyniv.testing.ANOTHER_ATTRIBUTE_INDEX, + pyniv.testing.THIRD_ID_INDEX)] + assert (result == expected).all() From 806228845ff132676c2cd3b86ee4ebb485aaa44b Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Mar 2018 17:17:41 +0200 Subject: [PATCH 58/82] Make producer::NestMultimeter record a Datum --- niv/include/niv/producer/device.hpp | 13 +++- niv/include/niv/producer/nest_multimeter.hpp | 26 ++++++-- niv/src/producer/device.cpp | 3 +- niv/src/producer/nest_multimeter.cpp | 32 ++++++---- .../src/producer/test_nest_multimeter.cpp | 64 ++++++++++++------- 5 files changed, 95 insertions(+), 43 deletions(-) diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index ec292ce..9ce3d1e 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -41,6 +41,12 @@ namespace producer { class Device { public: + struct Datum { + using Device_t = Device; + + double time; + }; + Device(const Device&) = default; Device(Device&&) = default; virtual ~Device() = default; @@ -48,7 +54,10 @@ class Device { void SetRecordingTime(double time); virtual void Record(std::size_t); - virtual void Record(std::size_t, const std::vector&); + template + void Record(const Datum_t& datum) { + static_cast(this)->RecordImplementation(datum); + } Device& operator=(const Device&) = default; Device& operator=(Device&&) = default; @@ -62,6 +71,8 @@ class Device { conduit::Node& GetNode(const std::string& path); private: + void RecordImplementation(const Datum& datum); + conduit::Node* node_{nullptr}; conduit::Node* timestep_node_{nullptr}; std::string name_{"recorder"}; diff --git a/niv/include/niv/producer/nest_multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp index 08b4ed5..fe3a692 100644 --- a/niv/include/niv/producer/nest_multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -34,6 +34,19 @@ namespace producer { class NestMultimeter final : public Device { public: + struct Datum : public Device::Datum { + using Device_t = NestMultimeter; + + Datum(double time, std::string neuron_id, const std::vector& values) + : Device::Datum{time}, neuron_id{neuron_id}, values{values} {} + Datum(double time, std::size_t neuron_id, const std::vector& values) + : Device::Datum{time}, + neuron_id{NestMultimeter::IdString(neuron_id)}, + values{values} {} + std::string neuron_id; + std::vector values; + }; + NestMultimeter(const std::string& name, const std::vector& value_names, conduit::Node* node); @@ -41,8 +54,6 @@ class NestMultimeter final : public Device { NestMultimeter(NestMultimeter&&) = default; virtual ~NestMultimeter() = default; - void Record(std::size_t id, const std::vector& values) override; - NestMultimeter& operator=(const NestMultimeter&) = default; NestMultimeter& operator=(NestMultimeter&&) = default; @@ -50,13 +61,16 @@ class NestMultimeter final : public Device { const std::string& name, const std::vector& value_names, conduit::Node* node); + void Record(const Datum& datum) { RecordImplementation(datum); } + void RecordImplementation(const Datum& datum); + private: - void RecordValue(std::string id_string, const std::vector values, - std::size_t value_index); - std::string IdString(std::size_t id) const; + static std::string IdString(std::size_t id); + + std::string ConstructPath(const Datum& datum, std::size_t attribute_index); std::vector value_names_; -}; +}; // namespace producer } // namespace producer } // namespace niv diff --git a/niv/src/producer/device.cpp b/niv/src/producer/device.cpp index 7f22d31..0d64765 100644 --- a/niv/src/producer/device.cpp +++ b/niv/src/producer/device.cpp @@ -38,7 +38,8 @@ void Device::SetRecordingTime(double time) { } void Device::Record(std::size_t) {} -void Device::Record(std::size_t, const std::vector&) {} + +void Device::RecordImplementation(const Datum& /*datum*/) {} conduit::Node& Device::GetTimestepNode() { if (timestep_node_ == nullptr) { diff --git a/niv/src/producer/nest_multimeter.cpp b/niv/src/producer/nest_multimeter.cpp index b26904b..3ffde37 100644 --- a/niv/src/producer/nest_multimeter.cpp +++ b/niv/src/producer/nest_multimeter.cpp @@ -19,6 +19,8 @@ // limitations under the License. //------------------------------------------------------------------------------ +#include + #include #include #include @@ -33,27 +35,31 @@ NestMultimeter::NestMultimeter(const std::string& name, conduit::Node* node) : Device{name, node}, value_names_{value_names} {} -void NestMultimeter::Record(std::size_t id, const std::vector& values) { - const std::string id_string{IdString(id)}; - for (std::size_t i = 0; i < value_names_.size(); ++i) { - RecordValue(id_string, values, i); - } -} +void NestMultimeter::RecordImplementation(const Datum& datum) { + assert(datum.values.size() == value_names_.size()); -void NestMultimeter::RecordValue(std::string id_string, - const std::vector values, - std::size_t value_index) { - const std::string& value_name = value_names_[value_index]; - const double value = values[value_index]; - GetTimestepNode()[value_name][id_string] = value; + for (std::size_t i = 0u; i < datum.values.size(); ++i) { + const std::string path{ConstructPath(datum, i)}; + GetNode(path) = datum.values[i]; + } } -std::string NestMultimeter::IdString(std::size_t id) const { +std::string NestMultimeter::IdString(std::size_t id) { std::stringstream id_stream; id_stream << id; return id_stream.str(); } +std::string NestMultimeter::ConstructPath(const NestMultimeter::Datum& datum, + std::size_t attribute_index) { + std::stringstream path; + path << GetName() << '/'; + path << datum.time << '/'; + path << value_names_[attribute_index] << '/'; + path << datum.neuron_id; + return path.str(); +} + std::unique_ptr NestMultimeter::New( const std::string& name, const std::vector& value_names, conduit::Node* node) { diff --git a/niv/tests/src/producer/test_nest_multimeter.cpp b/niv/tests/src/producer/test_nest_multimeter.cpp index 86ee5e6..daf4c56 100644 --- a/niv/tests/src/producer/test_nest_multimeter.cpp +++ b/niv/tests/src/producer/test_nest_multimeter.cpp @@ -27,6 +27,7 @@ #include "conduit/conduit_node.hpp" +#include "niv/nest_test_data.hpp" #include "niv/producer/nest_multimeter.hpp" SCENARIO("A unique multimeter ptr can be constructed via its factory", @@ -39,30 +40,49 @@ SCENARIO("A unique multimeter ptr can be constructed via its factory", } } -SCENARIO("A multimeter records to a conduit node", "[niv][niv::Multimeter]") { - const std::string any_name{"multimeter1"}; - constexpr double any_time{1.5}; - const std::string any_time_string{"1.5"}; - constexpr std::size_t any_id{3}; - const std::string any_id_string{"3"}; - const std::vector any_value_names{"A", "B", "C"}; - const std::vector any_values{3.1415, 4.123, 42.0}; - - GIVEN("a conduit node and a multimeter") { +SCENARIO("A multimeter records to a conduit node", + "[niv][niv::NestMultimeter]") { + GIVEN("A conduit node and a multimeter") { conduit::Node node; - niv::producer::NestMultimeter multimeter(any_name, any_value_names, &node); + niv::producer::NestMultimeter multimeter{ + niv::testing::ANY_MULTIMETER_NAME, niv::testing::ANY_ATTRIBUTES, &node}; + WHEN("recording data") { + niv::producer::NestMultimeter::Datum datum{ + niv::testing::ANY_TIME, niv::testing::ANY_ID, + niv::testing::ANY_VALUES_FOR_ATTRIBUTES}; + multimeter.Record(datum); + THEN("data is properly recorded") { + std::stringstream path0; + path0 << niv::testing::ANY_MULTIMETER_NAME << '/'; + path0 << niv::testing::ANY_TIME << '/'; + path0 << niv::testing::ANY_ATTRIBUTE << '/'; + path0 << niv::testing::ANY_ID; + REQUIRE(node[path0.str()].as_double() == + Approx(niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANY_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX))); + + std::stringstream path1; + path1 << niv::testing::ANY_MULTIMETER_NAME << '/'; + path1 << niv::testing::ANY_TIME << '/'; + path1 << niv::testing::ANOTHER_ATTRIBUTE << '/'; + path1 << niv::testing::ANY_ID; + REQUIRE( + node[path1.str()].as_double() == + Approx(niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX))); - WHEN("setting the recording time") { - multimeter.SetRecordingTime(any_time); - WHEN("recording") { - multimeter.Record(any_id, any_values); - THEN("data is recorded in the node") { - for (std::size_t i = 0; i < any_value_names.size(); ++i) { - REQUIRE(node[any_name][any_time_string][any_value_names[i]] - [any_id_string] - .to_double() == Approx(any_values[i])); - } - } + std::stringstream path2; + path2 << niv::testing::ANY_MULTIMETER_NAME << '/'; + path2 << niv::testing::ANY_TIME << '/'; + path2 << niv::testing::THIRD_ATTRIBUTE << '/'; + path2 << niv::testing::ANY_ID; + REQUIRE( + node[path2.str()].as_double() == + Approx(niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, + niv::testing::THIRD_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX))); } } } From 976c5a12382cb5c43c5f7ea508f8883c7d9feafc Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Mar 2018 23:52:10 +0200 Subject: [PATCH 59/82] Extend test data --- niv/include/niv/nest_test_data.hpp | 23 +++++++++++++------ .../src/consumer/test_arbor_multimeter.cpp | 20 ++++++++-------- .../src/producer/test_arbor_multimeter.cpp | 2 +- pyniv/src/testing/__init__.py | 1 + pyniv/src/testing/nest_test_data.cpp | 5 ++++ .../src/consumer/test_arbor_multimeter.py | 20 ++++++++-------- 6 files changed, 43 insertions(+), 28 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index 1892e40..db7b0b4 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -50,6 +50,9 @@ namespace testing { static const char* ANY_MULTIMETER_NAME{"multimeter A"}; static const char* NOT_A_MULTIMETER_NAME{"NOT_A_MULTIMETER_NAME"}; +static const char* ANY_SPIKE_DETECTOR_NAME{"spikes A"}; +static const char* NOT_A_SPIKE_DETECTOR_NAME{"NOT_A_SPIKE_DETECTOR_NAME"}; + static const std::size_t ANY_INDEX{0}; static const std::size_t ANOTHER_INDEX{1}; static const std::size_t THIRD_INDEX{2}; @@ -83,8 +86,8 @@ inline std::vector AnyTimesString() { return retval; } static const std::vector ANY_TIMES_STRING{ - AnyTimesString()[ANY_INDEX], AnyTimesString()[ANOTHER_INDEX], - AnyTimesString()[THIRD_INDEX]}; + AnyTimesString()[ANY_TIME_INDEX], AnyTimesString()[ANOTHER_TIME_INDEX], + AnyTimesString()[THIRD_TIME_INDEX]}; static const char* ANY_TIME_STRING{ANY_TIMES_STRING[ANY_TIME_INDEX].c_str()}; static const char* ANOTHER_TIME_STRING{ ANY_TIMES_STRING[ANOTHER_TIME_INDEX].c_str()}; @@ -100,11 +103,17 @@ static const char* THIRD_ATTRIBUTE{ ANY_ATTRIBUTES[THIRD_ATTRIBUTE_INDEX].c_str()}; static const char* NOT_AN_ATTRIBUTE{"NOT_AN_ATTRIBUTE"}; -static const std::vector ANY_IDS{"1", "2", "3"}; -static const char* ANY_ID{ANY_IDS[ANY_ID_INDEX].c_str()}; -static const char* ANOTHER_ID{ANY_IDS[ANOTHER_ID_INDEX].c_str()}; -static const char* THIRD_ID{ANY_IDS[THIRD_ID_INDEX].c_str()}; -static const char* NOT_AN_ID{"NOT_AN_ID"}; +static const std::vector ANY_IDS{1ul, 2ul, 3ul}; +static const std::size_t ANY_ID{ANY_IDS[ANY_ID_INDEX]}; +static const std::size_t ANOTHER_ID{ANY_IDS[ANOTHER_ID_INDEX]}; +static const std::size_t THIRD_ID{ANY_IDS[THIRD_ID_INDEX]}; +static const std::size_t NOT_AN_ID{THIRD_ID + 1}; + +static const std::vector ANY_IDS_STRING{"1", "2", "3"}; +static const char* ANY_ID_STRING{ANY_IDS_STRING[ANY_ID_INDEX].c_str()}; +static const char* ANOTHER_ID_STRING{ANY_IDS_STRING[ANOTHER_ID_INDEX].c_str()}; +static const char* THIRD_ID_STRING{ANY_IDS_STRING[THIRD_ID_INDEX].c_str()}; +static const char* NOT_AN_ID_STRING{"NOT_AN_ID"}; // clang-format off static const std::vector ANY_VALUES{ diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 0d2eb67..e39717f 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -121,7 +121,7 @@ SCENARIO( auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, niv::testing::ANY_ATTRIBUTE)}; THEN("the multimeter provides the ids") { - REQUIRE(ids == niv::testing::ANY_IDS); + REQUIRE(ids == niv::testing::ANY_IDS_STRING); } } @@ -161,7 +161,7 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", WHEN("requesting data") { const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, - niv::testing::THIRD_ID); + niv::testing::THIRD_ID_STRING); THEN("it is correct") { const std::size_t DATUM_OFFSET{niv::testing::ANY_TIME_OFFSET + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + @@ -173,21 +173,21 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", WHEN("requesting datum at an invalid time") { const double datum = multimeter.GetDatum(niv::testing::NOT_A_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, - niv::testing::THIRD_ID); + niv::testing::THIRD_ID_STRING); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } WHEN("requesting datum for an invalid attribute") { const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::NOT_AN_ATTRIBUTE, - niv::testing::THIRD_ID); + niv::testing::THIRD_ID_STRING); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } WHEN("requesting datum for an invalid neuron id") { const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, - niv::testing::NOT_AN_ID); + niv::testing::NOT_AN_ID_STRING); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } } @@ -200,7 +200,7 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", WHEN("requesting data") { const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, - niv::testing::THIRD_ID); + niv::testing::THIRD_ID_STRING); THEN("nan is returned") { REQUIRE(std::isnan(datum)); } } @@ -226,7 +226,7 @@ SCENARIO("ArborMultimeter provides time series data", WHEN("requesting time series data for an attribute and a neuron id") { const std::vector values{multimeter.GetTimeSeriesData( - niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID)}; + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING)}; THEN("the time series is correct") { REQUIRE(values == expected); } } @@ -235,7 +235,7 @@ SCENARIO("ArborMultimeter provides time series data", "requesting time series data for an invalid attribute and a neuron " "id") { const std::vector values{multimeter.GetTimeSeriesData( - niv::testing::NOT_AN_ATTRIBUTE, niv::testing::THIRD_ID)}; + niv::testing::NOT_AN_ATTRIBUTE, niv::testing::THIRD_ID_STRING)}; THEN("the time series is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); @@ -246,7 +246,7 @@ SCENARIO("ArborMultimeter provides time series data", "requesting time series data for an attribute and an invalid neuron " "id") { const std::vector values{multimeter.GetTimeSeriesData( - niv::testing::ANOTHER_ATTRIBUTE, niv::testing::NOT_AN_ID)}; + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::NOT_AN_ID_STRING)}; THEN("the time series is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); @@ -261,7 +261,7 @@ SCENARIO("ArborMultimeter provides time series data", WHEN("requesting time series data for an attribute and a neuron id") { const std::vector values{multimeter.GetTimeSeriesData( - niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID)}; + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING)}; THEN("the time series is all nans or empty") { REQUIRE_THAT(values, VectorAllNanOrEmpty()); diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp index 44f2656..6d751bd 100644 --- a/niv/tests/src/producer/test_arbor_multimeter.cpp +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -40,7 +40,7 @@ SCENARIO("A multimeter records to a conduit node", WHEN("recording data") { niv::producer::ArborMultimeter::Datum datum{ niv::testing::ANY_TIME + niv::testing::ANY_TIME_OFFSET, - niv::testing::ANY_ATTRIBUTE, niv::testing::ANY_ID, + niv::testing::ANY_ATTRIBUTE, niv::testing::ANY_ID_STRING, niv::testing::ANY_VALUE}; multimeter.Record(datum, &node); THEN("the data is properly recorded") { diff --git a/pyniv/src/testing/__init__.py b/pyniv/src/testing/__init__.py index 782902b..dbc83a8 100644 --- a/pyniv/src/testing/__init__.py +++ b/pyniv/src/testing/__init__.py @@ -27,6 +27,7 @@ ANY_TIMES_STRING = [ANY_TIME_STRING, ANOTHER_TIME_STRING, THIRD_TIME_STRING]; ANY_ATTRIBUTES = [ANY_ATTRIBUTE, ANOTHER_ATTRIBUTE, THIRD_ATTRIBUTE]; ANY_IDS = [ANY_ID, ANOTHER_ID, THIRD_ID]; +ANY_IDS_STRING = [ANY_ID_STRING, ANOTHER_ID_STRING, THIRD_ID_STRING]; ANY_VALUES = np.array([ 0.111, 0.112, 0.113, 0.121, 0.122, 0.123, 0.131, 0.132, 0.133, 0.211, 0.212, 0.213, 0.221, 0.222, 0.223, 0.231, 0.232, 0.233, diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 2e74fbe..fc4c55f 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -137,6 +137,11 @@ void expose() { EXPOSE_CONSTANT(THIRD_ID); EXPOSE_CONSTANT(NOT_AN_ID); + EXPOSE_CONSTANT(ANY_ID_STRING); + EXPOSE_CONSTANT(ANOTHER_ID_STRING); + EXPOSE_CONSTANT(THIRD_ID_STRING); + EXPOSE_CONSTANT(NOT_AN_ID_STRING); + EXPOSE_CONSTANT(ANY_NEST_DATA); EXPOSE_CONSTANT(ANY_VALUE); diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index e8a77d4..cb4c208 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -56,7 +56,7 @@ def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): multimeter, nest_data = setup_multimeter() ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANY_ATTRIBUTE) - assert ids == pyniv.testing.ANY_IDS + assert ids == pyniv.testing.ANY_IDS_STRING ids = multimeter.GetNeuronIds(pyniv.testing.NOT_A_TIME_STRING, @@ -77,7 +77,7 @@ def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): multimeter, nest_data = setup_multimeter() datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) datum_offset = (pyniv.testing.ANY_TIME_OFFSET + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + pyniv.testing.THIRD_ID_OFFSET); @@ -85,24 +85,24 @@ def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): datum = multimeter.GetDatum(pyniv.testing.NOT_A_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) assert np.isnan(datum) datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.NOT_AN_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) assert np.isnan(datum) datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.NOT_AN_ID) + pyniv.testing.NOT_AN_ID_STRING) assert np.isnan(datum) multimeter, nest_data = setup_multimeter( name = pyniv.testing.NOT_A_MULTIMETER_NAME) datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) assert np.isnan(datum) def test_arbor_multimeter_provides_time_series_data(): @@ -114,21 +114,21 @@ def test_arbor_multimeter_provides_time_series_data(): multimeter, nest_data = setup_multimeter() values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) assert (values == expected).all() values = multimeter.GetTimeSeriesData(pyniv.testing.NOT_AN_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) assert np.isnan(values).all() values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.NOT_AN_ID) + pyniv.testing.NOT_AN_ID_STRING) assert np.isnan(values).all() multimeter, nest_data = setup_multimeter( name = pyniv.testing.NOT_A_MULTIMETER_NAME) values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, - pyniv.testing.THIRD_ID) + pyniv.testing.THIRD_ID_STRING) assert np.isnan(values).all() def test_arbor_multimeter_provides_timestep_data_for_all_neurons(): From 097893302cd6a56b8dbb8219d0c4378db66cb1e7 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Mar 2018 23:53:28 +0200 Subject: [PATCH 60/82] Use static polymorphism for Record --- niv/include/niv/producer/device.hpp | 14 +++++++++----- niv/include/niv/producer/nest_multimeter.hpp | 5 ++--- niv/src/producer/device.cpp | 4 ---- niv/src/producer/nest_multimeter.cpp | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index 9ce3d1e..a10f0c9 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -55,9 +55,7 @@ class Device { virtual void Record(std::size_t); template - void Record(const Datum_t& datum) { - static_cast(this)->RecordImplementation(datum); - } + void Record(const Datum_t& datum); Device& operator=(const Device&) = default; Device& operator=(Device&&) = default; @@ -71,13 +69,19 @@ class Device { conduit::Node& GetNode(const std::string& path); private: - void RecordImplementation(const Datum& datum); - conduit::Node* node_{nullptr}; conduit::Node* timestep_node_{nullptr}; std::string name_{"recorder"}; }; +template <> +inline void Device::Record(const Datum& /*datum*/) {} + +template +inline void Device::Record(const Datum_t& datum) { + static_cast(this)->Record(datum); +} + } // namespace producer } // namespace niv diff --git a/niv/include/niv/producer/nest_multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp index fe3a692..51f7537 100644 --- a/niv/include/niv/producer/nest_multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -52,7 +52,7 @@ class NestMultimeter final : public Device { conduit::Node* node); NestMultimeter(const NestMultimeter&) = default; NestMultimeter(NestMultimeter&&) = default; - virtual ~NestMultimeter() = default; + ~NestMultimeter() override = default; NestMultimeter& operator=(const NestMultimeter&) = default; NestMultimeter& operator=(NestMultimeter&&) = default; @@ -61,8 +61,7 @@ class NestMultimeter final : public Device { const std::string& name, const std::vector& value_names, conduit::Node* node); - void Record(const Datum& datum) { RecordImplementation(datum); } - void RecordImplementation(const Datum& datum); + void Record(const Datum& datum); private: static std::string IdString(std::size_t id); diff --git a/niv/src/producer/device.cpp b/niv/src/producer/device.cpp index 0d64765..1c336a5 100644 --- a/niv/src/producer/device.cpp +++ b/niv/src/producer/device.cpp @@ -37,10 +37,6 @@ void Device::SetRecordingTime(double time) { timestep_node_ = &(*node_)[name_][time_stream.str()]; } -void Device::Record(std::size_t) {} - -void Device::RecordImplementation(const Datum& /*datum*/) {} - conduit::Node& Device::GetTimestepNode() { if (timestep_node_ == nullptr) { SetRecordingTime(0.0); diff --git a/niv/src/producer/nest_multimeter.cpp b/niv/src/producer/nest_multimeter.cpp index 3ffde37..d9971a3 100644 --- a/niv/src/producer/nest_multimeter.cpp +++ b/niv/src/producer/nest_multimeter.cpp @@ -35,7 +35,7 @@ NestMultimeter::NestMultimeter(const std::string& name, conduit::Node* node) : Device{name, node}, value_names_{value_names} {} -void NestMultimeter::RecordImplementation(const Datum& datum) { +void NestMultimeter::Record(const Datum& datum) { assert(datum.values.size() == value_names_.size()); for (std::size_t i = 0u; i < datum.values.size(); ++i) { From d8bbf578fe27196fff9daac40ed7a00dcd80017f Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Mon, 26 Mar 2018 23:53:48 +0200 Subject: [PATCH 61/82] Implement SpikeDetector to use Datum --- niv/include/niv/producer/device.hpp | 1 - niv/include/niv/producer/spike_detector.hpp | 14 ++++++- niv/src/producer/spike_detector.cpp | 17 ++++++-- .../src/producer/test_spike_detector.cpp | 41 +++++++++---------- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index a10f0c9..17a2ec2 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -53,7 +53,6 @@ class Device { void SetRecordingTime(double time); - virtual void Record(std::size_t); template void Record(const Datum_t& datum); diff --git a/niv/include/niv/producer/spike_detector.hpp b/niv/include/niv/producer/spike_detector.hpp index 8f0a52d..9f3245f 100644 --- a/niv/include/niv/producer/spike_detector.hpp +++ b/niv/include/niv/producer/spike_detector.hpp @@ -33,20 +33,30 @@ namespace producer { class SpikeDetector final : public Device { public: + struct Datum : public Device::Datum { + using Device_t = SpikeDetector; + + Datum(double time, std::size_t neuron_id) + : Device::Datum{time}, neuron_id{neuron_id} {} + + std::size_t neuron_id; + }; + SpikeDetector(const std::string& name, conduit::Node* node); SpikeDetector(const SpikeDetector&) = default; SpikeDetector(SpikeDetector&&) = default; virtual ~SpikeDetector() = default; - void Record(std::size_t id) override; - SpikeDetector& operator=(const SpikeDetector&) = default; SpikeDetector& operator=(SpikeDetector&&) = default; + void Record(const Datum& datum); + static std::unique_ptr New(const std::string& name, conduit::Node* node); private: + std::string ConstructPath(const SpikeDetector::Datum& datum); std::vector GetData(const conduit::Node& node); std::vector AsVector(const conduit::uint64_array& array); }; diff --git a/niv/src/producer/spike_detector.cpp b/niv/src/producer/spike_detector.cpp index 1998ebe..349cc85 100644 --- a/niv/src/producer/spike_detector.cpp +++ b/niv/src/producer/spike_detector.cpp @@ -31,10 +31,19 @@ namespace producer { SpikeDetector::SpikeDetector(const std::string& name, conduit::Node* node) : Device{name, node} {} -void SpikeDetector::Record(std::size_t id) { - std::vector data(GetData(GetTimestepNode())); - data.push_back(id); - GetTimestepNode().set_uint64_vector(data); +void SpikeDetector::Record(const Datum& datum) { + const std::string path{ConstructPath(datum)}; + + std::vector data{GetData(GetNode(path))}; + data.push_back(datum.neuron_id); + GetNode(path).set_uint64_vector(data); +} + +std::string SpikeDetector::ConstructPath(const SpikeDetector::Datum& datum) { + std::stringstream path; + path << GetName() << '/'; + path << datum.time; + return path.str(); } std::vector SpikeDetector::GetData(const conduit::Node& node) { diff --git a/niv/tests/src/producer/test_spike_detector.cpp b/niv/tests/src/producer/test_spike_detector.cpp index 825e289..e817daa 100644 --- a/niv/tests/src/producer/test_spike_detector.cpp +++ b/niv/tests/src/producer/test_spike_detector.cpp @@ -26,6 +26,7 @@ #include "conduit/conduit_node.hpp" +#include "niv/nest_test_data.hpp" #include "niv/producer/spike_detector.hpp" SCENARIO("A unique spike detector ptr can be constructed via its factory", @@ -39,32 +40,28 @@ SCENARIO("A unique spike detector ptr can be constructed via its factory", SCENARIO("A spike detector records to a conduit node", "[niv][niv::SpikeDetector]") { - const std::string any_name{"spikes1"}; - constexpr double any_time{1.5}; - const std::string any_time_string{"1.5"}; - constexpr std::size_t any_id{3}; - constexpr std::size_t another_id{5}; - GIVEN("a conduit node and a spike detector") { conduit::Node node; - niv::producer::SpikeDetector spike_detector(any_name, &node); + niv::producer::SpikeDetector spike_detector( + niv::testing::ANY_SPIKE_DETECTOR_NAME, &node); - WHEN("setting the recording time") { - spike_detector.SetRecordingTime(any_time); - WHEN("recording") { - spike_detector.Record(any_id); + WHEN("recording") { + spike_detector.Record(niv::producer::SpikeDetector::Datum{ + niv::testing::ANY_TIME, niv::testing::ANY_ID}); + THEN("data is recorded in the node") { + const auto recorded_node = node[niv::testing::ANY_SPIKE_DETECTOR_NAME] + [niv::testing::ANY_TIME_STRING]; + REQUIRE(recorded_node.as_uint64_array()[0] == niv::testing::ANY_ID); + } + WHEN("recording another spike") { + spike_detector.Record( + {niv::testing::ANY_TIME, niv::testing::ANOTHER_ID}); THEN("data is recorded in the node") { - REQUIRE(node[any_name][any_time_string].as_uint64_array()[0] == - any_id); - } - WHEN("recording another spike") { - spike_detector.Record(another_id); - THEN("data is recorded in the node") { - REQUIRE(node[any_name][any_time_string].as_uint64_array()[0] == - any_id); - REQUIRE(node[any_name][any_time_string].as_uint64_array()[1] == - another_id); - } + const auto recorded_node = node[niv::testing::ANY_SPIKE_DETECTOR_NAME] + [niv::testing::ANY_TIME_STRING]; + REQUIRE(recorded_node.as_uint64_array()[0] == niv::testing::ANY_ID); + REQUIRE(recorded_node.as_uint64_array()[1] == + niv::testing::ANOTHER_ID); } } } From f04bfd1564df938f3b41775f89be019ffe70d3b1 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 00:02:35 +0200 Subject: [PATCH 62/82] Slightly refactor NestMultimeter::Datum --- niv/include/niv/producer/nest_multimeter.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/niv/include/niv/producer/nest_multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp index 51f7537..a397a16 100644 --- a/niv/include/niv/producer/nest_multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -40,9 +40,7 @@ class NestMultimeter final : public Device { Datum(double time, std::string neuron_id, const std::vector& values) : Device::Datum{time}, neuron_id{neuron_id}, values{values} {} Datum(double time, std::size_t neuron_id, const std::vector& values) - : Device::Datum{time}, - neuron_id{NestMultimeter::IdString(neuron_id)}, - values{values} {} + : Datum{time, NestMultimeter::IdString(neuron_id), values} {} std::string neuron_id; std::vector values; }; From 55e0a15c76747d57b50cc3a029ddc9c1c7bc12f1 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 00:08:47 +0200 Subject: [PATCH 63/82] Remove NestMultimeter's/SpkeDetector's New method --- niv/include/niv/producer/nest_multimeter.hpp | 4 ---- niv/include/niv/producer/spike_detector.hpp | 3 --- niv/src/producer/nest_multimeter.cpp | 6 ------ niv/src/producer/spike_detector.cpp | 5 ----- niv/tests/src/producer/test_nest_multimeter.cpp | 10 ---------- niv/tests/src/producer/test_spike_detector.cpp | 9 --------- 6 files changed, 37 deletions(-) diff --git a/niv/include/niv/producer/nest_multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp index a397a16..df4e64f 100644 --- a/niv/include/niv/producer/nest_multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -55,10 +55,6 @@ class NestMultimeter final : public Device { NestMultimeter& operator=(const NestMultimeter&) = default; NestMultimeter& operator=(NestMultimeter&&) = default; - static std::unique_ptr New( - const std::string& name, const std::vector& value_names, - conduit::Node* node); - void Record(const Datum& datum); private: diff --git a/niv/include/niv/producer/spike_detector.hpp b/niv/include/niv/producer/spike_detector.hpp index 9f3245f..c6097c0 100644 --- a/niv/include/niv/producer/spike_detector.hpp +++ b/niv/include/niv/producer/spike_detector.hpp @@ -52,9 +52,6 @@ class SpikeDetector final : public Device { void Record(const Datum& datum); - static std::unique_ptr New(const std::string& name, - conduit::Node* node); - private: std::string ConstructPath(const SpikeDetector::Datum& datum); std::vector GetData(const conduit::Node& node); diff --git a/niv/src/producer/nest_multimeter.cpp b/niv/src/producer/nest_multimeter.cpp index d9971a3..d52e890 100644 --- a/niv/src/producer/nest_multimeter.cpp +++ b/niv/src/producer/nest_multimeter.cpp @@ -60,11 +60,5 @@ std::string NestMultimeter::ConstructPath(const NestMultimeter::Datum& datum, return path.str(); } -std::unique_ptr NestMultimeter::New( - const std::string& name, const std::vector& value_names, - conduit::Node* node) { - return std::make_unique(name, value_names, node); -} - } // namespace producer } // namespace niv diff --git a/niv/src/producer/spike_detector.cpp b/niv/src/producer/spike_detector.cpp index 349cc85..57e3018 100644 --- a/niv/src/producer/spike_detector.cpp +++ b/niv/src/producer/spike_detector.cpp @@ -62,10 +62,5 @@ std::vector SpikeDetector::AsVector( return std::vector(begin, end); } -std::unique_ptr SpikeDetector::New(const std::string& name, - conduit::Node* node) { - return std::make_unique(name, node); -} - } // namespace producer } // namespace niv diff --git a/niv/tests/src/producer/test_nest_multimeter.cpp b/niv/tests/src/producer/test_nest_multimeter.cpp index daf4c56..06e2c13 100644 --- a/niv/tests/src/producer/test_nest_multimeter.cpp +++ b/niv/tests/src/producer/test_nest_multimeter.cpp @@ -30,16 +30,6 @@ #include "niv/nest_test_data.hpp" #include "niv/producer/nest_multimeter.hpp" -SCENARIO("A unique multimeter ptr can be constructed via its factory", - "[niv][niv::Multimeter]") { - WHEN("a new multimeter is constructed") { - std::unique_ptr multimeter{ - niv::producer::NestMultimeter::New("name", std::vector(), - nullptr)}; - THEN("a pointer was obtained") { REQUIRE(multimeter.get() != nullptr); } - } -} - SCENARIO("A multimeter records to a conduit node", "[niv][niv::NestMultimeter]") { GIVEN("A conduit node and a multimeter") { diff --git a/niv/tests/src/producer/test_spike_detector.cpp b/niv/tests/src/producer/test_spike_detector.cpp index e817daa..2b5a7c6 100644 --- a/niv/tests/src/producer/test_spike_detector.cpp +++ b/niv/tests/src/producer/test_spike_detector.cpp @@ -29,15 +29,6 @@ #include "niv/nest_test_data.hpp" #include "niv/producer/spike_detector.hpp" -SCENARIO("A unique spike detector ptr can be constructed via its factory", - "[niv][niv::SpikeDetector]") { - WHEN("a new spike detector is constructed") { - std::unique_ptr spike_detector{ - niv::producer::SpikeDetector::New("name", nullptr)}; - THEN("a pointer was obtained") { REQUIRE(spike_detector.get() != nullptr); } - } -} - SCENARIO("A spike detector records to a conduit node", "[niv][niv::SpikeDetector]") { GIVEN("a conduit node and a spike detector") { From 9389954f29f55d59a4daad9ed659fb270c513ff8 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 00:15:26 +0200 Subject: [PATCH 64/82] Get rid of Device TimestepNode stuff --- niv/include/niv/producer/device.hpp | 10 +++------- niv/src/producer/device.cpp | 13 ------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index 17a2ec2..d4686ec 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -47,29 +47,25 @@ class Device { double time; }; + Device() = delete; Device(const Device&) = default; Device(Device&&) = default; virtual ~Device() = default; - void SetRecordingTime(double time); + Device& operator=(const Device&) = default; + Device& operator=(Device&&) = default; template void Record(const Datum_t& datum); - Device& operator=(const Device&) = default; - Device& operator=(Device&&) = default; - protected: Device(const std::string& name, conduit::Node* node); - conduit::Node& GetTimestepNode(); - const std::string& GetName() { return name_; } conduit::Node& GetNode(const std::string& path); private: conduit::Node* node_{nullptr}; - conduit::Node* timestep_node_{nullptr}; std::string name_{"recorder"}; }; diff --git a/niv/src/producer/device.cpp b/niv/src/producer/device.cpp index 1c336a5..6ff3974 100644 --- a/niv/src/producer/device.cpp +++ b/niv/src/producer/device.cpp @@ -31,19 +31,6 @@ namespace producer { Device::Device(const std::string& name, conduit::Node* node) : node_(node), name_(name) {} -void Device::SetRecordingTime(double time) { - std::stringstream time_stream; - time_stream << time; - timestep_node_ = &(*node_)[name_][time_stream.str()]; -} - -conduit::Node& Device::GetTimestepNode() { - if (timestep_node_ == nullptr) { - SetRecordingTime(0.0); - } - return *timestep_node_; -} - conduit::Node& Device::GetNode(const std::string& path) { return (*node_)[path]; } From 336ab7b39bce43a5113ef298c9eab8dc7cb64405 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 00:17:56 +0200 Subject: [PATCH 65/82] Explicitely delete NestMultimeter's, SpikeDetector's default ctor --- niv/include/niv/producer/nest_multimeter.hpp | 1 + niv/include/niv/producer/spike_detector.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/niv/include/niv/producer/nest_multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp index df4e64f..1fd0b50 100644 --- a/niv/include/niv/producer/nest_multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -45,6 +45,7 @@ class NestMultimeter final : public Device { std::vector values; }; + NestMultimeter() = delete; NestMultimeter(const std::string& name, const std::vector& value_names, conduit::Node* node); diff --git a/niv/include/niv/producer/spike_detector.hpp b/niv/include/niv/producer/spike_detector.hpp index c6097c0..9163dd7 100644 --- a/niv/include/niv/producer/spike_detector.hpp +++ b/niv/include/niv/producer/spike_detector.hpp @@ -42,6 +42,7 @@ class SpikeDetector final : public Device { std::size_t neuron_id; }; + SpikeDetector() = delete; SpikeDetector(const std::string& name, conduit::Node* node); SpikeDetector(const SpikeDetector&) = default; SpikeDetector(SpikeDetector&&) = default; From 9f53fe8c767329fde65cb3041f6aa1088b3f2247 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 00:24:46 +0200 Subject: [PATCH 66/82] Move ConstructPath to sensible location(s) --- niv/include/niv/producer/device.hpp | 2 ++ niv/include/niv/producer/spike_detector.hpp | 3 +-- niv/src/producer/device.cpp | 7 +++++++ niv/src/producer/nest_multimeter.cpp | 3 +-- niv/src/producer/spike_detector.cpp | 7 ------- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index d4686ec..1e31d44 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -61,6 +61,8 @@ class Device { protected: Device(const std::string& name, conduit::Node* node); + std::string ConstructPath(const Datum& datum); + const std::string& GetName() { return name_; } conduit::Node& GetNode(const std::string& path); diff --git a/niv/include/niv/producer/spike_detector.hpp b/niv/include/niv/producer/spike_detector.hpp index 9163dd7..e186256 100644 --- a/niv/include/niv/producer/spike_detector.hpp +++ b/niv/include/niv/producer/spike_detector.hpp @@ -46,7 +46,7 @@ class SpikeDetector final : public Device { SpikeDetector(const std::string& name, conduit::Node* node); SpikeDetector(const SpikeDetector&) = default; SpikeDetector(SpikeDetector&&) = default; - virtual ~SpikeDetector() = default; + ~SpikeDetector() override = default; SpikeDetector& operator=(const SpikeDetector&) = default; SpikeDetector& operator=(SpikeDetector&&) = default; @@ -54,7 +54,6 @@ class SpikeDetector final : public Device { void Record(const Datum& datum); private: - std::string ConstructPath(const SpikeDetector::Datum& datum); std::vector GetData(const conduit::Node& node); std::vector AsVector(const conduit::uint64_array& array); }; diff --git a/niv/src/producer/device.cpp b/niv/src/producer/device.cpp index 6ff3974..911ef9d 100644 --- a/niv/src/producer/device.cpp +++ b/niv/src/producer/device.cpp @@ -31,6 +31,13 @@ namespace producer { Device::Device(const std::string& name, conduit::Node* node) : node_(node), name_(name) {} +std::string Device::ConstructPath(const Datum& datum) { + std::stringstream path; + path << name_ << '/'; + path << datum.time; + return path.str(); +} + conduit::Node& Device::GetNode(const std::string& path) { return (*node_)[path]; } diff --git a/niv/src/producer/nest_multimeter.cpp b/niv/src/producer/nest_multimeter.cpp index d52e890..db6fda2 100644 --- a/niv/src/producer/nest_multimeter.cpp +++ b/niv/src/producer/nest_multimeter.cpp @@ -53,8 +53,7 @@ std::string NestMultimeter::IdString(std::size_t id) { std::string NestMultimeter::ConstructPath(const NestMultimeter::Datum& datum, std::size_t attribute_index) { std::stringstream path; - path << GetName() << '/'; - path << datum.time << '/'; + path << Device::ConstructPath(datum) << '/'; path << value_names_[attribute_index] << '/'; path << datum.neuron_id; return path.str(); diff --git a/niv/src/producer/spike_detector.cpp b/niv/src/producer/spike_detector.cpp index 57e3018..164d206 100644 --- a/niv/src/producer/spike_detector.cpp +++ b/niv/src/producer/spike_detector.cpp @@ -39,13 +39,6 @@ void SpikeDetector::Record(const Datum& datum) { GetNode(path).set_uint64_vector(data); } -std::string SpikeDetector::ConstructPath(const SpikeDetector::Datum& datum) { - std::stringstream path; - path << GetName() << '/'; - path << datum.time; - return path.str(); -} - std::vector SpikeDetector::GetData(const conduit::Node& node) { if (node.total_bytes_allocated() != 0) { return AsVector(node.as_uint64_array()); From 79f23d01e6c221fc2ab88e2f5fd49e13785e3068 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 00:51:57 +0200 Subject: [PATCH 67/82] Make producer::ArborMultimeter a producer::Device --- niv/include/niv/producer/arbor_multimeter.hpp | 18 ++++++++++++------ niv/include/niv/producer/device.hpp | 4 +--- niv/include/niv/producer/nest_multimeter.hpp | 1 + niv/include/niv/producer/spike_detector.hpp | 2 ++ niv/src/producer/arbor_multimeter.cpp | 7 +++---- niv/src/producer/device.cpp | 7 +------ niv/src/producer/nest_multimeter.cpp | 4 ++-- niv/src/producer/spike_detector.cpp | 8 ++++---- 8 files changed, 26 insertions(+), 25 deletions(-) diff --git a/niv/include/niv/producer/arbor_multimeter.hpp b/niv/include/niv/producer/arbor_multimeter.hpp index 3f2e1df..9f6bf63 100644 --- a/niv/include/niv/producer/arbor_multimeter.hpp +++ b/niv/include/niv/producer/arbor_multimeter.hpp @@ -24,13 +24,21 @@ #include +#include "niv/producer/device.hpp" + namespace niv { namespace producer { -class ArborMultimeter final { +class ArborMultimeter final : public Device { public: - struct Datum { - double time; + struct Datum : public Device::Datum { + Datum(double time, std::string attribute, std::string id, double value) + : Device::Datum{std::round(10.0 * time) / 10.0}, + exact_time{time}, + attribute{attribute}, + id{id}, + value{value} {} + double exact_time; std::string attribute; std::string id; double value; @@ -49,9 +57,7 @@ class ArborMultimeter final { private: std::string ConstructPath(const Datum& datum); double ConstructTimestep(const Datum& datum); - - std::string name_; -}; +}; // namespace producer } // namespace producer } // namespace niv diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index 1e31d44..9abda46 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -59,15 +59,13 @@ class Device { void Record(const Datum_t& datum); protected: - Device(const std::string& name, conduit::Node* node); + explicit Device(const std::string& name); std::string ConstructPath(const Datum& datum); const std::string& GetName() { return name_; } - conduit::Node& GetNode(const std::string& path); private: - conduit::Node* node_{nullptr}; std::string name_{"recorder"}; }; diff --git a/niv/include/niv/producer/nest_multimeter.hpp b/niv/include/niv/producer/nest_multimeter.hpp index 1fd0b50..5fc5025 100644 --- a/niv/include/niv/producer/nest_multimeter.hpp +++ b/niv/include/niv/producer/nest_multimeter.hpp @@ -63,6 +63,7 @@ class NestMultimeter final : public Device { std::string ConstructPath(const Datum& datum, std::size_t attribute_index); + conduit::Node* node_; std::vector value_names_; }; // namespace producer diff --git a/niv/include/niv/producer/spike_detector.hpp b/niv/include/niv/producer/spike_detector.hpp index e186256..5b6a44b 100644 --- a/niv/include/niv/producer/spike_detector.hpp +++ b/niv/include/niv/producer/spike_detector.hpp @@ -56,6 +56,8 @@ class SpikeDetector final : public Device { private: std::vector GetData(const conduit::Node& node); std::vector AsVector(const conduit::uint64_array& array); + + conduit::Node* node_; }; } // namespace producer diff --git a/niv/src/producer/arbor_multimeter.cpp b/niv/src/producer/arbor_multimeter.cpp index 0d7ea64..6f0fcf7 100644 --- a/niv/src/producer/arbor_multimeter.cpp +++ b/niv/src/producer/arbor_multimeter.cpp @@ -33,19 +33,18 @@ namespace niv { namespace producer { -ArborMultimeter::ArborMultimeter(const std::string& name) : name_{name} {} +ArborMultimeter::ArborMultimeter(const std::string& name) : Device{name} {} void ArborMultimeter::Record(const ArborMultimeter::Datum& datum, conduit::Node* node) { const std::string path{ConstructPath(datum)}; - (*node)[path] = datum.value; + node->fetch(path) = datum.value; } std::string ArborMultimeter::ConstructPath( const ArborMultimeter::Datum& datum) { std::stringstream path; - path << name_ << '/'; - path << ConstructTimestep(datum) << '/'; + path << Device::ConstructPath(datum) << '/'; path << datum.attribute << '/'; path << datum.id; return path.str(); diff --git a/niv/src/producer/device.cpp b/niv/src/producer/device.cpp index 911ef9d..41fc749 100644 --- a/niv/src/producer/device.cpp +++ b/niv/src/producer/device.cpp @@ -28,8 +28,7 @@ namespace niv { namespace producer { -Device::Device(const std::string& name, conduit::Node* node) - : node_(node), name_(name) {} +Device::Device(const std::string& name) : name_(name) {} std::string Device::ConstructPath(const Datum& datum) { std::stringstream path; @@ -38,9 +37,5 @@ std::string Device::ConstructPath(const Datum& datum) { return path.str(); } -conduit::Node& Device::GetNode(const std::string& path) { - return (*node_)[path]; -} - } // namespace producer } // namespace niv diff --git a/niv/src/producer/nest_multimeter.cpp b/niv/src/producer/nest_multimeter.cpp index db6fda2..f319921 100644 --- a/niv/src/producer/nest_multimeter.cpp +++ b/niv/src/producer/nest_multimeter.cpp @@ -33,14 +33,14 @@ namespace producer { NestMultimeter::NestMultimeter(const std::string& name, const std::vector& value_names, conduit::Node* node) - : Device{name, node}, value_names_{value_names} {} + : Device{name}, node_{node}, value_names_{value_names} {} void NestMultimeter::Record(const Datum& datum) { assert(datum.values.size() == value_names_.size()); for (std::size_t i = 0u; i < datum.values.size(); ++i) { const std::string path{ConstructPath(datum, i)}; - GetNode(path) = datum.values[i]; + node_->fetch(path) = datum.values[i]; } } diff --git a/niv/src/producer/spike_detector.cpp b/niv/src/producer/spike_detector.cpp index 164d206..118125f 100644 --- a/niv/src/producer/spike_detector.cpp +++ b/niv/src/producer/spike_detector.cpp @@ -29,14 +29,14 @@ namespace niv { namespace producer { SpikeDetector::SpikeDetector(const std::string& name, conduit::Node* node) - : Device{name, node} {} + : Device{name}, node_{node} {} void SpikeDetector::Record(const Datum& datum) { - const std::string path{ConstructPath(datum)}; + auto& recording_node = node_->fetch(ConstructPath(datum)); - std::vector data{GetData(GetNode(path))}; + std::vector data{GetData(recording_node)}; data.push_back(datum.neuron_id); - GetNode(path).set_uint64_vector(data); + recording_node.set_uint64_vector(data); } std::vector SpikeDetector::GetData(const conduit::Node& node) { From 2d09658043241a6ec8993e5fc54e9f450cc8b14d Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 06:49:34 +0200 Subject: [PATCH 68/82] Slightly streamline producer::ArborMultimeter::Datum --- niv/include/niv/producer/arbor_multimeter.hpp | 7 ++++--- niv/src/producer/arbor_multimeter.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/niv/include/niv/producer/arbor_multimeter.hpp b/niv/include/niv/producer/arbor_multimeter.hpp index 9f6bf63..2a753c8 100644 --- a/niv/include/niv/producer/arbor_multimeter.hpp +++ b/niv/include/niv/producer/arbor_multimeter.hpp @@ -33,7 +33,7 @@ class ArborMultimeter final : public Device { public: struct Datum : public Device::Datum { Datum(double time, std::string attribute, std::string id, double value) - : Device::Datum{std::round(10.0 * time) / 10.0}, + : Device::Datum{ConstructTimestep(time)}, exact_time{time}, attribute{attribute}, id{id}, @@ -42,6 +42,8 @@ class ArborMultimeter final : public Device { std::string attribute; std::string id; double value; + + static double ConstructTimestep(double time); }; explicit ArborMultimeter(const std::string& name); @@ -56,8 +58,7 @@ class ArborMultimeter final : public Device { private: std::string ConstructPath(const Datum& datum); - double ConstructTimestep(const Datum& datum); -}; // namespace producer +}; } // namespace producer } // namespace niv diff --git a/niv/src/producer/arbor_multimeter.cpp b/niv/src/producer/arbor_multimeter.cpp index 6f0fcf7..b36684a 100644 --- a/niv/src/producer/arbor_multimeter.cpp +++ b/niv/src/producer/arbor_multimeter.cpp @@ -50,8 +50,8 @@ std::string ArborMultimeter::ConstructPath( return path.str(); } -double ArborMultimeter::ConstructTimestep(const ArborMultimeter::Datum& datum) { - return std::round(10.0 * datum.time) / 10.0; +double ArborMultimeter::Datum::ConstructTimestep(const double time) { + return std::round(10.0 * time) / 10.0; } } // namespace producer From 5df5379ebe6a058b67d9c3784db753d10ed5d2c1 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 07:51:30 +0200 Subject: [PATCH 69/82] Move timestep listing to consumer::Device --- niv/include/niv/consumer/arbor_multimeter.hpp | 4 -- niv/include/niv/consumer/device.hpp | 9 +++- niv/include/niv/nest_test_data.hpp | 3 ++ niv/src/consumer/arbor_multimeter.cpp | 17 ++----- niv/src/consumer/device.cpp | 46 +++++++++++-------- .../src/consumer/test_arbor_multimeter.cpp | 2 +- niv/tests/src/consumer/test_device.cpp | 35 +++++++++----- pyniv/src/consumer/device.cpp | 14 +++--- pyniv/src/testing/nest_test_data.cpp | 3 ++ pyniv/tests/src/consumer/test_device.py | 5 +- 10 files changed, 75 insertions(+), 63 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 39e618f..572f713 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -40,8 +40,6 @@ class ArborMultimeter : public niv::consumer::Device { void Update() override; - std::vector GetTimestepsString() const; - std::vector GetAttributes(const std::string& time) const; std::vector GetNeuronIds(const std::string& time, @@ -66,9 +64,7 @@ class ArborMultimeter : public niv::consumer::Device { std::string ConstructPath(const std::string& time, const std::string& attribute) const; std::string ConstructPath(const std::string& time) const; - std::string ConstructPath() const; - std::vector GetChildNames(const std::string& path) const; double GetValue(const std::string& path) const; const conduit::Node* GetNode(const std::string& path) const; diff --git a/niv/include/niv/consumer/device.hpp b/niv/include/niv/consumer/device.hpp index 9eeb05b..df2d6fa 100644 --- a/niv/include/niv/consumer/device.hpp +++ b/niv/include/niv/consumer/device.hpp @@ -40,7 +40,8 @@ class Device { Device& operator=(const Device&) = default; Device& operator=(Device&&) = default; - const std::vector& GetTimesteps(); + std::vector GetTimestepsString() const; + const std::vector GetTimesteps() const; virtual void SetTime(double time); @@ -53,6 +54,12 @@ class Device { protected: explicit Device(const std::string& name); + std::vector GetChildNames(const std::string& path) const; + + const conduit::Node* GetNode(const std::string& path) const; + + std::string ConstructPath() const; + void SetTimestepNode(); const conduit::Node* GetTimestepNode() const; diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index db7b0b4..cb3d3aa 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -47,6 +47,9 @@ namespace testing { #pragma GCC diagnostic ignored "-Wunused-variable" #endif +static const char* ANY_DEVICE_NAME{"multimeter A"}; +static const char* NOT_A_DEVICE_NAME{"NOT_A_DEVICE_NAME"}; + static const char* ANY_MULTIMETER_NAME{"multimeter A"}; static const char* NOT_A_MULTIMETER_NAME{"NOT_A_MULTIMETER_NAME"}; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 92845d0..08c3564 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -36,10 +36,6 @@ ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} void ArborMultimeter::Update() {} -std::vector ArborMultimeter::GetTimestepsString() const { - return GetChildNames(ConstructPath()); -} - std::vector ArborMultimeter::GetAttributes( const std::string& time) const { return GetChildNames(ConstructPath(time)); @@ -80,7 +76,8 @@ double ArborMultimeter::GetDatum(const std::string& time, std::string ArborMultimeter::ConstructPath(const std::string& time, const std::string& attribute, const std::string& neuron_id) const { - return ConstructPath() + "/" + time + "/" + attribute + "/" + neuron_id; + return Device::ConstructPath() + "/" + time + "/" + attribute + "/" + + neuron_id; } std::string ArborMultimeter::ConstructPath(const std::string& time, @@ -89,15 +86,7 @@ std::string ArborMultimeter::ConstructPath(const std::string& time, } std::string ArborMultimeter::ConstructPath(const std::string& time) const { - return ConstructPath() + '/' + time; -} - -std::string ArborMultimeter::ConstructPath() const { return GetName(); } - -std::vector ArborMultimeter::GetChildNames( - const std::string& path) const { - const conduit::Node* node{GetNode(path)}; - return (node != nullptr) ? node->child_names() : std::vector(); + return Device::ConstructPath() + '/' + time; } double ArborMultimeter::GetValue(const std::string& path) const { diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index 25db0a0..f83fc66 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -21,11 +21,11 @@ #include "niv/consumer/device.hpp" +#include #include -#include - #include +#include #include #include @@ -34,30 +34,36 @@ namespace consumer { Device::Device(const std::string& name) : name_{name} {} -const std::vector& Device::GetTimesteps() { - timesteps_.clear(); +std::vector Device::GetTimestepsString() const { + return GetChildNames(ConstructPath()); +} + +const std::vector Device::GetTimesteps() const { + const auto timestep_strings{GetTimestepsString()}; + std::vector timesteps_double(timestep_strings.size(), std::nan("")); + std::transform(timestep_strings.begin(), timestep_strings.end(), + timesteps_double.begin(), [](const std::string& t) { + return std::strtof(t.c_str(), nullptr); + }); + return timesteps_double; +} + +std::vector Device::GetChildNames(const std::string& path) const { + const conduit::Node* node{GetNode(path)}; + return (node != nullptr) ? node->child_names() : std::vector(); +} - const conduit::Node* device_node{nullptr}; +const conduit::Node* Device::GetNode(const std::string& path) const { + const conduit::Node* node{nullptr}; try { - device_node = &node_->fetch_child(name_); + node = &GetRootNode()->fetch_child(path); } catch (...) { - return timesteps_; - } - - const std::string device_node_path{device_node->path()}; - for (auto i = 0u; i < device_node->number_of_children(); ++i) { - const conduit::Node& curr_child{device_node->child(i)}; - const std::string child_path{curr_child.path()}; - const std::string child_local_path{ - child_path.substr(device_node_path.size() + 1, - child_path.size() - device_node_path.size() - 1)}; - timesteps_.push_back(std::strtof(child_local_path.c_str(), nullptr)); } - - std::sort(timesteps_.begin(), timesteps_.end()); - return timesteps_; + return node; } +std::string Device::ConstructPath() const { return name_; } + void Device::SetTime(double time) { time_ = time; } void Device::SetTimestepNode() { diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index e39717f..d78eeb1 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -56,7 +56,7 @@ SCENARIO("ArborMultimeter lists the timesteps", THEN("the multimeter provides correct timesteps") { REQUIRE(multimeter.GetTimestepsString() == - niv::testing::AnyTimesString()); + niv::testing::ANY_TIMES_STRING); } } diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index f2d9890..2e97e86 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -77,19 +77,30 @@ Vector::EqualsApproxMatcher EqualsApprox(std::vector const& comparator) { } // namespace Matchers } // namespace Catch -SCENARIO("A consumer::Device can list its timesteps", +SCENARIO("NestMultimeter lists the timesteps", "[niv][niv::consumer][niv::consumer::Device]") { - GIVEN("A device accessing a node") { - conduit::Node any_data{niv::testing::ANY_NEST_DATA}; - ::Device device(niv::testing::AnyMultimeterName()); - device.SetNode(&any_data); - WHEN("The device is asked for the timesteps") { - auto timesteps(device.GetTimesteps()); - THEN("the list of timesteps is correct") { - REQUIRE_THAT(timesteps, - Catch::Matchers::EqualsApprox( - std::vector{niv::testing::ANY_TIMES})); - } + GIVEN("a device providing access to some data") { + ::Device device(niv::testing::ANY_DEVICE_NAME); + device.SetNode(&niv::testing::ANY_NEST_DATA); + + THEN("the device provides correct timesteps as strings") { + REQUIRE(device.GetTimestepsString() == niv::testing::ANY_TIMES_STRING); + } + THEN("the device provides correct timesteps as doubles") { + REQUIRE_THAT(device.GetTimesteps(), + Catch::Matchers::EqualsApprox(niv::testing::ANY_TIMES)); + } + } + + GIVEN("a device with an incorrect name providing access to some data") { + ::Device multimeter(niv::testing::NOT_A_DEVICE_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + THEN("the device does not provide timesteps as strings") { + REQUIRE(multimeter.GetTimestepsString().empty()); + } + THEN("the device does not provide timesteps as doubles") { + REQUIRE(multimeter.GetTimesteps().empty()); } } } diff --git a/pyniv/src/consumer/device.cpp b/pyniv/src/consumer/device.cpp index 56cf1c6..00b61e0 100644 --- a/pyniv/src/consumer/device.cpp +++ b/pyniv/src/consumer/device.cpp @@ -36,14 +36,12 @@ struct DeviceWrap : niv::consumer::Device, wrapper { explicit DeviceWrap(const std::string& name) : niv::consumer::Device(name) {} void Update() { this->get_override("Update")(); } - static boost::python::numpy::ndarray GetTimesteps( - niv::consumer::Device* device) { - auto& timesteps{device->GetTimesteps()}; - - return boost::python::numpy::from_data( - timesteps.data(), boost::python::numpy::dtype::get_builtin(), - boost::python::make_tuple(timesteps.size()), - boost::python::make_tuple(sizeof(double)), boost::python::object()); + boost::python::list GetTimesteps() { + boost::python::list ret_val; + for (auto t : Device::GetTimesteps()) { + ret_val.append(t); + } + return ret_val; } static void SetNodePointer(niv::consumer::Device* device, PyObject* node) { diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index fc4c55f..25b7ad6 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -98,6 +98,9 @@ boost::python::list IdOffsets() { template <> void expose() { + EXPOSE_CONSTANT(ANY_DEVICE_NAME); + EXPOSE_CONSTANT(NOT_A_DEVICE_NAME); + EXPOSE_CONSTANT(ANY_MULTIMETER_NAME); EXPOSE_CONSTANT(NOT_A_MULTIMETER_NAME); diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index dd1ce85..53233d3 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -28,9 +28,8 @@ def __init__(self, name): pyniv.consumer.Device.__init__(self, name) def test_consumer_device_lists_timesteps(): - any_data = pyniv.testing.ANY_NEST_DATA - device = Device(pyniv.testing.AnyMultimeterName()) - device.SetNode(any_data) + device = Device(pyniv.testing.ANY_DEVICE_NAME) + device.SetNode(pyniv.testing.ANY_NEST_DATA) timesteps = device.GetTimesteps() assert len(timesteps) == len(pyniv.testing.ANY_TIMES) assert np.isclose(timesteps, pyniv.testing.ANY_TIMES).all() From 7b5bce81adf7ff92196a316f8fa1b719076a589b Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 16:47:43 +0200 Subject: [PATCH 70/82] Split consumer::ArborMultimeter into Multimeter --- niv/include/niv/consumer/arbor_multimeter.hpp | 20 +--- niv/include/niv/consumer/device.hpp | 6 +- niv/include/niv/consumer/multimeter.hpp | 56 ++++++++++ niv/include/niv/consumer/nest_multimeter.hpp | 2 +- niv/src/consumer/arbor_multimeter.cpp | 23 +--- niv/src/consumer/backend.cpp | 6 +- niv/src/consumer/device.cpp | 4 + niv/src/consumer/multimeter.cpp | 48 ++++++++ .../src/consumer/test_arbor_multimeter.cpp | 104 ------------------ niv/tests/src/consumer/test_backend.cpp | 8 +- niv/tests/src/consumer/test_device.cpp | 4 +- niv/tests/src/consumer/test_multimeter.cpp | 101 +++++++++++++++++ pyniv/src/consumer/arbor_multimeter.cpp | 43 +------- pyniv/src/consumer/consumer.cpp | 2 + pyniv/src/consumer/device.cpp | 43 ++++---- pyniv/src/consumer/multimeter.cpp | 61 ++++++++++ .../src/consumer/test_arbor_multimeter.py | 44 -------- pyniv/tests/src/consumer/test_backend.py | 2 +- pyniv/tests/src/consumer/test_device.py | 21 +++- pyniv/tests/src/consumer/test_multimeter.py | 63 +++++++++++ 20 files changed, 396 insertions(+), 265 deletions(-) create mode 100644 niv/include/niv/consumer/multimeter.hpp create mode 100644 niv/src/consumer/multimeter.cpp create mode 100644 niv/tests/src/consumer/test_multimeter.cpp create mode 100644 pyniv/src/consumer/multimeter.cpp create mode 100644 pyniv/tests/src/consumer/test_multimeter.py diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 572f713..6dd54a6 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -25,25 +25,21 @@ #include #include -#include "niv/consumer/device.hpp" +#include "niv/consumer/multimeter.hpp" namespace niv { namespace consumer { -class ArborMultimeter : public niv::consumer::Device { +class ArborMultimeter : public niv::consumer::Multimeter { public: - ArborMultimeter() = default; + ArborMultimeter() = delete; explicit ArborMultimeter(const std::string& name); ArborMultimeter(const ArborMultimeter&) = default; ArborMultimeter(ArborMultimeter&&) = default; ~ArborMultimeter() = default; - void Update() override; - - std::vector GetAttributes(const std::string& time) const; - - std::vector GetNeuronIds(const std::string& time, - const std::string& attribute) const; + ArborMultimeter& operator=(const ArborMultimeter&) = default; + ArborMultimeter& operator=(ArborMultimeter&&) = default; std::vector GetTimestepData(const std::string& time, const std::string& attribute) const; @@ -54,16 +50,10 @@ class ArborMultimeter : public niv::consumer::Device { double GetDatum(const std::string& time, const std::string& attribute, const std::string& neuron_id) const; - ArborMultimeter& operator=(const ArborMultimeter&) = default; - ArborMultimeter& operator=(ArborMultimeter&&) = default; - private: std::string ConstructPath(const std::string& time, const std::string& attribute, const std::string& neuron_id) const; - std::string ConstructPath(const std::string& time, - const std::string& attribute) const; - std::string ConstructPath(const std::string& time) const; double GetValue(const std::string& path) const; diff --git a/niv/include/niv/consumer/device.hpp b/niv/include/niv/consumer/device.hpp index df2d6fa..35e04c7 100644 --- a/niv/include/niv/consumer/device.hpp +++ b/niv/include/niv/consumer/device.hpp @@ -33,6 +33,7 @@ namespace consumer { class Device { public: Device() = delete; + explicit Device(const std::string& name); Device(const Device&) = default; Device(Device&&) = default; virtual ~Device() = default; @@ -45,20 +46,17 @@ class Device { virtual void SetTime(double time); - virtual void Update() = 0; - void SetNode(const conduit::Node* node) { node_ = node; } void Print() const; protected: - explicit Device(const std::string& name); - std::vector GetChildNames(const std::string& path) const; const conduit::Node* GetNode(const std::string& path) const; std::string ConstructPath() const; + std::string ConstructPath(const std::string& time) const; void SetTimestepNode(); const conduit::Node* GetTimestepNode() const; diff --git a/niv/include/niv/consumer/multimeter.hpp b/niv/include/niv/consumer/multimeter.hpp new file mode 100644 index 0000000..8133157 --- /dev/null +++ b/niv/include/niv/consumer/multimeter.hpp @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_INCLUDE_NIV_CONSUMER_MULTIMETER_HPP_ +#define NIV_INCLUDE_NIV_CONSUMER_MULTIMETER_HPP_ + +#include +#include + +#include "niv/consumer/device.hpp" + +namespace niv { +namespace consumer { + +class Multimeter : public niv::consumer::Device { + public: + Multimeter() = delete; + explicit Multimeter(const std::string& name); + Multimeter(const Multimeter&) = default; + Multimeter(Multimeter&&) = default; + ~Multimeter() = default; + + Multimeter& operator=(const Multimeter&) = default; + Multimeter& operator=(Multimeter&&) = default; + + std::vector GetAttributes(const std::string& time) const; + std::vector GetNeuronIds(const std::string& time, + const std::string& attribute) const; + + protected: + std::string ConstructPath(const std::string& time, + const std::string& attribute) const; +}; + +} // namespace consumer +} // namespace niv + +#endif // NIV_INCLUDE_NIV_CONSUMER_MULTIMETER_HPP_ diff --git a/niv/include/niv/consumer/nest_multimeter.hpp b/niv/include/niv/consumer/nest_multimeter.hpp index 41fd408..28e5167 100644 --- a/niv/include/niv/consumer/nest_multimeter.hpp +++ b/niv/include/niv/consumer/nest_multimeter.hpp @@ -45,7 +45,7 @@ class NestMultimeter : public consumer::Device { void SetAttribute(const std::string& attribute); - void Update() override; + void Update(); const std::vector& GetValues() const; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 08c3564..d23cb3c 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -32,19 +32,7 @@ namespace niv { namespace consumer { -ArborMultimeter::ArborMultimeter(const std::string& name) : Device(name) {} - -void ArborMultimeter::Update() {} - -std::vector ArborMultimeter::GetAttributes( - const std::string& time) const { - return GetChildNames(ConstructPath(time)); -} - -std::vector ArborMultimeter::GetNeuronIds( - const std::string& time, const std::string& attribute) const { - return GetChildNames(ConstructPath(time, attribute)); -} +ArborMultimeter::ArborMultimeter(const std::string& name) : Multimeter(name) {} std::vector ArborMultimeter::GetTimestepData( const std::string& time, const std::string& attribute) const { @@ -80,15 +68,6 @@ std::string ArborMultimeter::ConstructPath(const std::string& time, neuron_id; } -std::string ArborMultimeter::ConstructPath(const std::string& time, - const std::string& attribute) const { - return ConstructPath(time) + '/' + attribute; -} - -std::string ArborMultimeter::ConstructPath(const std::string& time) const { - return Device::ConstructPath() + '/' + time; -} - double ArborMultimeter::GetValue(const std::string& path) const { const conduit::Node* node{GetNode(path)}; return (node != nullptr) ? node->as_double() : std::nan(""); diff --git a/niv/src/consumer/backend.cpp b/niv/src/consumer/backend.cpp index 9f3516a..b7aa331 100644 --- a/niv/src/consumer/backend.cpp +++ b/niv/src/consumer/backend.cpp @@ -45,9 +45,9 @@ void consumer::Backend::Receive() { receiver_->Receive(); } - for (auto device : devices_) { - device->Update(); - } + // for (auto device : devices_) { + // device->Update(); + //} } } // namespace niv diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index f83fc66..74a1b5c 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -64,6 +64,10 @@ const conduit::Node* Device::GetNode(const std::string& path) const { std::string Device::ConstructPath() const { return name_; } +std::string Device::ConstructPath(const std::string& time) const { + return Device::ConstructPath() + '/' + time; +} + void Device::SetTime(double time) { time_ = time; } void Device::SetTimestepNode() { diff --git a/niv/src/consumer/multimeter.cpp b/niv/src/consumer/multimeter.cpp new file mode 100644 index 0000000..752ff94 --- /dev/null +++ b/niv/src/consumer/multimeter.cpp @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "niv/consumer/multimeter.hpp" + +#include +#include + +namespace niv { +namespace consumer { + +Multimeter::Multimeter(const std::string& name) : Device(name) {} + +std::vector Multimeter::GetAttributes( + const std::string& time) const { + return GetChildNames(Device::ConstructPath(time)); +} + +std::vector Multimeter::GetNeuronIds( + const std::string& time, const std::string& attribute) const { + return GetChildNames(ConstructPath(time, attribute)); +} + +std::string Multimeter::ConstructPath(const std::string& time, + const std::string& attribute) const { + return Device::ConstructPath(time) + '/' + attribute; +} + +} // namespace consumer +} // namespace niv diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index d78eeb1..351d7c0 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -47,110 +47,6 @@ class VectorAllNanOrEmpty : public Catch::MatcherBase> { using Catch::Matchers::VectorAllNanOrEmpty; -SCENARIO("ArborMultimeter lists the timesteps", - "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { - GIVEN("a multimeter providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::ANY_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - - THEN("the multimeter provides correct timesteps") { - REQUIRE(multimeter.GetTimestepsString() == - niv::testing::ANY_TIMES_STRING); - } - } - - GIVEN("a multimeter with an incorrect name providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::NOT_A_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - - THEN("the multimeter does not provide timesteps") { - REQUIRE(multimeter.GetTimestepsString().empty()); - } - } -} - -SCENARIO("ArborMultimeter lists attributes for a timestep", - "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { - GIVEN("a multimeter providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::ANY_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - - WHEN("attributes are requested") { - auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME_STRING)}; - THEN("the multimeter provides the attributes") { - REQUIRE(attributes == niv::testing::ANY_ATTRIBUTES); - } - } - - WHEN("attributes are requested for an invalid timestep") { - auto attributes{ - multimeter.GetAttributes(niv::testing::NOT_A_TIME_STRING)}; - THEN("the multimeter does not provide attributes") { - REQUIRE(attributes.empty()); - } - } - } - - GIVEN("a multimeter with an incorrect name providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::NOT_A_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - - WHEN("attributes are requested") { - auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME_STRING)}; - THEN("the multimeter does not provide attributes") { - REQUIRE(attributes.empty()); - } - } - } -} - -SCENARIO( - "ArborMultimeter lists the neuron ids stored for an attribute in a " - "timestep", - "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { - GIVEN("a multimeter providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::ANY_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - - WHEN("neuron ids are requested") { - auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, - niv::testing::ANY_ATTRIBUTE)}; - THEN("the multimeter provides the ids") { - REQUIRE(ids == niv::testing::ANY_IDS_STRING); - } - } - - WHEN("neuron ids are requested for an invalid timestep") { - auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME_STRING, - niv::testing::ANY_ATTRIBUTE)}; - THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } - } - - WHEN("neuron ids are requested for an invalid attribute") { - auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, - niv::testing::NOT_AN_ATTRIBUTE)}; - THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } - } - } - - GIVEN("a multimeter with an incorrect name providing access to some data") { - niv::consumer::ArborMultimeter multimeter( - niv::testing::NOT_A_MULTIMETER_NAME); - multimeter.SetNode(&niv::testing::ANY_NEST_DATA); - - WHEN("neuron ids are requested") { - auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, - niv::testing::ANY_ATTRIBUTE)}; - THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } - } - } -} - SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { GIVEN("a multimeter providing access to some data") { diff --git a/niv/tests/src/consumer/test_backend.cpp b/niv/tests/src/consumer/test_backend.cpp index cea21b1..fea0995 100644 --- a/niv/tests/src/consumer/test_backend.cpp +++ b/niv/tests/src/consumer/test_backend.cpp @@ -42,7 +42,7 @@ class Receiver : public niv::consumer::Receiver { class Device : public niv::consumer::Device { public: Device() : niv::consumer::Device("any_name") {} - void Update() override { ++count_updates_; } + void Update() { ++count_updates_; } std::size_t GetCountUpdates() const { return count_updates_; } @@ -76,9 +76,9 @@ SCENARIO("A consumer::Backend feeds data into the connected devices", THEN("the receiver was updated twice") { REQUIRE(receiver.GetCountReceives() == 2); } - THEN("the device was updated once") { - REQUIRE(device.GetCountUpdates() == 1); - } + // THEN("the device was updated once") { + // REQUIRE(device.GetCountUpdates() == 1); + //} } } } diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index 2e97e86..491ff4b 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -38,8 +38,6 @@ class Device : public niv::consumer::Device { Device& operator=(const Device&) = delete; Device& operator=(Device&&) = delete; - - void Update() override {} }; } // namespace @@ -77,7 +75,7 @@ Vector::EqualsApproxMatcher EqualsApprox(std::vector const& comparator) { } // namespace Matchers } // namespace Catch -SCENARIO("NestMultimeter lists the timesteps", +SCENARIO("consumer::Device lists the timesteps", "[niv][niv::consumer][niv::consumer::Device]") { GIVEN("a device providing access to some data") { ::Device device(niv::testing::ANY_DEVICE_NAME); diff --git a/niv/tests/src/consumer/test_multimeter.cpp b/niv/tests/src/consumer/test_multimeter.cpp new file mode 100644 index 0000000..34fa515 --- /dev/null +++ b/niv/tests/src/consumer/test_multimeter.cpp @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "catch/catch.hpp" + +#include "niv/consumer/multimeter.hpp" +#include "niv/nest_test_data.hpp" + +SCENARIO("consumer::Multimeter lists attributes for a timestep", + "[niv][niv::consumer][niv::consumer::Multimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::Multimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("attributes are requested") { + auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME_STRING)}; + THEN("the multimeter provides the attributes") { + REQUIRE(attributes == niv::testing::ANY_ATTRIBUTES); + } + } + + WHEN("attributes are requested for an invalid timestep") { + auto attributes{ + multimeter.GetAttributes(niv::testing::NOT_A_TIME_STRING)}; + THEN("the multimeter does not provide attributes") { + REQUIRE(attributes.empty()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::Multimeter multimeter(niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("attributes are requested") { + auto attributes{multimeter.GetAttributes(niv::testing::ANY_TIME_STRING)}; + THEN("the multimeter does not provide attributes") { + REQUIRE(attributes.empty()); + } + } + } +} + +SCENARIO( + "Multimeter lists the neuron ids stored for an attribute in a " + "timestep", + "[niv][niv::consumer][niv::consumer::Multimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::Multimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("neuron ids are requested") { + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter provides the ids") { + REQUIRE(ids == niv::testing::ANY_IDS_STRING); + } + } + + WHEN("neuron ids are requested for an invalid timestep") { + auto ids{multimeter.GetNeuronIds(niv::testing::NOT_A_TIME_STRING, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } + } + + WHEN("neuron ids are requested for an invalid attribute") { + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, + niv::testing::NOT_AN_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::Multimeter multimeter(niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("neuron ids are requested") { + auto ids{multimeter.GetNeuronIds(niv::testing::ANY_TIME_STRING, + niv::testing::ANY_ATTRIBUTE)}; + THEN("the multimeter does not provide ids") { REQUIRE(ids.empty()); } + } + } +} diff --git a/pyniv/src/consumer/arbor_multimeter.cpp b/pyniv/src/consumer/arbor_multimeter.cpp index 939e0a8..3a0d8f5 100644 --- a/pyniv/src/consumer/arbor_multimeter.cpp +++ b/pyniv/src/consumer/arbor_multimeter.cpp @@ -30,37 +30,6 @@ namespace pyniv { namespace consumer { namespace arbor_multimeter { -boost::python::list GetTimestepsString( - const niv::consumer::ArborMultimeter& multimeter) { - boost::python::list retval; - const auto timesteps = multimeter.GetTimestepsString(); - for (auto t : timesteps) { - retval.append(t); - } - return retval; -} - -boost::python::list GetAttributes( - const niv::consumer::ArborMultimeter& multimeter, const std::string& time) { - boost::python::list retval; - const auto attributes = multimeter.GetAttributes(time); - for (auto a : attributes) { - retval.append(a); - } - return retval; -} - -boost::python::list GetNeuronIds( - const niv::consumer::ArborMultimeter& multimeter, const std::string& time, - const std::string& attribute) { - boost::python::list retval; - const auto ids = multimeter.GetNeuronIds(time, attribute); - for (auto i : ids) { - retval.append(i); - } - return retval; -} - boost::python::list GetTimeSeriesData( const niv::consumer::ArborMultimeter& multimeter, const std::string& attribute, const std::string& neuron_id) { @@ -86,17 +55,13 @@ boost::python::list GetTimestepData( template <> void expose() { - class_>( + class_>( "ArborMultimeter", init()) - .def("GetTimestepsString", - &pyniv::consumer::arbor_multimeter::GetTimestepsString) - .def("GetAttributes", &pyniv::consumer::arbor_multimeter::GetAttributes) - .def("GetNeuronIds", &pyniv::consumer::arbor_multimeter::GetNeuronIds) - .def("GetDatum", &niv::consumer::ArborMultimeter::GetDatum) + .def("GetTimestepData", + &pyniv::consumer::arbor_multimeter::GetTimestepData) .def("GetTimeSeriesData", &pyniv::consumer::arbor_multimeter::GetTimeSeriesData) - .def("GetTimestepData", - &pyniv::consumer::arbor_multimeter::GetTimestepData); + .def("GetDatum", &niv::consumer::ArborMultimeter::GetDatum); } } // namespace pyniv diff --git a/pyniv/src/consumer/consumer.cpp b/pyniv/src/consumer/consumer.cpp index b0127a8..42d6f67 100644 --- a/pyniv/src/consumer/consumer.cpp +++ b/pyniv/src/consumer/consumer.cpp @@ -24,6 +24,7 @@ #include "niv/consumer/arbor_multimeter.hpp" #include "niv/consumer/backend.hpp" #include "niv/consumer/device.hpp" +#include "niv/consumer/multimeter.hpp" #include "niv/consumer/nest_multimeter.hpp" #include "niv/consumer/receiver.hpp" @@ -34,6 +35,7 @@ BOOST_PYTHON_MODULE(_consumer) { pyniv::expose(); pyniv::expose(); + pyniv::expose(); pyniv::expose(); pyniv::expose(); } diff --git a/pyniv/src/consumer/device.cpp b/pyniv/src/consumer/device.cpp index 00b61e0..7b7b79a 100644 --- a/pyniv/src/consumer/device.cpp +++ b/pyniv/src/consumer/device.cpp @@ -31,34 +31,39 @@ SUPPRESS_WARNINGS_END namespace pyniv { namespace consumer { +namespace device { -struct DeviceWrap : niv::consumer::Device, wrapper { - explicit DeviceWrap(const std::string& name) : niv::consumer::Device(name) {} - void Update() { this->get_override("Update")(); } - - boost::python::list GetTimesteps() { - boost::python::list ret_val; - for (auto t : Device::GetTimesteps()) { - ret_val.append(t); - } - return ret_val; +boost::python::list GetTimesteps(const niv::consumer::Device& device) { + boost::python::list ret_val; + for (auto t : device.GetTimesteps()) { + ret_val.append(t); } + return ret_val; +} - static void SetNodePointer(niv::consumer::Device* device, PyObject* node) { - device->SetNode(boost::python::extract(node)); +boost::python::list GetTimestepsString(const niv::consumer::Device& device) { + boost::python::list retval; + const auto timesteps = device.GetTimestepsString(); + for (auto t : timesteps) { + retval.append(t); } -}; + return retval; +} + +static void SetNodePointer(niv::consumer::Device* device, PyObject* node) { + device->SetNode(boost::python::extract(node)); +} +} // namespace device } // namespace consumer template <> void expose() { - class_("Device", - init()) - .def("GetTimesteps", &pyniv::consumer::DeviceWrap::GetTimesteps) - .def("SetNode", &pyniv::consumer::DeviceWrap::SetNodePointer) - .def("SetTime", &niv::consumer::Device::SetTime) - .def("Update", pure_virtual(&niv::consumer::Device::Update)); + class_("Device", init()) + .def("GetTimestepsString", &pyniv::consumer::device::GetTimestepsString) + .def("GetTimesteps", &pyniv::consumer::device::GetTimesteps) + .def("SetNode", &pyniv::consumer::device::SetNodePointer) + .def("SetTime", &niv::consumer::Device::SetTime); } } // namespace pyniv diff --git a/pyniv/src/consumer/multimeter.cpp b/pyniv/src/consumer/multimeter.cpp new file mode 100644 index 0000000..44d779d --- /dev/null +++ b/pyniv/src/consumer/multimeter.cpp @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "pyniv.hpp" + +#include // NOLINT +#include "niv/consumer/multimeter.hpp" + +namespace pyniv { +namespace consumer { +namespace multimeter { + +boost::python::list GetAttributes(const niv::consumer::Multimeter& multimeter, + const std::string& time) { + boost::python::list ret_val; + for (auto v : multimeter.GetAttributes(time)) { + ret_val.append(v); + } + return ret_val; +} + +boost::python::list GetNeuronIds(const niv::consumer::Multimeter& multimeter, + const std::string& time, + const std::string& attribute) { + boost::python::list ret_val; + for (auto v : multimeter.GetNeuronIds(time, attribute)) { + ret_val.append(v); + } + return ret_val; +} + +} // namespace multimeter +} // namespace consumer + +template <> +void expose() { + class_>( + "Multimeter", init()) + .def("GetAttributes", &pyniv::consumer::multimeter::GetAttributes) + .def("GetNeuronIds", &pyniv::consumer::multimeter::GetNeuronIds); +} + +} // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_arbor_multimeter.py b/pyniv/tests/src/consumer/test_arbor_multimeter.py index cb4c208..d364aa3 100644 --- a/pyniv/tests/src/consumer/test_arbor_multimeter.py +++ b/pyniv/tests/src/consumer/test_arbor_multimeter.py @@ -29,50 +29,6 @@ def setup_multimeter(name = pyniv.testing.ANY_MULTIMETER_NAME, multimeter.SetNode(data) return multimeter, data -def test_arbor_multimeter_lists_the_timesteps(): - multimeter, nest_data = setup_multimeter() - timesteps = multimeter.GetTimestepsString(); - assert timesteps == pyniv.testing.ANY_TIMES_STRING - - multimeter, nest_data = setup_multimeter( - name = pyniv.testing.NOT_A_MULTIMETER_NAME) - timesteps = multimeter.GetTimestepsString(); - assert timesteps == [] - -def test_arbor_multimeter_lists_attributes_for_a_timestep(): - multimeter, nest_data = setup_multimeter() - attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME_STRING) - assert attributes == pyniv.testing.ANY_ATTRIBUTES - - attributes = multimeter.GetAttributes(pyniv.testing.NOT_A_TIME_STRING) - assert attributes == [] - - multimeter, nest_data = setup_multimeter( - name = pyniv.testing.NOT_A_MULTIMETER_NAME) - attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME_STRING) - assert attributes == [] - -def test_arbor_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): - multimeter, nest_data = setup_multimeter() - ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, - pyniv.testing.ANY_ATTRIBUTE) - assert ids == pyniv.testing.ANY_IDS_STRING - - - ids = multimeter.GetNeuronIds(pyniv.testing.NOT_A_TIME_STRING, - pyniv.testing.ANY_ATTRIBUTE) - assert ids == [] - - ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, - pyniv.testing.NOT_AN_ATTRIBUTE) - assert ids == [] - - multimeter, nest_data = setup_multimeter( - name = pyniv.testing.NOT_A_MULTIMETER_NAME) - ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, - pyniv.testing.ANY_ATTRIBUTE) - assert ids == [] - def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): multimeter, nest_data = setup_multimeter() datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, diff --git a/pyniv/tests/src/consumer/test_backend.py b/pyniv/tests/src/consumer/test_backend.py index 025bf25..294d49d 100644 --- a/pyniv/tests/src/consumer/test_backend.py +++ b/pyniv/tests/src/consumer/test_backend.py @@ -49,4 +49,4 @@ def test_pyniv_consumer_backend(): backend.Connect(device) backend.Receive() assert receiver.count_receives == 2 - assert device.count_updates == 1 + #assert device.count_updates == 1 diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index 53233d3..9257f2e 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -27,9 +27,18 @@ class Device(pyniv.consumer.Device): def __init__(self, name): pyniv.consumer.Device.__init__(self, name) -def test_consumer_device_lists_timesteps(): - device = Device(pyniv.testing.ANY_DEVICE_NAME) - device.SetNode(pyniv.testing.ANY_NEST_DATA) - timesteps = device.GetTimesteps() - assert len(timesteps) == len(pyniv.testing.ANY_TIMES) - assert np.isclose(timesteps, pyniv.testing.ANY_TIMES).all() +def setup_device(name = pyniv.testing.ANY_DEVICE_NAME, + data = pyniv.testing.ANY_NEST_DATA): + multimeter = pyniv.consumer.Device(name) + multimeter.SetNode(data) + return multimeter, data + +def test_multimeter_lists_the_timesteps(): + multimeter, nest_data = setup_device() + timesteps = multimeter.GetTimestepsString(); + assert timesteps == pyniv.testing.ANY_TIMES_STRING + + multimeter, nest_data = setup_device( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + timesteps = multimeter.GetTimestepsString(); + assert timesteps == [] diff --git a/pyniv/tests/src/consumer/test_multimeter.py b/pyniv/tests/src/consumer/test_multimeter.py new file mode 100644 index 0000000..afcf191 --- /dev/null +++ b/pyniv/tests/src/consumer/test_multimeter.py @@ -0,0 +1,63 @@ +#------------------------------------------------------------------------------- +# nest in situ vis +# +# Copyright (c) 2017-2018 RWTH Aachen University, Germany, +# Virtual Reality & Immersive Visualisation Group. +#------------------------------------------------------------------------------- +# License +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------- + +import pyniv + +def setup_multimeter(name = pyniv.testing.ANY_MULTIMETER_NAME, + data = pyniv.testing.ANY_NEST_DATA): + multimeter = pyniv.consumer.Multimeter(name) + multimeter.SetNode(data) + return multimeter, data + +def test_multimeter_lists_attributes_for_a_timestep(): + multimeter, nest_data = setup_multimeter() + attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME_STRING) + assert attributes == pyniv.testing.ANY_ATTRIBUTES + + attributes = multimeter.GetAttributes(pyniv.testing.NOT_A_TIME_STRING) + assert attributes == [] + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + attributes = multimeter.GetAttributes(pyniv.testing.ANY_TIME_STRING) + assert attributes == [] + +def test_multimeter_lists_neuron_ids_for_an_attribute_in_a_timestep(): + multimeter, nest_data = setup_multimeter() + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANY_ATTRIBUTE) + assert ids == pyniv.testing.ANY_IDS_STRING + + + ids = multimeter.GetNeuronIds(pyniv.testing.NOT_A_TIME_STRING, + pyniv.testing.ANY_ATTRIBUTE) + assert ids == [] + + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.NOT_AN_ATTRIBUTE) + assert ids == [] + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + ids = multimeter.GetNeuronIds(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANY_ATTRIBUTE) + assert ids == [] + From d0610312bf350e40eff4ba8bd0f165c7ebdd3b39 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 16:55:28 +0200 Subject: [PATCH 71/82] Move another two ArborMultimeter methods to Multimeter --- niv/include/niv/consumer/arbor_multimeter.hpp | 6 ------ niv/include/niv/consumer/multimeter.hpp | 3 +++ niv/src/consumer/arbor_multimeter.cpp | 16 ---------------- niv/src/consumer/multimeter.cpp | 6 ++++++ 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/niv/include/niv/consumer/arbor_multimeter.hpp b/niv/include/niv/consumer/arbor_multimeter.hpp index 6dd54a6..0f952e7 100644 --- a/niv/include/niv/consumer/arbor_multimeter.hpp +++ b/niv/include/niv/consumer/arbor_multimeter.hpp @@ -51,13 +51,7 @@ class ArborMultimeter : public niv::consumer::Multimeter { const std::string& neuron_id) const; private: - std::string ConstructPath(const std::string& time, - const std::string& attribute, - const std::string& neuron_id) const; - double GetValue(const std::string& path) const; - - const conduit::Node* GetNode(const std::string& path) const; }; } // namespace consumer diff --git a/niv/include/niv/consumer/multimeter.hpp b/niv/include/niv/consumer/multimeter.hpp index 8133157..c7e0fa5 100644 --- a/niv/include/niv/consumer/multimeter.hpp +++ b/niv/include/niv/consumer/multimeter.hpp @@ -48,6 +48,9 @@ class Multimeter : public niv::consumer::Device { protected: std::string ConstructPath(const std::string& time, const std::string& attribute) const; + std::string ConstructPath(const std::string& time, + const std::string& attribute, + const std::string& neuron_id) const; }; } // namespace consumer diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index d23cb3c..f5b2189 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -61,26 +61,10 @@ double ArborMultimeter::GetDatum(const std::string& time, return GetValue(ConstructPath(time, attribute, neuron_id)); } -std::string ArborMultimeter::ConstructPath(const std::string& time, - const std::string& attribute, - const std::string& neuron_id) const { - return Device::ConstructPath() + "/" + time + "/" + attribute + "/" + - neuron_id; -} - double ArborMultimeter::GetValue(const std::string& path) const { const conduit::Node* node{GetNode(path)}; return (node != nullptr) ? node->as_double() : std::nan(""); } -const conduit::Node* ArborMultimeter::GetNode(const std::string& path) const { - const conduit::Node* node{nullptr}; - try { - node = &GetRootNode()->fetch_child(path); - } catch (...) { - } - return node; -} - } // namespace consumer } // namespace niv diff --git a/niv/src/consumer/multimeter.cpp b/niv/src/consumer/multimeter.cpp index 752ff94..cc13a57 100644 --- a/niv/src/consumer/multimeter.cpp +++ b/niv/src/consumer/multimeter.cpp @@ -44,5 +44,11 @@ std::string Multimeter::ConstructPath(const std::string& time, return Device::ConstructPath(time) + '/' + attribute; } +std::string Multimeter::ConstructPath(const std::string& time, + const std::string& attribute, + const std::string& neuron_id) const { + return ConstructPath(time, attribute) + "/" + neuron_id; +} + } // namespace consumer } // namespace niv From 568068cbacbdddd1205ee2d67c9917b09d5c1d5c Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 23:27:00 +0200 Subject: [PATCH 72/82] Add datum, timestep and timeseries getters to NestMultimeter --- niv/include/niv/consumer/nest_multimeter.hpp | 15 +- niv/src/consumer/arbor_multimeter.cpp | 3 +- niv/src/consumer/nest_multimeter.cpp | 38 +++- .../src/consumer/test_arbor_multimeter.cpp | 20 +- .../src/consumer/test_nest_multimeter.cpp | 177 ++++++++++++++++++ .../vector_all_nan_or_empty.hpp | 48 +++++ 6 files changed, 278 insertions(+), 23 deletions(-) create mode 100644 niv/tests/test_utilities/vector_all_nan_or_empty.hpp diff --git a/niv/include/niv/consumer/nest_multimeter.hpp b/niv/include/niv/consumer/nest_multimeter.hpp index 28e5167..fb80653 100644 --- a/niv/include/niv/consumer/nest_multimeter.hpp +++ b/niv/include/niv/consumer/nest_multimeter.hpp @@ -27,12 +27,12 @@ #include "conduit/conduit_node.hpp" -#include "niv/consumer/device.hpp" +#include "niv/consumer/multimeter.hpp" namespace niv { namespace consumer { -class NestMultimeter : public consumer::Device { +class NestMultimeter : public consumer::Multimeter { public: NestMultimeter() = delete; explicit NestMultimeter(const std::string& name); @@ -43,6 +43,15 @@ class NestMultimeter : public consumer::Device { NestMultimeter& operator=(const NestMultimeter&) = default; NestMultimeter& operator=(NestMultimeter&&) = default; + std::vector GetTimestepData(const std::string& time, + const std::string& attribute) const; + + std::vector GetTimeSeriesData(const std::string& attribute, + const std::string& neuron_id) const; + + double GetDatum(const std::string& time, const std::string& attribute, + const std::string& neuron_id) const; + void SetAttribute(const std::string& attribute); void Update(); @@ -50,6 +59,8 @@ class NestMultimeter : public consumer::Device { const std::vector& GetValues() const; private: + double GetValue(const std::string& path) const; + void SetValues(); std::vector values_; diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index f5b2189..1568897 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -19,6 +19,8 @@ // limitations under the License. //------------------------------------------------------------------------------ +#include "niv/consumer/arbor_multimeter.hpp" + #include #include @@ -26,7 +28,6 @@ #include "conduit/conduit_node.hpp" -#include "niv/consumer/arbor_multimeter.hpp" #include "niv/nest_test_data.hpp" namespace niv { diff --git a/niv/src/consumer/nest_multimeter.cpp b/niv/src/consumer/nest_multimeter.cpp index 1e4df39..755f429 100644 --- a/niv/src/consumer/nest_multimeter.cpp +++ b/niv/src/consumer/nest_multimeter.cpp @@ -21,6 +21,8 @@ #include "niv/consumer/nest_multimeter.hpp" +#include + #include #include @@ -28,7 +30,41 @@ namespace niv { namespace consumer { NestMultimeter::NestMultimeter(const std::string& name) - : consumer::Device{name} {} + : consumer::Multimeter{name} {} + +std::vector NestMultimeter::GetTimestepData( + const std::string& time, const std::string& attribute) const { + std::vector retval; + const auto neuron_ids{GetNeuronIds(time, attribute)}; + for (auto curr_neuron_id : neuron_ids) { + retval.push_back(GetDatum(time, attribute, curr_neuron_id)); + } + return retval; +} + +std::vector NestMultimeter::GetTimeSeriesData( + const std::string& attribute, const std::string& neuron_id) const { + std::vector retval; + const auto timesteps = GetTimestepsString(); + retval.reserve(timesteps.size()); + for (auto time : timesteps) { + retval.push_back(GetDatum(time, attribute, neuron_id)); + } + return retval; +} + +double NestMultimeter::GetDatum(const std::string& time, + const std::string& attribute, + const std::string& neuron_id) const { + return GetValue(ConstructPath(time, attribute, neuron_id)); +} + +double NestMultimeter::GetValue(const std::string& path) const { + const conduit::Node* node{GetNode(path)}; + return (node != nullptr) ? node->as_double() : std::nan(""); +} + +// ------------------------------------------------------------ void NestMultimeter::SetAttribute(const std::string& attribute) { attribute_ = attribute; diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 351d7c0..c37c2ae 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -27,25 +27,7 @@ #include "niv/consumer/arbor_multimeter.hpp" #include "niv/nest_test_data.hpp" -namespace Catch { -namespace Matchers { - -class VectorAllNanOrEmpty : public Catch::MatcherBase> { - public: - bool match(const std::vector& values) const override { - bool retval = true; - for (double v : values) { - retval &= std::isnan(v); - } - return retval; - } - std::string describe() const override { return ""; } -}; - -} // namespace Matchers -} // namespace Catch - -using Catch::Matchers::VectorAllNanOrEmpty; +#include "test_utilities/vector_all_nan_or_empty.hpp" SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", "[niv][niv::consumer][niv::consumer::ArborMultimeter]") { diff --git a/niv/tests/src/consumer/test_nest_multimeter.cpp b/niv/tests/src/consumer/test_nest_multimeter.cpp index 4460464..38c29d2 100644 --- a/niv/tests/src/consumer/test_nest_multimeter.cpp +++ b/niv/tests/src/consumer/test_nest_multimeter.cpp @@ -28,6 +28,183 @@ #include "niv/consumer/nest_multimeter.hpp" #include "niv/nest_test_data.hpp" +#include "test_utilities/vector_all_nan_or_empty.hpp" + +SCENARIO("NestMultimeter retrieves datum for time, attribute, neuron", + "[niv][niv::consumer][niv::consumer::NestMultimeter]") { + GIVEN("a multimeter providing access to some data") { + niv::consumer::NestMultimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting data") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID_STRING); + THEN("it is correct") { + const std::size_t DATUM_OFFSET{niv::testing::ANY_TIME_OFFSET + + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + + niv::testing::THIRD_ID_OFFSET}; + REQUIRE(datum == Approx(niv::testing::ANY_VALUES[DATUM_OFFSET])); + } + } + + WHEN("requesting datum at an invalid time") { + const double datum = multimeter.GetDatum(niv::testing::NOT_A_TIME_STRING, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID_STRING); + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + + WHEN("requesting datum for an invalid attribute") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, + niv::testing::NOT_AN_ATTRIBUTE, + niv::testing::THIRD_ID_STRING); + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + + WHEN("requesting datum for an invalid neuron id") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::NOT_AN_ID_STRING); + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::NestMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting data") { + const double datum = multimeter.GetDatum(niv::testing::ANY_TIME_STRING, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID_STRING); + + THEN("nan is returned") { REQUIRE(std::isnan(datum)); } + } + } +} + +SCENARIO("NestMultimeter provides time series data", + "[niv][niv::consumer][niv::consumer::NestMultimeter]") { + std::vector expected; + for (auto time_offset : niv::testing::TIME_OFFSETS) { + const auto DATUM_INDEX{time_offset + + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + + niv::testing::THIRD_ID_OFFSET}; + expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + } + const std::vector nans(niv::testing::ANY_TIMES_STRING.size(), + std::nan("")); + + GIVEN("a multimeter providing access to some data") { + niv::consumer::NestMultimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time series data for an attribute and a neuron id") { + const std::vector values{multimeter.GetTimeSeriesData( + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING)}; + + THEN("the time series is correct") { REQUIRE(values == expected); } + } + + WHEN( + "requesting time series data for an invalid attribute and a neuron " + "id") { + const std::vector values{multimeter.GetTimeSeriesData( + niv::testing::NOT_AN_ATTRIBUTE, niv::testing::THIRD_ID_STRING)}; + + THEN("the time series is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + + WHEN( + "requesting time series data for an attribute and an invalid neuron " + "id") { + const std::vector values{multimeter.GetTimeSeriesData( + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::NOT_AN_ID_STRING)}; + + THEN("the time series is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::NestMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time series data for an attribute and a neuron id") { + const std::vector values{multimeter.GetTimeSeriesData( + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING)}; + + THEN("the time series is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + } +} + +SCENARIO("NestMultimeter provides timestep data for all neurons", + "[niv][niv::consumer][niv::consumer::NestMultimeter]") { + std::vector expected; + for (std::size_t i = 0; i < niv::testing::ANY_IDS.size(); ++i) { + const auto ID_OFFSET{i * niv::testing::ID_STRIDE}; + const auto DATUM_INDEX{niv::testing::THIRD_TIME_OFFSET + + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + ID_OFFSET}; + expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + } + + GIVEN("a multimeter providing access to some data") { + niv::consumer::NestMultimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time step data for an attribute") { + const std::vector values{multimeter.GetTimestepData( + niv::testing::THIRD_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE)}; + + THEN("the time step data is correct") { REQUIRE(values == expected); } + } + + WHEN("requesting time step data for an invalid time step") { + const std::vector values{multimeter.GetTimestepData( + niv::testing::NOT_A_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE)}; + + THEN("the time step data is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + + WHEN("requesting time step data for an invalid attribute") { + const std::vector values{multimeter.GetTimestepData( + niv::testing::THIRD_TIME_STRING, niv::testing::NOT_AN_ATTRIBUTE)}; + + THEN("the time step data is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + } + + GIVEN("a multimeter with an incorrect name providing access to some data") { + niv::consumer::NestMultimeter multimeter( + niv::testing::NOT_A_MULTIMETER_NAME); + multimeter.SetNode(&niv::testing::ANY_NEST_DATA); + + WHEN("requesting time step data for an attribute") { + const std::vector values{multimeter.GetTimestepData( + niv::testing::THIRD_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE)}; + + THEN("the time step data is all nans or empty") { + REQUIRE_THAT(values, VectorAllNanOrEmpty()); + } + } + } +} + +// ------------------------------------------------------------ + SCENARIO("a Multimeter provides access to data stored in a conduit node", "[niv][niv::consumer][niv::consumer::Multimeter]") { GIVEN("A Multimeter with some data") { diff --git a/niv/tests/test_utilities/vector_all_nan_or_empty.hpp b/niv/tests/test_utilities/vector_all_nan_or_empty.hpp new file mode 100644 index 0000000..5a8a89c --- /dev/null +++ b/niv/tests/test_utilities/vector_all_nan_or_empty.hpp @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_TESTS_TEST_UTILITIES_VECTOR_ALL_NAN_OR_EMPTY_HPP_ +#define NIV_TESTS_TEST_UTILITIES_VECTOR_ALL_NAN_OR_EMPTY_HPP_ + +#include +#include + +namespace Catch { +namespace Matchers { + +class VectorAllNanOrEmpty : public Catch::MatcherBase> { + public: + bool match(const std::vector& values) const override { + bool retval = true; + for (double v : values) { + retval &= std::isnan(v); + } + return retval; + } + std::string describe() const override { return ""; } +}; + +} // namespace Matchers +} // namespace Catch + +using Catch::Matchers::VectorAllNanOrEmpty; + +#endif // NIV_TESTS_TEST_UTILITIES_VECTOR_ALL_NAN_OR_EMPTY_HPP_ From 041f7f4b59d67eaa7b91271714a8641033b4e60e Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 23:51:01 +0200 Subject: [PATCH 73/82] Export missing functions --- pyniv/src/consumer/nest_multimeter.cpp | 32 ++++++- .../src/consumer/test_nest_multimeter.py | 93 +++++++++++++++++++ 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/pyniv/src/consumer/nest_multimeter.cpp b/pyniv/src/consumer/nest_multimeter.cpp index ee5a3cc..dc9f357 100644 --- a/pyniv/src/consumer/nest_multimeter.cpp +++ b/pyniv/src/consumer/nest_multimeter.cpp @@ -47,16 +47,44 @@ boost::python::numpy::ndarray GetValues( boost::python::make_tuple(sizeof(double)), boost::python::object()); } +namespace nest_multimeter { + +boost::python::list GetTimeSeriesData( + const niv::consumer::NestMultimeter& multimeter, + const std::string& attribute, const std::string& neuron_id) { + boost::python::list ret_val; + for (auto v : multimeter.GetTimeSeriesData(attribute, neuron_id)) { + ret_val.append(v); + } + return ret_val; +} + +boost::python::list GetTimestepData( + const niv::consumer::NestMultimeter& multimeter, const std::string& time, + const std::string& attribute) { + boost::python::list ret_val; + for (auto v : multimeter.GetTimestepData(time, attribute)) { + ret_val.append(v); + } + return ret_val; +} + +} // namespace nest_multimeter } // namespace consumer template <> void expose() { - class_>( + class_>( "NestMultimeter", init()) .def("GetValues", &pyniv::consumer::GetValues) .def("SetAttribute", &niv::consumer::NestMultimeter::SetAttribute) .def("Update", &niv::consumer::NestMultimeter::Update) - .def("Print", &niv::consumer::NestMultimeter::Print); + .def("Print", &niv::consumer::NestMultimeter::Print) + .def("GetTimestepData", + &pyniv::consumer::nest_multimeter::GetTimestepData) + .def("GetTimeSeriesData", + &pyniv::consumer::nest_multimeter::GetTimeSeriesData) + .def("GetDatum", &niv::consumer::NestMultimeter::GetDatum); } } // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_nest_multimeter.py b/pyniv/tests/src/consumer/test_nest_multimeter.py index 2d8e24a..470f68e 100644 --- a/pyniv/tests/src/consumer/test_nest_multimeter.py +++ b/pyniv/tests/src/consumer/test_nest_multimeter.py @@ -21,6 +21,99 @@ import pyniv +import numpy as np + +def setup_multimeter(name = pyniv.testing.ANY_MULTIMETER_NAME, + data = pyniv.testing.ANY_NEST_DATA): + multimeter = pyniv.consumer.NestMultimeter(name) + multimeter.SetNode(data) + return multimeter, data + +def test_arbor_multimeter_retrieves_datum_for_time_attribute_neuron(): + multimeter, nest_data = setup_multimeter() + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + datum_offset = (pyniv.testing.ANY_TIME_OFFSET + + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + + pyniv.testing.THIRD_ID_OFFSET); + assert np.isclose(datum, pyniv.testing.ANY_VALUES[datum_offset]) + + datum = multimeter.GetDatum(pyniv.testing.NOT_A_TIME_STRING, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + assert np.isnan(datum) + + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.NOT_AN_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + assert np.isnan(datum) + + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.NOT_AN_ID_STRING) + assert np.isnan(datum) + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + datum = multimeter.GetDatum(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + assert np.isnan(datum) + +def test_arbor_multimeter_provides_time_series_data(): + data_offsets = [(time_offset + + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + + pyniv.testing.THIRD_ID_OFFSET) + for time_offset in pyniv.testing.TIME_OFFSETS()] + expected = np.array([pyniv.testing.ANY_VALUES[o] for o in data_offsets]) + + multimeter, nest_data = setup_multimeter() + values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + assert (values == expected).all() + + values = multimeter.GetTimeSeriesData(pyniv.testing.NOT_AN_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + assert np.isnan(values).all() + + values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.NOT_AN_ID_STRING) + assert np.isnan(values).all() + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + values = multimeter.GetTimeSeriesData(pyniv.testing.ANOTHER_ATTRIBUTE, + pyniv.testing.THIRD_ID_STRING) + assert np.isnan(values).all() + +def test_arbor_multimeter_provides_timestep_data_for_all_neurons(): + data_offsets = [(pyniv.testing.THIRD_TIME_OFFSET + + pyniv.testing.ANOTHER_ATTRIBUTE_OFFSET + + id_offset) for id_offset in pyniv.testing.ID_OFFSETS()] + expected = np.array([pyniv.testing.ANY_VALUES[o] for o in data_offsets]) + + multimeter, nest_data = setup_multimeter() + values = multimeter.GetTimestepData( + pyniv.testing.THIRD_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE) + assert (values == expected).all() + + values = multimeter.GetTimestepData( + pyniv.testing.NOT_A_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE) + assert np.isnan(values).all() + + values = multimeter.GetTimestepData( + pyniv.testing.THIRD_TIME_STRING, pyniv.testing.NOT_AN_ATTRIBUTE) + assert np.isnan(values).all() + + multimeter, nest_data = setup_multimeter( + name = pyniv.testing.NOT_A_MULTIMETER_NAME) + values = multimeter.GetTimestepData( + pyniv.testing.THIRD_TIME_STRING, pyniv.testing.ANOTHER_ATTRIBUTE) + assert np.isnan(values).all() + + +# ------------------------------------------------------------ def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): nest_data = pyniv.testing.ANY_NEST_DATA multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) From 28e364a74ecf2938f67e11bfeef897e0160dac09 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Tue, 27 Mar 2018 23:51:10 +0200 Subject: [PATCH 74/82] Update demos to new API --- demo/arbor_miniapp-niv/vis.py | 15 +------ demo/brunel_example/nest_python_vis.py | 51 +++++++++--------------- demo/nest_python_vis/nest_python_vis.py | 53 +++++++++++-------------- 3 files changed, 44 insertions(+), 75 deletions(-) diff --git a/demo/arbor_miniapp-niv/vis.py b/demo/arbor_miniapp-niv/vis.py index 6b5b80f..2d20d27 100644 --- a/demo/arbor_miniapp-niv/vis.py +++ b/demo/arbor_miniapp-niv/vis.py @@ -62,7 +62,7 @@ def SetupPlot(self): def VisualizeButtonClicked(self): self.visualize_button.setEnabled(False) - self.update_timer.start(0.5) + self.update_timer.start(250) self.Visualize() def Show(self): @@ -77,19 +77,6 @@ def Visualize(self): self.backend.Receive() self.Plot(); - def GetValues(self, multimeter): - ts = multimeter.GetTimesteps() - plot_ts = [] - plot_vs = [] - for t in ts: - multimeter.SetTime(t) - multimeter.Update() - vs = multimeter.GetValues() - if len(vs) > 0: - plot_ts.append(t.tolist()) - plot_vs.append(vs.tolist()) - return plot_ts, plot_vs - def Plot(self): timesteps = self.multimeter.GetTimestepsString() attribute = 'v' diff --git a/demo/brunel_example/nest_python_vis.py b/demo/brunel_example/nest_python_vis.py index 58e0f1b..1486576 100644 --- a/demo/brunel_example/nest_python_vis.py +++ b/demo/brunel_example/nest_python_vis.py @@ -36,12 +36,11 @@ def __init__(self): self.SetupWindow() self.SetupPlot() self.SetupUpdateTimer() - + def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - + self.multimeter = pyniv.consumer.NestMultimeter("recordingNode51") - self.multimeter.SetAttribute("V_m") self.backend = pyniv.consumer.Backend(); self.backend.Connect(self.receiver); @@ -63,9 +62,9 @@ def SetupPlot(self): def VisualizeButtonClicked(self): self.visualize_button.setEnabled(False) - self.update_timer.start(0.5) + self.update_timer.start(250) self.Visualize() - + def Show(self): self.visualize_button.show() button_geometry = self.visualize_button.geometry() @@ -76,40 +75,28 @@ def Show(self): def Visualize(self): self.backend.Receive() - plot_ts, plot_vs = self.GetValues(self.multimeter) - self.Plot(plot_ts, plot_vs); - - def GetValues(self, multimeter): - ts = multimeter.GetTimesteps() - plot_ts = [] - plot_vs = [] - for t in ts: - multimeter.SetTime(t) - multimeter.Update() - vs = multimeter.GetValues() - if len(vs) > 0: - plot_ts.append(t.tolist()) - plot_vs.append(vs.tolist()) - return plot_ts, plot_vs - - def Plot(self, ts, vs): - values = [] - for i in range(0, 35): - tmp = [] - for t in range(0, len(vs)): - tmp.append(vs[t][i]) - values.append(tmp) - + self.Plot() + + def Plot(self): + timesteps = self.multimeter.GetTimestepsString() + attribute = 'V_m' + neuron_ids = [] + if len(timesteps) > 0: + neuron_ids = self.multimeter.GetNeuronIds(timesteps[0], attribute) + self.ax1.clear() - for i in range(0, len(values)): - self.ax1.plot(ts, values[i]) + + for neuron_id in neuron_ids: + values = self.multimeter.GetTimeSeriesData(attribute, neuron_id) + times = [float(t) for t in timesteps] + self.ax1.plot(times, values) + self.ax1.set_title("Brunel Example") self.ax1.set_xlabel("Time") self.ax1.set_ylabel("V_m") plt.show(block=False) self.fig.canvas.draw() - def main(argv): app = QApplication(argv) diff --git a/demo/nest_python_vis/nest_python_vis.py b/demo/nest_python_vis/nest_python_vis.py index 30da077..cde27f8 100644 --- a/demo/nest_python_vis/nest_python_vis.py +++ b/demo/nest_python_vis/nest_python_vis.py @@ -39,17 +39,14 @@ def __init__(self): def SetupStreaming(self): self.receiver = pyniv.consumer.Receiver() - - self.multimeter_a = pyniv.consumer.NestMultimeter("multimeter A") - self.multimeter_a.SetAttribute("V_m") - self.multimeter_b = pyniv.consumer.NestMultimeter("multimeter B") - self.multimeter_b.SetAttribute("V_m") + self.multimeters = [pyniv.consumer.NestMultimeter("multimeter A"), + pyniv.consumer.NestMultimeter("multimeter B")] self.backend = pyniv.consumer.Backend(); self.backend.Connect(self.receiver); - self.backend.Connect(self.multimeter_a); - self.backend.Connect(self.multimeter_b); + for multimeter in self.multimeters: + self.backend.Connect(multimeter); def SetupWindow(self): self.visualize_button = QPushButton("Visualize") @@ -73,7 +70,7 @@ def SetupPlot(self): def VisualizeButtonClicked(self): self.visualize_button.setEnabled(False) - self.update_timer.start(0.5) + self.update_timer.start(250) self.Visualize() def Show(self): @@ -81,30 +78,28 @@ def Show(self): def Visualize(self): self.backend.Receive() - plot_ts_a, plot_vs_a = self.GetValues(self.multimeter_a) - plot_ts_b, plot_vs_b = self.GetValues(self.multimeter_b) - self.Plot([[plot_ts_a, plot_vs_a], [plot_ts_b, plot_vs_b]]); - - def GetValues(self, multimeter): - ts = multimeter.GetTimesteps() - plot_ts = [] - plot_vs = [] - for t in ts: - multimeter.SetTime(t) - multimeter.Update() - vs = multimeter.GetValues() - if len(vs) > 0: - plot_ts.append(t) - plot_vs.append(vs[0]) - return plot_ts, plot_vs - - def Plot(self, values): + self.Plot(); + + def Plot(self): self.ax1.clear() - for [ts, vs] in values: - self.ax1.plot(ts, vs) + + for multimeter in self.multimeters: + self.MultimeterPlot(multimeter) + plt.show(block=False) self.fig.canvas.draw() - + + def MultimeterPlot(self, multimeter): + timesteps = multimeter.GetTimestepsString() + attribute = 'V_m' + neuron_ids = [] + if len(timesteps) > 0: + neuron_ids = multimeter.GetNeuronIds(timesteps[0], attribute) + + for neuron_id in neuron_ids: + values = multimeter.GetTimeSeriesData(attribute, neuron_id) + times = [float(t) for t in timesteps] + self.ax1.plot(times, values) def main(argv): app = QApplication(argv) From fa0ea38da3d25e3ef6ddd8f06f3a0b459c0c0adb Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Mar 2018 00:25:36 +0200 Subject: [PATCH 75/82] Remove obsolete/superfluous methods from consumer::Device --- niv/include/niv/consumer/device.hpp | 15 --- niv/src/consumer/device.cpp | 28 +----- niv/src/consumer/nest_multimeter.cpp | 12 --- niv/tests/src/consumer/test_device.cpp | 19 +--- niv/tests/src/consumer/test_integration.cpp | 11 +-- .../src/consumer/test_nest_multimeter.cpp | 93 ------------------- pyniv/src/consumer/device.cpp | 5 +- pyniv/src/consumer/nest_multimeter.cpp | 1 - pyniv/tests/src/consumer/test_device.py | 18 ++-- pyniv/tests/src/consumer/test_integration.py | 10 +- .../src/consumer/test_nest_multimeter.py | 16 ++-- 11 files changed, 27 insertions(+), 201 deletions(-) diff --git a/niv/include/niv/consumer/device.hpp b/niv/include/niv/consumer/device.hpp index 35e04c7..de7f449 100644 --- a/niv/include/niv/consumer/device.hpp +++ b/niv/include/niv/consumer/device.hpp @@ -44,12 +44,8 @@ class Device { std::vector GetTimestepsString() const; const std::vector GetTimesteps() const; - virtual void SetTime(double time); - void SetNode(const conduit::Node* node) { node_ = node; } - void Print() const; - protected: std::vector GetChildNames(const std::string& path) const; @@ -58,19 +54,8 @@ class Device { std::string ConstructPath() const; std::string ConstructPath(const std::string& time) const; - void SetTimestepNode(); - const conduit::Node* GetTimestepNode() const; - - const conduit::Node* GetRootNode() const; - const std::string GetName() const; - private: const conduit::Node* node_{nullptr}; - const conduit::Node* timestep_node_{nullptr}; - - std::vector timesteps_; - - double time_{0.0}; std::string name_{""}; }; diff --git a/niv/src/consumer/device.cpp b/niv/src/consumer/device.cpp index 74a1b5c..5fbb9d6 100644 --- a/niv/src/consumer/device.cpp +++ b/niv/src/consumer/device.cpp @@ -56,7 +56,7 @@ std::vector Device::GetChildNames(const std::string& path) const { const conduit::Node* Device::GetNode(const std::string& path) const { const conduit::Node* node{nullptr}; try { - node = &GetRootNode()->fetch_child(path); + node = &(node_->fetch_child(path)); } catch (...) { } return node; @@ -68,31 +68,5 @@ std::string Device::ConstructPath(const std::string& time) const { return Device::ConstructPath() + '/' + time; } -void Device::SetTime(double time) { time_ = time; } - -void Device::SetTimestepNode() { - std::stringstream time_stream; - time_stream << time_; - try { - timestep_node_ = &node_->fetch_child(name_ + "/" + time_stream.str()); - } catch (...) { - } -} - -void Device::Print() const { - if (node_ != nullptr) { - std::cout << "Schema" << std::endl; - std::cout << node_->schema().to_json() << std::endl; - std::cout << "Data" << std::endl; - node_->print(); - } -} - -const conduit::Node* Device::GetTimestepNode() const { return timestep_node_; } - -const conduit::Node* Device::GetRootNode() const { return node_; } - -const std::string Device::GetName() const { return name_; } - } // namespace consumer } // namespace niv diff --git a/niv/src/consumer/nest_multimeter.cpp b/niv/src/consumer/nest_multimeter.cpp index 755f429..67498f8 100644 --- a/niv/src/consumer/nest_multimeter.cpp +++ b/niv/src/consumer/nest_multimeter.cpp @@ -71,23 +71,11 @@ void NestMultimeter::SetAttribute(const std::string& attribute) { } void NestMultimeter::Update() { - SetTimestepNode(); SetValues(); } void NestMultimeter::SetValues() { values_.clear(); - if (GetTimestepNode() == nullptr) { - return; - } - try { - const conduit::Node* attribute_node = - &GetTimestepNode()->fetch_child(attribute_); - for (auto i = 0u; i < attribute_node->number_of_children(); ++i) { - values_.push_back(attribute_node->child(i).as_double()); - } - } catch (...) { - } } const std::vector& NestMultimeter::GetValues() const { return values_; } diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index 491ff4b..d317110 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -27,21 +27,6 @@ #include "niv/consumer/device.hpp" #include "niv/nest_test_data.hpp" -namespace { - -class Device : public niv::consumer::Device { - public: - explicit Device(const std::string& name) : niv::consumer::Device(name) {} - Device(const Device&) = delete; - Device(Device&&) = delete; - ~Device() = default; - - Device& operator=(const Device&) = delete; - Device& operator=(Device&&) = delete; -}; - -} // namespace - namespace Catch { namespace Matchers { namespace Vector { @@ -78,7 +63,7 @@ Vector::EqualsApproxMatcher EqualsApprox(std::vector const& comparator) { SCENARIO("consumer::Device lists the timesteps", "[niv][niv::consumer][niv::consumer::Device]") { GIVEN("a device providing access to some data") { - ::Device device(niv::testing::ANY_DEVICE_NAME); + niv::consumer::Device device(niv::testing::ANY_DEVICE_NAME); device.SetNode(&niv::testing::ANY_NEST_DATA); THEN("the device provides correct timesteps as strings") { @@ -91,7 +76,7 @@ SCENARIO("consumer::Device lists the timesteps", } GIVEN("a device with an incorrect name providing access to some data") { - ::Device multimeter(niv::testing::NOT_A_DEVICE_NAME); + niv::consumer::Device multimeter(niv::testing::NOT_A_DEVICE_NAME); multimeter.SetNode(&niv::testing::ANY_NEST_DATA); THEN("the device does not provide timesteps as strings") { diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index f001795..112f7f9 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -46,13 +46,10 @@ SCENARIO("Consumer integration", "[niv][integration]") { backend.Receive(); WHEN("the multimeter queries the data") { - multimeter.SetTime(niv::testing::ANY_TIME); - multimeter.Update(); - std::vector values_at_t0{multimeter.GetValues()}; - - multimeter.SetTime(niv::testing::ANOTHER_TIME); - multimeter.Update(); - std::vector values_at_t1{multimeter.GetValues()}; + std::vector values_at_t0{multimeter.GetTimestepData( + niv::testing::ANY_TIME_STRING, niv::testing::ANY_ATTRIBUTE)}; + std::vector values_at_t1{multimeter.GetTimestepData( + niv::testing::ANOTHER_TIME_STRING, niv::testing::ANY_ATTRIBUTE)}; THEN("the received values are correct") { const std::vector expected_at_t0{ diff --git a/niv/tests/src/consumer/test_nest_multimeter.cpp b/niv/tests/src/consumer/test_nest_multimeter.cpp index 38c29d2..9a8afcf 100644 --- a/niv/tests/src/consumer/test_nest_multimeter.cpp +++ b/niv/tests/src/consumer/test_nest_multimeter.cpp @@ -202,96 +202,3 @@ SCENARIO("NestMultimeter provides timestep data for all neurons", } } } - -// ------------------------------------------------------------ - -SCENARIO("a Multimeter provides access to data stored in a conduit node", - "[niv][niv::consumer][niv::consumer::Multimeter]") { - GIVEN("A Multimeter with some data") { - const conduit::Node nest_data{niv::testing::ANY_NEST_DATA}; - niv::consumer::NestMultimeter multimeter(niv::testing::AnyMultimeterName()); - multimeter.SetNode(&nest_data); - - WHEN("The time step is set") { - multimeter.SetTime(niv::testing::ANY_TIME); - WHEN("one attribute is queried") { - multimeter.SetAttribute(niv::testing::ANY_ATTRIBUTE); - multimeter.Update(); - auto result = multimeter.GetValues(); - THEN("the result is correct") { - const std::vector expected{ - niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANY_ATTRIBUTE_INDEX, - niv::testing::ANY_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANY_ATTRIBUTE_INDEX, - niv::testing::ANOTHER_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANY_ATTRIBUTE_INDEX, - niv::testing::THIRD_ID_INDEX)}; - REQUIRE(result == expected); - } - } - WHEN("another attribute is queried") { - multimeter.SetAttribute(niv::testing::ANOTHER_ATTRIBUTE); - multimeter.Update(); - - auto result = multimeter.GetValues(); - THEN("the result is correct") { - const std::vector expected{ - niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::ANY_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::ANOTHER_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::THIRD_ID_INDEX)}; - REQUIRE(result == expected); - } - } - - WHEN("The time step is set to another value") { - multimeter.SetTime(niv::testing::ANOTHER_TIME); - WHEN("one attribute is queried") { - multimeter.SetAttribute(niv::testing::ANY_ATTRIBUTE); - multimeter.Update(); - auto result = multimeter.GetValues(); - THEN("the result is correct") { - const std::vector expected{ - niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, - niv::testing::ANY_ATTRIBUTE_INDEX, - niv::testing::ANY_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, - niv::testing::ANY_ATTRIBUTE_INDEX, - niv::testing::ANOTHER_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, - niv::testing::ANY_ATTRIBUTE_INDEX, - niv::testing::THIRD_ID_INDEX)}; - REQUIRE(result == expected); - } - } - WHEN("another attribute is queried") { - multimeter.SetAttribute(niv::testing::ANOTHER_ATTRIBUTE); - multimeter.Update(); - - auto result = multimeter.GetValues(); - THEN("the result is correct") { - const std::vector expected{ - niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::ANY_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::ANOTHER_ID_INDEX), - niv::testing::ValueAt(niv::testing::ANOTHER_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::THIRD_ID_INDEX)}; - REQUIRE(result == expected); - } - } - } - } - } -} diff --git a/pyniv/src/consumer/device.cpp b/pyniv/src/consumer/device.cpp index 7b7b79a..292adeb 100644 --- a/pyniv/src/consumer/device.cpp +++ b/pyniv/src/consumer/device.cpp @@ -50,7 +50,7 @@ boost::python::list GetTimestepsString(const niv::consumer::Device& device) { return retval; } -static void SetNodePointer(niv::consumer::Device* device, PyObject* node) { +static void SetNode(niv::consumer::Device* device, PyObject* node) { device->SetNode(boost::python::extract(node)); } @@ -62,8 +62,7 @@ void expose() { class_("Device", init()) .def("GetTimestepsString", &pyniv::consumer::device::GetTimestepsString) .def("GetTimesteps", &pyniv::consumer::device::GetTimesteps) - .def("SetNode", &pyniv::consumer::device::SetNodePointer) - .def("SetTime", &niv::consumer::Device::SetTime); + .def("SetNode", &pyniv::consumer::device::SetNode); } } // namespace pyniv diff --git a/pyniv/src/consumer/nest_multimeter.cpp b/pyniv/src/consumer/nest_multimeter.cpp index dc9f357..ce0492f 100644 --- a/pyniv/src/consumer/nest_multimeter.cpp +++ b/pyniv/src/consumer/nest_multimeter.cpp @@ -79,7 +79,6 @@ void expose() { .def("GetValues", &pyniv::consumer::GetValues) .def("SetAttribute", &niv::consumer::NestMultimeter::SetAttribute) .def("Update", &niv::consumer::NestMultimeter::Update) - .def("Print", &niv::consumer::NestMultimeter::Print) .def("GetTimestepData", &pyniv::consumer::nest_multimeter::GetTimestepData) .def("GetTimeSeriesData", diff --git a/pyniv/tests/src/consumer/test_device.py b/pyniv/tests/src/consumer/test_device.py index 9257f2e..d17e0f3 100644 --- a/pyniv/tests/src/consumer/test_device.py +++ b/pyniv/tests/src/consumer/test_device.py @@ -29,16 +29,16 @@ def __init__(self, name): def setup_device(name = pyniv.testing.ANY_DEVICE_NAME, data = pyniv.testing.ANY_NEST_DATA): - multimeter = pyniv.consumer.Device(name) - multimeter.SetNode(data) - return multimeter, data + device = pyniv.consumer.Device(name) + device.SetNode(data) + return device, data -def test_multimeter_lists_the_timesteps(): - multimeter, nest_data = setup_device() - timesteps = multimeter.GetTimestepsString(); +def test_device_lists_the_timesteps(): + device, nest_data = setup_device() + timesteps = device.GetTimestepsString(); assert timesteps == pyniv.testing.ANY_TIMES_STRING - multimeter, nest_data = setup_device( - name = pyniv.testing.NOT_A_MULTIMETER_NAME) - timesteps = multimeter.GetTimestepsString(); + device, nest_data = setup_device( + name = pyniv.testing.NOT_A_DEVICE_NAME) + timesteps = device.GetTimestepsString(); assert timesteps == [] diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index 06ec921..2b874f6 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -37,9 +37,7 @@ def test_integration_consumer(): backend.Receive() - multimeter.SetTime(pyniv.testing.ANY_TIME) - multimeter.Update() - values_at_t0 = multimeter.GetValues() + values_at_t0 = multimeter.GetTimestepData(pyniv.testing.ANY_TIME_STRING, pyniv.testing.ANY_ATTRIBUTE) expected_at_t0 = [ pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, pyniv.testing.ANY_ATTRIBUTE_INDEX, @@ -52,9 +50,7 @@ def test_integration_consumer(): pyniv.testing.THIRD_ID_INDEX)] assert np.isclose(values_at_t0, expected_at_t0).all() - multimeter.SetTime(pyniv.testing.ANOTHER_TIME) - multimeter.Update() - values_at_t1 = multimeter.GetValues() + values_at_t1 = multimeter.GetTimestepData(pyniv.testing.ANOTHER_TIME_STRING, pyniv.testing.ANY_ATTRIBUTE) expected_at_t1 = [ pyniv.testing.ValueAt(pyniv.testing.ANOTHER_TIME_INDEX, pyniv.testing.ANY_ATTRIBUTE_INDEX, @@ -65,4 +61,4 @@ def test_integration_consumer(): pyniv.testing.ValueAt(pyniv.testing.ANOTHER_TIME_INDEX, pyniv.testing.ANY_ATTRIBUTE_INDEX, pyniv.testing.THIRD_ID_INDEX)] - assert np.isclose(values_at_t0, expected_at_t1).all() + assert np.isclose(values_at_t1, expected_at_t1).all() diff --git a/pyniv/tests/src/consumer/test_nest_multimeter.py b/pyniv/tests/src/consumer/test_nest_multimeter.py index 470f68e..983141f 100644 --- a/pyniv/tests/src/consumer/test_nest_multimeter.py +++ b/pyniv/tests/src/consumer/test_nest_multimeter.py @@ -119,11 +119,8 @@ def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) multimeter.SetNode(nest_data) - multimeter.SetTime(pyniv.testing.ANY_TIME) - - multimeter.SetAttribute(pyniv.testing.ANY_ATTRIBUTE) - multimeter.Update() - result = multimeter.GetValues() + result = multimeter.GetTimestepData(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANY_ATTRIBUTE) expected = [ pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, pyniv.testing.ANY_ATTRIBUTE_INDEX, @@ -134,11 +131,10 @@ def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, pyniv.testing.ANY_ATTRIBUTE_INDEX, pyniv.testing.THIRD_ID_INDEX)] - assert (result == expected).all() + assert result == expected - multimeter.SetAttribute(pyniv.testing.ANOTHER_ATTRIBUTE) - multimeter.Update() - result = multimeter.GetValues() + result = multimeter.GetTimestepData(pyniv.testing.ANY_TIME_STRING, + pyniv.testing.ANOTHER_ATTRIBUTE) expected = [ pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, pyniv.testing.ANOTHER_ATTRIBUTE_INDEX, @@ -149,5 +145,5 @@ def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): pyniv.testing.ValueAt(pyniv.testing.ANY_TIME_INDEX, pyniv.testing.ANOTHER_ATTRIBUTE_INDEX, pyniv.testing.THIRD_ID_INDEX)] - assert (result == expected).all() + assert result == expected From 6752bb7cf0c2f574b9930d356a16adb263204a52 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Mar 2018 00:30:13 +0200 Subject: [PATCH 76/82] Remove obsolete/superfluous methods from consumer::NestMultimeter --- niv/include/niv/consumer/nest_multimeter.hpp | 11 ----------- niv/src/consumer/nest_multimeter.cpp | 16 ---------------- niv/tests/src/consumer/test_integration.cpp | 1 - pyniv/src/consumer/nest_multimeter.cpp | 16 ---------------- pyniv/tests/src/consumer/test_integration.py | 1 - 5 files changed, 45 deletions(-) diff --git a/niv/include/niv/consumer/nest_multimeter.hpp b/niv/include/niv/consumer/nest_multimeter.hpp index fb80653..751d1fb 100644 --- a/niv/include/niv/consumer/nest_multimeter.hpp +++ b/niv/include/niv/consumer/nest_multimeter.hpp @@ -52,19 +52,8 @@ class NestMultimeter : public consumer::Multimeter { double GetDatum(const std::string& time, const std::string& attribute, const std::string& neuron_id) const; - void SetAttribute(const std::string& attribute); - - void Update(); - - const std::vector& GetValues() const; - private: double GetValue(const std::string& path) const; - - void SetValues(); - - std::vector values_; - std::string attribute_{""}; }; } // namespace consumer diff --git a/niv/src/consumer/nest_multimeter.cpp b/niv/src/consumer/nest_multimeter.cpp index 67498f8..ac098e0 100644 --- a/niv/src/consumer/nest_multimeter.cpp +++ b/niv/src/consumer/nest_multimeter.cpp @@ -64,21 +64,5 @@ double NestMultimeter::GetValue(const std::string& path) const { return (node != nullptr) ? node->as_double() : std::nan(""); } -// ------------------------------------------------------------ - -void NestMultimeter::SetAttribute(const std::string& attribute) { - attribute_ = attribute; -} - -void NestMultimeter::Update() { - SetValues(); -} - -void NestMultimeter::SetValues() { - values_.clear(); -} - -const std::vector& NestMultimeter::GetValues() const { return values_; } - } // namespace consumer } // namespace niv diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index 112f7f9..eeccc15 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -36,7 +36,6 @@ SCENARIO("Consumer integration", "[niv][integration]") { backend.Connect(&receiver); niv::consumer::NestMultimeter multimeter(niv::testing::ANY_MULTIMETER_NAME); - multimeter.SetAttribute(niv::testing::ANY_ATTRIBUTE); backend.Connect(&multimeter); WHEN("The data producer sends data") { diff --git a/pyniv/src/consumer/nest_multimeter.cpp b/pyniv/src/consumer/nest_multimeter.cpp index ce0492f..9578e7f 100644 --- a/pyniv/src/consumer/nest_multimeter.cpp +++ b/pyniv/src/consumer/nest_multimeter.cpp @@ -34,19 +34,6 @@ SUPPRESS_WARNINGS_END namespace pyniv { namespace consumer { - -boost::python::numpy::ndarray GetValues( - const niv::consumer::NestMultimeter& multimeter); -boost::python::numpy::ndarray GetValues( - const niv::consumer::NestMultimeter& multimeter) { - const auto& values{multimeter.GetValues()}; - - return boost::python::numpy::from_data( - values.data(), boost::python::numpy::dtype::get_builtin(), - boost::python::make_tuple(values.size()), - boost::python::make_tuple(sizeof(double)), boost::python::object()); -} - namespace nest_multimeter { boost::python::list GetTimeSeriesData( @@ -76,9 +63,6 @@ template <> void expose() { class_>( "NestMultimeter", init()) - .def("GetValues", &pyniv::consumer::GetValues) - .def("SetAttribute", &niv::consumer::NestMultimeter::SetAttribute) - .def("Update", &niv::consumer::NestMultimeter::Update) .def("GetTimestepData", &pyniv::consumer::nest_multimeter::GetTimestepData) .def("GetTimeSeriesData", diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index 2b874f6..c7d761c 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -30,7 +30,6 @@ def test_integration_consumer(): backend.Connect(receiver) multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) - multimeter.SetAttribute(pyniv.testing.AnyValueNames(0)) backend.Connect(multimeter) pyniv.testing.Send(pyniv.testing.ANY_NEST_DATA) From a22284c470aed581fb778936ff2fec5b90473bc4 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Mar 2018 06:27:03 +0200 Subject: [PATCH 77/82] Name devices "" by default --- niv/include/niv/producer/device.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niv/include/niv/producer/device.hpp b/niv/include/niv/producer/device.hpp index 9abda46..9effa50 100644 --- a/niv/include/niv/producer/device.hpp +++ b/niv/include/niv/producer/device.hpp @@ -66,7 +66,7 @@ class Device { const std::string& GetName() { return name_; } private: - std::string name_{"recorder"}; + std::string name_{""}; }; template <> From a00df3be55ea356c79ce454c63c19dde0eb4b8ce Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Wed, 28 Mar 2018 06:27:26 +0200 Subject: [PATCH 78/82] Extract path generation for tests --- niv/include/niv/nest_test_data.hpp | 7 +++ .../src/producer/test_arbor_multimeter.cpp | 16 +++---- .../src/producer/test_nest_multimeter.cpp | 47 +++++++++---------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index cb3d3aa..a294efe 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -118,6 +118,13 @@ static const char* ANOTHER_ID_STRING{ANY_IDS_STRING[ANOTHER_ID_INDEX].c_str()}; static const char* THIRD_ID_STRING{ANY_IDS_STRING[THIRD_ID_INDEX].c_str()}; static const char* NOT_AN_ID_STRING{"NOT_AN_ID"}; +inline std::string PathFor(const std::string& device_name, + const std::string& timestep, + const std::string& attribute, + const std::string& neuron_id) { + return device_name + '/' + timestep + '/' + attribute + '/' + neuron_id; +} + // clang-format off static const std::vector ANY_VALUES{ 0.111, 0.112, 0.113, 0.121, 0.122, 0.123, 0.131, 0.132, 0.133, diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp index 6d751bd..4d8dc61 100644 --- a/niv/tests/src/producer/test_arbor_multimeter.cpp +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -40,20 +40,16 @@ SCENARIO("A multimeter records to a conduit node", WHEN("recording data") { niv::producer::ArborMultimeter::Datum datum{ niv::testing::ANY_TIME + niv::testing::ANY_TIME_OFFSET, - niv::testing::ANY_ATTRIBUTE, niv::testing::ANY_ID_STRING, + niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING, niv::testing::ANY_VALUE}; multimeter.Record(datum, &node); THEN("the data is properly recorded") { - std::stringstream path; - path << niv::testing::ANY_MULTIMETER_NAME << '/'; - path << niv::testing::ANY_TIME << '/'; - path << niv::testing::ANY_ATTRIBUTE << '/'; - path << niv::testing::ANY_ID; - - REQUIRE(node[path.str()].as_double() == - Approx(niv::testing::ANY_VALUE)); + REQUIRE(node[niv::testing::PathFor(niv::testing::ANY_MULTIMETER_NAME, + niv::testing::ANY_TIME_STRING, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::THIRD_ID_STRING)] + .as_double() == Approx(niv::testing::ANY_VALUE)); } - // id tag time value } } } diff --git a/niv/tests/src/producer/test_nest_multimeter.cpp b/niv/tests/src/producer/test_nest_multimeter.cpp index 06e2c13..e5444fc 100644 --- a/niv/tests/src/producer/test_nest_multimeter.cpp +++ b/niv/tests/src/producer/test_nest_multimeter.cpp @@ -42,37 +42,32 @@ SCENARIO("A multimeter records to a conduit node", niv::testing::ANY_VALUES_FOR_ATTRIBUTES}; multimeter.Record(datum); THEN("data is properly recorded") { - std::stringstream path0; - path0 << niv::testing::ANY_MULTIMETER_NAME << '/'; - path0 << niv::testing::ANY_TIME << '/'; - path0 << niv::testing::ANY_ATTRIBUTE << '/'; - path0 << niv::testing::ANY_ID; - REQUIRE(node[path0.str()].as_double() == + REQUIRE(node[niv::testing::PathFor(niv::testing::ANY_MULTIMETER_NAME, + niv::testing::ANY_TIME_STRING, + niv::testing::ANY_ATTRIBUTE, + niv::testing::ANY_ID_STRING)] + .as_double() == Approx(niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, niv::testing::ANY_ATTRIBUTE_INDEX, niv::testing::ANY_ID_INDEX))); - std::stringstream path1; - path1 << niv::testing::ANY_MULTIMETER_NAME << '/'; - path1 << niv::testing::ANY_TIME << '/'; - path1 << niv::testing::ANOTHER_ATTRIBUTE << '/'; - path1 << niv::testing::ANY_ID; - REQUIRE( - node[path1.str()].as_double() == - Approx(niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::ANOTHER_ATTRIBUTE_INDEX, - niv::testing::ANY_ID_INDEX))); + REQUIRE(node[niv::testing::PathFor(niv::testing::ANY_MULTIMETER_NAME, + niv::testing::ANY_TIME_STRING, + niv::testing::ANOTHER_ATTRIBUTE, + niv::testing::ANY_ID_STRING)] + .as_double() == Approx(niv::testing::ValueAt( + niv::testing::ANY_TIME_INDEX, + niv::testing::ANOTHER_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX))); - std::stringstream path2; - path2 << niv::testing::ANY_MULTIMETER_NAME << '/'; - path2 << niv::testing::ANY_TIME << '/'; - path2 << niv::testing::THIRD_ATTRIBUTE << '/'; - path2 << niv::testing::ANY_ID; - REQUIRE( - node[path2.str()].as_double() == - Approx(niv::testing::ValueAt(niv::testing::ANY_TIME_INDEX, - niv::testing::THIRD_ATTRIBUTE_INDEX, - niv::testing::ANY_ID_INDEX))); + REQUIRE(node[niv::testing::PathFor(niv::testing::ANY_MULTIMETER_NAME, + niv::testing::ANY_TIME_STRING, + niv::testing::THIRD_ATTRIBUTE, + niv::testing::ANY_ID_STRING)] + .as_double() == Approx(niv::testing::ValueAt( + niv::testing::ANY_TIME_INDEX, + niv::testing::THIRD_ATTRIBUTE_INDEX, + niv::testing::ANY_ID_INDEX))); } } } From a4140edc7a1c5bd175c276d0550d80d40f383034 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 29 Mar 2018 07:55:03 +0200 Subject: [PATCH 79/82] Remove superfluous functions from test data --- niv/include/niv/nest_test_data.hpp | 8 ----- pyniv/src/testing/nest_test_data.cpp | 32 ------------------- pyniv/tests/src/consumer/test_integration.py | 2 +- .../src/consumer/test_nest_multimeter.py | 2 +- 4 files changed, 2 insertions(+), 42 deletions(-) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/nest_test_data.hpp index a294efe..baf6ac6 100644 --- a/niv/include/niv/nest_test_data.hpp +++ b/niv/include/niv/nest_test_data.hpp @@ -226,14 +226,6 @@ static conduit::Node ANY_NEST_DATA{ #pragma GCC diagnostic pop #endif -std::vector AnyAttributesValues(double time = 0.0); -std::vector AnotherAttributesValues(double time = 0.0); -std::vector ThirdAttributesValues(double time = 0.0); - -std::vector AnyValueNames(); - -std::string AnyMultimeterName(); - void Send(const conduit::Node& node); conduit::Node AnyNode(); diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 25b7ad6..2fac8f3 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -48,32 +48,6 @@ bool Equal(const conduit::Node& node1, const conduit::Node& node2) { return is_equal; } -std::string AnyValueNames(std::size_t index) { - return niv::testing::AnyValueNames()[index]; -} - -boost::python::numpy::ndarray AnyAttributesValues(double time = 0) { - static std::vector values; - values = std::vector{niv::testing::AnyAttributesValues(time)}; - - return boost::python::numpy::from_data( - values.data(), boost::python::numpy::dtype::get_builtin(), - boost::python::make_tuple(values.size()), - boost::python::make_tuple(sizeof(double)), boost::python::object()); -} - -boost::python::numpy::ndarray AnotherAttributesValues() { - static std::vector values{niv::testing::AnotherAttributesValues()}; - - return boost::python::numpy::from_data( - values.data(), boost::python::numpy::dtype::get_builtin(), - boost::python::make_tuple(values.size()), - boost::python::make_tuple(sizeof(double)), boost::python::object()); -} - -BOOST_PYTHON_FUNCTION_OVERLOADS(AnyAttributesValuesOverloads, - AnyAttributesValues, 0, 1) - boost::python::list TimeOffsets() { boost::python::list ret_val; for (auto t : niv::testing::TIME_OFFSETS) { @@ -163,12 +137,6 @@ void expose() { def("TIME_OFFSETS", &pyniv::testing::TimeOffsets); def("ID_OFFSETS", &pyniv::testing::IdOffsets); - def("AnyAttributesValues", &pyniv::testing::AnyAttributesValues, - pyniv::testing::AnyAttributesValuesOverloads()); - def("AnotherAttributesValues", &pyniv::testing::AnotherAttributesValues); - def("ThirdAttributesValues", &niv::testing::ThirdAttributesValues); - def("AnyValueNames", &pyniv::testing::AnyValueNames); - def("AnyMultimeterName", &niv::testing::AnyMultimeterName); def("Send", &niv::testing::Send); def("AnyNode", &niv::testing::AnyNode); def("AnotherNode", &niv::testing::AnotherNode); diff --git a/pyniv/tests/src/consumer/test_integration.py b/pyniv/tests/src/consumer/test_integration.py index c7d761c..d8b61a2 100644 --- a/pyniv/tests/src/consumer/test_integration.py +++ b/pyniv/tests/src/consumer/test_integration.py @@ -29,7 +29,7 @@ def test_integration_consumer(): receiver = pyniv.consumer.Receiver() backend.Connect(receiver) - multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) + multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.ANY_MULTIMETER_NAME) backend.Connect(multimeter) pyniv.testing.Send(pyniv.testing.ANY_NEST_DATA) diff --git a/pyniv/tests/src/consumer/test_nest_multimeter.py b/pyniv/tests/src/consumer/test_nest_multimeter.py index 983141f..8c4edd3 100644 --- a/pyniv/tests/src/consumer/test_nest_multimeter.py +++ b/pyniv/tests/src/consumer/test_nest_multimeter.py @@ -116,7 +116,7 @@ def test_arbor_multimeter_provides_timestep_data_for_all_neurons(): # ------------------------------------------------------------ def test_nest_multimeter_provides_access_to_data_stored_in_a_conduit_node(): nest_data = pyniv.testing.ANY_NEST_DATA - multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.AnyMultimeterName()) + multimeter = pyniv.consumer.NestMultimeter(pyniv.testing.ANY_MULTIMETER_NAME) multimeter.SetNode(nest_data) result = multimeter.GetTimestepData(pyniv.testing.ANY_TIME_STRING, From 94778bcdc5d1a9af3655557eabbf1770d6ab841b Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 29 Mar 2018 08:03:49 +0200 Subject: [PATCH 80/82] Move nest_test_data.hpp/cpp to proper subdir --- niv/include/niv/{ => testing}/nest_test_data.hpp | 0 niv/src/consumer/arbor_multimeter.cpp | 2 +- niv/src/{ => testing}/nest_test_data.cpp | 2 +- niv/tests/src/consumer/test_arbor_multimeter.cpp | 2 +- niv/tests/src/consumer/test_device.cpp | 2 +- niv/tests/src/consumer/test_integration.cpp | 2 +- niv/tests/src/consumer/test_multimeter.cpp | 2 +- niv/tests/src/consumer/test_nest_multimeter.cpp | 2 +- niv/tests/src/consumer/test_receiver.cpp | 2 +- niv/tests/src/exchange/test_node_storage.cpp | 2 +- niv/tests/src/exchange/test_relay_shared_memory.cpp | 2 +- niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp | 2 +- niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp | 2 +- niv/tests/src/exchange/test_shared_memory.cpp | 2 +- niv/tests/src/producer/test_arbor_multimeter.cpp | 2 +- niv/tests/src/producer/test_nest_multimeter.cpp | 2 +- niv/tests/src/producer/test_sender.cpp | 2 +- niv/tests/src/producer/test_spike_detector.cpp | 2 +- niv/tests/src/test_conduit.cpp | 2 +- pyniv/src/testing/nest_test_data.cpp | 2 +- pyniv/src/testing/testing.cpp | 2 +- 21 files changed, 20 insertions(+), 20 deletions(-) rename niv/include/niv/{ => testing}/nest_test_data.hpp (100%) rename niv/src/{ => testing}/nest_test_data.cpp (98%) diff --git a/niv/include/niv/nest_test_data.hpp b/niv/include/niv/testing/nest_test_data.hpp similarity index 100% rename from niv/include/niv/nest_test_data.hpp rename to niv/include/niv/testing/nest_test_data.hpp diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 1568897..60284f9 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -28,7 +28,7 @@ #include "conduit/conduit_node.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" namespace niv { namespace consumer { diff --git a/niv/src/nest_test_data.cpp b/niv/src/testing/nest_test_data.cpp similarity index 98% rename from niv/src/nest_test_data.cpp rename to niv/src/testing/nest_test_data.cpp index 07a8bd8..35fbd60 100644 --- a/niv/src/nest_test_data.cpp +++ b/niv/src/testing/nest_test_data.cpp @@ -19,7 +19,7 @@ // limitations under the License. //------------------------------------------------------------------------------ -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include #include diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index c37c2ae..0ed6462 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -25,7 +25,7 @@ #include "catch/Catch.hpp" #include "niv/consumer/arbor_multimeter.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "test_utilities/vector_all_nan_or_empty.hpp" diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index d317110..508c31a 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -25,7 +25,7 @@ #include "catch/catch.hpp" #include "niv/consumer/device.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" namespace Catch { namespace Matchers { diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index eeccc15..4a3adbf 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -26,7 +26,7 @@ #include "niv/consumer/backend.hpp" #include "niv/consumer/nest_multimeter.hpp" #include "niv/consumer/receiver.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" SCENARIO("Consumer integration", "[niv][integration]") { GIVEN("The required objects") { diff --git a/niv/tests/src/consumer/test_multimeter.cpp b/niv/tests/src/consumer/test_multimeter.cpp index 34fa515..8b769d3 100644 --- a/niv/tests/src/consumer/test_multimeter.cpp +++ b/niv/tests/src/consumer/test_multimeter.cpp @@ -22,7 +22,7 @@ #include "catch/catch.hpp" #include "niv/consumer/multimeter.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" SCENARIO("consumer::Multimeter lists attributes for a timestep", "[niv][niv::consumer][niv::consumer::Multimeter]") { diff --git a/niv/tests/src/consumer/test_nest_multimeter.cpp b/niv/tests/src/consumer/test_nest_multimeter.cpp index 9a8afcf..30a46c1 100644 --- a/niv/tests/src/consumer/test_nest_multimeter.cpp +++ b/niv/tests/src/consumer/test_nest_multimeter.cpp @@ -26,7 +26,7 @@ #include "conduit/conduit_node.hpp" #include "niv/consumer/nest_multimeter.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "test_utilities/vector_all_nan_or_empty.hpp" diff --git a/niv/tests/src/consumer/test_receiver.cpp b/niv/tests/src/consumer/test_receiver.cpp index 74b3919..c899577 100644 --- a/niv/tests/src/consumer/test_receiver.cpp +++ b/niv/tests/src/consumer/test_receiver.cpp @@ -23,7 +23,7 @@ #include "niv/consumer/receiver.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "conduit_node_helper.hpp" diff --git a/niv/tests/src/exchange/test_node_storage.cpp b/niv/tests/src/exchange/test_node_storage.cpp index 9566230..a972c53 100644 --- a/niv/tests/src/exchange/test_node_storage.cpp +++ b/niv/tests/src/exchange/test_node_storage.cpp @@ -26,7 +26,7 @@ #include "catch/catch.hpp" #include "niv/exchange/node_storage.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "conduit_node_helper.hpp" diff --git a/niv/tests/src/exchange/test_relay_shared_memory.cpp b/niv/tests/src/exchange/test_relay_shared_memory.cpp index 8aec570..3cb05b8 100644 --- a/niv/tests/src/exchange/test_relay_shared_memory.cpp +++ b/niv/tests/src/exchange/test_relay_shared_memory.cpp @@ -27,7 +27,7 @@ #include "niv/exchange/relay_shared_memory.hpp" #include "niv/exchange/shared_memory.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "conduit_node_helper.hpp" diff --git a/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp b/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp index 28bcbb5..473a0b2 100644 --- a/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp +++ b/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp @@ -24,7 +24,7 @@ #include "catch/catch.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" SCENARIO("Mutex does not stall multiple sends/receives", "[niv][niv::RelaySharedMemory]") { diff --git a/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp b/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp index 5c84bfa..79810c1 100644 --- a/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp +++ b/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp @@ -26,7 +26,7 @@ #include "catch/catch.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" namespace { diff --git a/niv/tests/src/exchange/test_shared_memory.cpp b/niv/tests/src/exchange/test_shared_memory.cpp index fcdecec..9e0f75f 100644 --- a/niv/tests/src/exchange/test_shared_memory.cpp +++ b/niv/tests/src/exchange/test_shared_memory.cpp @@ -24,7 +24,7 @@ #include "conduit/conduit_node.hpp" #include "niv/exchange/shared_memory.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "conduit_node_helper.hpp" diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp index 4d8dc61..2b68569 100644 --- a/niv/tests/src/producer/test_arbor_multimeter.cpp +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -28,8 +28,8 @@ #include "conduit/conduit.hpp" -#include "niv/nest_test_data.hpp" #include "niv/producer/arbor_multimeter.hpp" +#include "niv/testing/nest_test_data.hpp" SCENARIO("A multimeter records to a conduit node", "[niv][niv::ArborMultimeter]") { diff --git a/niv/tests/src/producer/test_nest_multimeter.cpp b/niv/tests/src/producer/test_nest_multimeter.cpp index e5444fc..7bbdd4c 100644 --- a/niv/tests/src/producer/test_nest_multimeter.cpp +++ b/niv/tests/src/producer/test_nest_multimeter.cpp @@ -27,8 +27,8 @@ #include "conduit/conduit_node.hpp" -#include "niv/nest_test_data.hpp" #include "niv/producer/nest_multimeter.hpp" +#include "niv/testing/nest_test_data.hpp" SCENARIO("A multimeter records to a conduit node", "[niv][niv::NestMultimeter]") { diff --git a/niv/tests/src/producer/test_sender.cpp b/niv/tests/src/producer/test_sender.cpp index 9650076..a064204 100644 --- a/niv/tests/src/producer/test_sender.cpp +++ b/niv/tests/src/producer/test_sender.cpp @@ -24,8 +24,8 @@ #include "conduit/conduit_node.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/nest_test_data.hpp" #include "niv/producer/sender.hpp" +#include "niv/testing/nest_test_data.hpp" #include "conduit_node_helper.hpp" diff --git a/niv/tests/src/producer/test_spike_detector.cpp b/niv/tests/src/producer/test_spike_detector.cpp index 2b5a7c6..d64ade4 100644 --- a/niv/tests/src/producer/test_spike_detector.cpp +++ b/niv/tests/src/producer/test_spike_detector.cpp @@ -26,8 +26,8 @@ #include "conduit/conduit_node.hpp" -#include "niv/nest_test_data.hpp" #include "niv/producer/spike_detector.hpp" +#include "niv/testing/nest_test_data.hpp" SCENARIO("A spike detector records to a conduit node", "[niv][niv::SpikeDetector]") { diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index 71f2068..a24c5c1 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -28,7 +28,7 @@ #include "conduit/conduit_node.hpp" #include "niv/exchange/node_storage.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" #include "conduit_node_helper.hpp" diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/nest_test_data.cpp index 2fac8f3..8b175e4 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/nest_test_data.cpp @@ -30,7 +30,7 @@ SUPPRESS_WARNINGS_END #include "conduit/conduit_node.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" namespace pyniv { diff --git a/pyniv/src/testing/testing.cpp b/pyniv/src/testing/testing.cpp index 8066e7d..61a98b3 100644 --- a/pyniv/src/testing/testing.cpp +++ b/pyniv/src/testing/testing.cpp @@ -21,7 +21,7 @@ #include "pyniv.hpp" -#include "niv/nest_test_data.hpp" +#include "niv/testing/nest_test_data.hpp" namespace pyniv { From f30db1f2e75e16ea0faa7f8184efbbaee03540aa Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Thu, 29 Mar 2018 16:56:42 +0200 Subject: [PATCH 81/82] Split nest_test_data into data and helpers --- niv/include/niv/testing/conduit_schema.hpp | 60 +++++++++++ .../testing/{nest_test_data.hpp => data.hpp} | 99 +++++-------------- niv/include/niv/testing/helpers.hpp | 57 +++++++++++ niv/src/consumer/arbor_multimeter.cpp | 2 +- .../testing/{nest_test_data.cpp => data.cpp} | 55 +---------- niv/src/testing/helpers.cpp | 83 ++++++++++++++++ .../src/consumer/test_arbor_multimeter.cpp | 8 +- niv/tests/src/consumer/test_device.cpp | 2 +- niv/tests/src/consumer/test_integration.cpp | 3 +- niv/tests/src/consumer/test_multimeter.cpp | 2 +- .../src/consumer/test_nest_multimeter.cpp | 8 +- niv/tests/src/consumer/test_receiver.cpp | 10 +- niv/tests/src/exchange/test_node_storage.cpp | 18 ++-- .../src/exchange/test_relay_shared_memory.cpp | 16 +-- .../test_relay_shared_memory_mutex.cpp | 18 ++-- .../test_relay_shared_memory_threaded.cpp | 4 +- niv/tests/src/exchange/test_shared_memory.cpp | 46 ++++----- .../src/producer/test_arbor_multimeter.cpp | 6 +- .../src/producer/test_nest_multimeter.cpp | 4 +- niv/tests/src/producer/test_sender.cpp | 6 +- .../src/producer/test_spike_detector.cpp | 2 +- niv/tests/src/test_conduit.cpp | 69 +++++++------ .../testing/{nest_test_data.cpp => data.cpp} | 30 +----- pyniv/src/testing/helpers.cpp | 65 ++++++++++++ pyniv/src/testing/testing.cpp | 8 +- pyniv/tests/src/consumer/test_receiver.py | 8 +- 26 files changed, 416 insertions(+), 273 deletions(-) create mode 100644 niv/include/niv/testing/conduit_schema.hpp rename niv/include/niv/testing/{nest_test_data.hpp => data.hpp} (76%) create mode 100644 niv/include/niv/testing/helpers.hpp rename niv/src/testing/{nest_test_data.cpp => data.cpp} (69%) create mode 100644 niv/src/testing/helpers.cpp rename pyniv/src/testing/{nest_test_data.cpp => data.cpp} (78%) create mode 100644 pyniv/src/testing/helpers.cpp diff --git a/niv/include/niv/testing/conduit_schema.hpp b/niv/include/niv/testing/conduit_schema.hpp new file mode 100644 index 0000000..fc7bad8 --- /dev/null +++ b/niv/include/niv/testing/conduit_schema.hpp @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_INCLUDE_NIV_TESTING_CONDUIT_SCHEMA_HPP_ +#define NIV_INCLUDE_NIV_TESTING_CONDUIT_SCHEMA_HPP_ + +namespace niv { +namespace testing { +namespace conduit_schema { + +template +inline std::string OpenTag(T tag) { + std::stringstream s; + s << '\"' << tag << '\"' << ":{ \n"; + return s.str(); +} + +inline std::string CloseTag() { return std::string("} \n"); } +inline std::string CloseTagNext() { return std::string("}, \n"); } + +inline std::string DoubleData(std::size_t offset) { + std::stringstream s; + s << "dtype:float64, "; + s << "number_of_elements:1, "; + s << "offset:" << offset << ", "; + s << "stride:8, "; + s << "element_bytes:8"; + s << "\n"; + return s.str(); +} + +inline void RemoveNextIndicator(std::stringstream* s) { + s->clear(); + s->seekp(s->str().size() - 3); + *s << " \n"; +} + +} // namespace conduit_schema +} // namespace testing +} // namespace niv + +#endif // NIV_INCLUDE_NIV_TESTING_CONDUIT_SCHEMA_HPP_ diff --git a/niv/include/niv/testing/nest_test_data.hpp b/niv/include/niv/testing/data.hpp similarity index 76% rename from niv/include/niv/testing/nest_test_data.hpp rename to niv/include/niv/testing/data.hpp index baf6ac6..c7d87fb 100644 --- a/niv/include/niv/testing/nest_test_data.hpp +++ b/niv/include/niv/testing/data.hpp @@ -19,29 +19,21 @@ // limitations under the License. //------------------------------------------------------------------------------ -#ifndef NIV_INCLUDE_NIV_NEST_TEST_DATA_HPP_ -#define NIV_INCLUDE_NIV_NEST_TEST_DATA_HPP_ +#ifndef NIV_INCLUDE_NIV_TESTING_DATA_HPP_ +#define NIV_INCLUDE_NIV_TESTING_DATA_HPP_ #include #include #include "niv/producer/nest_multimeter.hpp" -namespace niv { - -class Testing { - public: - Testing() = delete; - Testing(const Testing&) = delete; - Testing(Testing&&) = delete; - ~Testing() = delete; - - Testing& operator=(const Testing&) = delete; - Testing& operator=(Testing&&) = delete; -}; +#include "niv/testing/conduit_schema.hpp" +namespace niv { namespace testing { +class Data; + #if defined __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" @@ -126,14 +118,14 @@ inline std::string PathFor(const std::string& device_name, } // clang-format off -static const std::vector ANY_VALUES{ +static const std::vector ANY_DATA_VALUES{ 0.111, 0.112, 0.113, 0.121, 0.122, 0.123, 0.131, 0.132, 0.133, 0.211, 0.212, 0.213, 0.221, 0.222, 0.223, 0.231, 0.232, 0.233, 0.311, 0.312, 0.313, 0.321, 0.322, 0.323, 0.331, 0.332, 0.333}; // clang-format on -static const double ANY_VALUE{ANY_VALUES[0]}; -static const std::vector ANY_VALUES_FOR_ATTRIBUTES{ - ANY_VALUES[0], ANY_VALUES[3], ANY_VALUES[6]}; +static const double ANY_DATA_VALUE{ANY_DATA_VALUES[0]}; +static const std::vector ANY_DATA_VALUES_FOR_ATTRIBUTES{ + ANY_DATA_VALUES[0], ANY_DATA_VALUES[3], ANY_DATA_VALUES[6]}; static const std::size_t TIME_STRIDE{9}; static const std::size_t ATTRIBUTE_STRIDE{3}; @@ -144,7 +136,7 @@ inline double ValueAt(std::size_t time_id, std::size_t attribute_id, const std::size_t index = time_id * TIME_STRIDE + attribute_id * ATTRIBUTE_STRIDE + neuron_id * ID_STRIDE; - return ANY_VALUES[index]; + return ANY_DATA_VALUES[index]; } static const std::size_t ANY_TIME_OFFSET{ANY_INDEX * niv::testing::TIME_STRIDE}; @@ -165,81 +157,42 @@ static const std::size_t THIRD_ID_OFFSET{THIRD_INDEX * niv::testing::ID_STRIDE}; static const std::vector ID_OFFSETS{ ANY_ID_OFFSET, ANOTHER_ID_OFFSET, THIRD_ID_OFFSET}; -template -inline std::string OpenTag(T tag) { - std::stringstream s; - s << '\"' << tag << '\"' << ":{ \n"; - return s.str(); -} - -inline std::string CloseTag() { return std::string("} \n"); } -inline std::string CloseTagNext() { return std::string("}, \n"); } - -inline std::string DoubleData(std::size_t offset) { - std::stringstream s; - s << "dtype:float64, "; - s << "number_of_elements:1, "; - s << "offset:" << offset << ", "; - s << "stride:8, "; - s << "element_bytes:8"; - s << "\n"; - return s.str(); -} - -inline void RemoveNextIndicator(std::stringstream* s) { - s->clear(); - s->seekp(s->str().size() - 3); - *s << " \n"; -} - inline static const std::string AnyNestDataSchema() { std::stringstream s; std::size_t offset = 0; const std::size_t datum_size = 8; s << "{\n"; - s << " " << OpenTag(ANY_MULTIMETER_NAME); + s << " " << conduit_schema::OpenTag(ANY_MULTIMETER_NAME); for (auto time : ANY_TIMES) { - s << " " << OpenTag(time); + s << " " << conduit_schema::OpenTag(time); for (auto attribute : ANY_ATTRIBUTES) { - s << " " << OpenTag(attribute); + s << " " << conduit_schema::OpenTag(attribute); for (auto id : ANY_IDS) { - s << " " << OpenTag(id); - s << " " << DoubleData((offset++) * datum_size); - s << " " << CloseTagNext(); + s << " " << conduit_schema::OpenTag(id); + s << " " + << conduit_schema::DoubleData((offset++) * datum_size); + s << " " << conduit_schema::CloseTagNext(); } - RemoveNextIndicator(&s); - s << " " << CloseTagNext(); + conduit_schema::RemoveNextIndicator(&s); + s << " " << conduit_schema::CloseTagNext(); } - RemoveNextIndicator(&s); - s << " " << CloseTagNext(); + conduit_schema::RemoveNextIndicator(&s); + s << " " << conduit_schema::CloseTagNext(); } - RemoveNextIndicator(&s); - s << " " << CloseTag(); + conduit_schema::RemoveNextIndicator(&s); + s << " " << conduit_schema::CloseTag(); s << "}"; return s.str(); } static conduit::Node ANY_NEST_DATA{ - AnyNestDataSchema(), const_cast(ANY_VALUES.data()), false}; + AnyNestDataSchema(), const_cast(ANY_DATA_VALUES.data()), false}; #if defined __GNUC__ #pragma GCC diagnostic pop #endif -void Send(const conduit::Node& node); - -conduit::Node AnyNode(); - -conduit::Node AnotherNode(); - -conduit::Node Update(); - -conduit::Node UpdatedNode(); -conduit::Node UpdatedNodeAllZeros(); - -conduit::Node ADifferentNode(); - } // namespace testing } // namespace niv -#endif // NIV_INCLUDE_NIV_NEST_TEST_DATA_HPP_ +#endif // NIV_INCLUDE_NIV_TESTING_DATA_HPP_ diff --git a/niv/include/niv/testing/helpers.hpp b/niv/include/niv/testing/helpers.hpp new file mode 100644 index 0000000..f95e2ca --- /dev/null +++ b/niv/include/niv/testing/helpers.hpp @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef NIV_INCLUDE_NIV_TESTING_HELPERS_HPP_ +#define NIV_INCLUDE_NIV_TESTING_HELPERS_HPP_ + +#include "conduit/conduit_node.hpp" + +namespace niv { +namespace testing { + +class Helpers; + +void Send(const conduit::Node& node); + +conduit::Node AnyNode(); +conduit::Node AnotherNode(); + +conduit::Node AnyUpdate(); +conduit::Node UpdatedNode(); +conduit::Node UpdatedNodeAllZeros(); + +conduit::Node ADifferentNode(); + +static const conduit::Node ANY_NODE{AnyNode()}; +static const conduit::Node ANOTHER_NODE{AnotherNode()}; + +static const conduit::Node ANY_UPDATE{AnyUpdate()}; +static const conduit::Node UPDATED_NODE{UpdatedNode()}; +static const conduit::Node UPDATED_NODE_ALL_ZEROS{UpdatedNodeAllZeros()}; + +static const conduit::Node A_DIFFERENT_NODE{ADifferentNode()}; + +static const double ANY_VALUE{4.123}; + +} // namespace testing +} // namespace niv + +#endif // NIV_INCLUDE_NIV_TESTING_HELPERS_HPP_ diff --git a/niv/src/consumer/arbor_multimeter.cpp b/niv/src/consumer/arbor_multimeter.cpp index 60284f9..06300ac 100644 --- a/niv/src/consumer/arbor_multimeter.cpp +++ b/niv/src/consumer/arbor_multimeter.cpp @@ -28,7 +28,7 @@ #include "conduit/conduit_node.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" namespace niv { namespace consumer { diff --git a/niv/src/testing/nest_test_data.cpp b/niv/src/testing/data.cpp similarity index 69% rename from niv/src/testing/nest_test_data.cpp rename to niv/src/testing/data.cpp index 35fbd60..3a1a696 100644 --- a/niv/src/testing/nest_test_data.cpp +++ b/niv/src/testing/data.cpp @@ -19,7 +19,7 @@ // limitations under the License. //------------------------------------------------------------------------------ -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" #include #include @@ -59,58 +59,5 @@ std::vector ThirdAttributesValues(double time) { std::string AnyMultimeterName() { return "multimeter A"; } -void Send(const conduit::Node& node) { - exchange::RelaySharedMemory relay; - relay.Send(node); -} - -conduit::Node AnyNode() { - conduit::Node node; - node["A/B/C"] = 3.1415; - node["A/B/D"] = 4.124; - node["A/E"] = 42.0; - return node; -} - -conduit::Node AnotherNode() { - conduit::Node node; - node["A/B/C"] = 2.0 * 3.1415; - node["A/B/D"] = 3.0 * 4.124; - node["A/E"] = 4.0 * 42.0; - return node; -} - -conduit::Node Update() { - conduit::Node node; - node["A/B/F"] = 2.0 * 3.1415; - node["A/B/G"] = 3.0 * 4.124; - node["A/H"] = 4.0 * 42.0; - return node; -} - -conduit::Node UpdatedNode() { - conduit::Node node; - node["A/B/C"] = 3.1415; - node["A/B/D"] = 4.124; - node["A/E"] = 42.0; - node["A/B/F"] = 2.0 * 3.1415; - node["A/B/G"] = 3.0 * 4.124; - node["A/H"] = 4.0 * 42.0; - return node; -} - -conduit::Node UpdatedNodeAllZeros() { - conduit::Node node; - node["A/B/C"] = 0.0; - node["A/B/D"] = 0.0; - node["A/E"] = 0.0; - node["A/B/F"] = 0.0; - node["A/B/G"] = 0.0; - node["A/H"] = 0.0; - return node; -} - -conduit::Node ADifferentNode() { return Update(); } - } // namespace testing } // namespace niv diff --git a/niv/src/testing/helpers.cpp b/niv/src/testing/helpers.cpp new file mode 100644 index 0000000..8a780da --- /dev/null +++ b/niv/src/testing/helpers.cpp @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "niv/testing/helpers.hpp" + +#include "niv/exchange/relay_shared_memory.hpp" + +namespace niv { +namespace testing { + +void Send(const conduit::Node& node) { + exchange::RelaySharedMemory relay; + relay.Send(node); +} + +conduit::Node AnyNode() { + conduit::Node node; + node["A/B/C"] = 3.1415; + node["A/B/D"] = 4.124; + node["A/E"] = 42.0; + return node; +} + +conduit::Node AnotherNode() { + conduit::Node node; + node["A/B/C"] = 2.0 * 3.1415; + node["A/B/D"] = 3.0 * 4.124; + node["A/E"] = 4.0 * 42.0; + return node; +} + +conduit::Node AnyUpdate() { + conduit::Node node; + node["A/B/F"] = 2.0 * 3.1415; + node["A/B/G"] = 3.0 * 4.124; + node["A/H"] = 4.0 * 42.0; + return node; +} + +conduit::Node UpdatedNode() { + conduit::Node node; + node["A/B/C"] = 3.1415; + node["A/B/D"] = 4.124; + node["A/E"] = 42.0; + node["A/B/F"] = 2.0 * 3.1415; + node["A/B/G"] = 3.0 * 4.124; + node["A/H"] = 4.0 * 42.0; + return node; +} + +conduit::Node UpdatedNodeAllZeros() { + conduit::Node node; + node["A/B/C"] = 0.0; + node["A/B/D"] = 0.0; + node["A/E"] = 0.0; + node["A/B/F"] = 0.0; + node["A/B/G"] = 0.0; + node["A/H"] = 0.0; + return node; +} + +conduit::Node ADifferentNode() { return AnyUpdate(); } + +} // namespace testing +} // namespace niv diff --git a/niv/tests/src/consumer/test_arbor_multimeter.cpp b/niv/tests/src/consumer/test_arbor_multimeter.cpp index 0ed6462..0cc5bab 100644 --- a/niv/tests/src/consumer/test_arbor_multimeter.cpp +++ b/niv/tests/src/consumer/test_arbor_multimeter.cpp @@ -25,7 +25,7 @@ #include "catch/Catch.hpp" #include "niv/consumer/arbor_multimeter.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" #include "test_utilities/vector_all_nan_or_empty.hpp" @@ -44,7 +44,7 @@ SCENARIO("ArborMultimeter retrieves datum for time, attribute, neuron", const std::size_t DATUM_OFFSET{niv::testing::ANY_TIME_OFFSET + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + niv::testing::THIRD_ID_OFFSET}; - REQUIRE(datum == Approx(niv::testing::ANY_VALUES[DATUM_OFFSET])); + REQUIRE(datum == Approx(niv::testing::ANY_DATA_VALUES[DATUM_OFFSET])); } } @@ -92,7 +92,7 @@ SCENARIO("ArborMultimeter provides time series data", const auto DATUM_INDEX{time_offset + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + niv::testing::THIRD_ID_OFFSET}; - expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + expected.push_back(niv::testing::ANY_DATA_VALUES[DATUM_INDEX]); } const std::vector nans(niv::testing::ANY_TIMES_STRING.size(), std::nan("")); @@ -155,7 +155,7 @@ SCENARIO("ArborMultimeter provides timestep data for all neurons", const auto ID_OFFSET{i * niv::testing::ID_STRIDE}; const auto DATUM_INDEX{niv::testing::THIRD_TIME_OFFSET + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + ID_OFFSET}; - expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + expected.push_back(niv::testing::ANY_DATA_VALUES[DATUM_INDEX]); } GIVEN("a multimeter providing access to some data") { diff --git a/niv/tests/src/consumer/test_device.cpp b/niv/tests/src/consumer/test_device.cpp index 508c31a..5859154 100644 --- a/niv/tests/src/consumer/test_device.cpp +++ b/niv/tests/src/consumer/test_device.cpp @@ -25,7 +25,7 @@ #include "catch/catch.hpp" #include "niv/consumer/device.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" namespace Catch { namespace Matchers { diff --git a/niv/tests/src/consumer/test_integration.cpp b/niv/tests/src/consumer/test_integration.cpp index 4a3adbf..03b1005 100644 --- a/niv/tests/src/consumer/test_integration.cpp +++ b/niv/tests/src/consumer/test_integration.cpp @@ -26,7 +26,8 @@ #include "niv/consumer/backend.hpp" #include "niv/consumer/nest_multimeter.hpp" #include "niv/consumer/receiver.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" +#include "niv/testing/helpers.hpp" SCENARIO("Consumer integration", "[niv][integration]") { GIVEN("The required objects") { diff --git a/niv/tests/src/consumer/test_multimeter.cpp b/niv/tests/src/consumer/test_multimeter.cpp index 8b769d3..8b98b7c 100644 --- a/niv/tests/src/consumer/test_multimeter.cpp +++ b/niv/tests/src/consumer/test_multimeter.cpp @@ -22,7 +22,7 @@ #include "catch/catch.hpp" #include "niv/consumer/multimeter.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" SCENARIO("consumer::Multimeter lists attributes for a timestep", "[niv][niv::consumer][niv::consumer::Multimeter]") { diff --git a/niv/tests/src/consumer/test_nest_multimeter.cpp b/niv/tests/src/consumer/test_nest_multimeter.cpp index 30a46c1..e6c76a5 100644 --- a/niv/tests/src/consumer/test_nest_multimeter.cpp +++ b/niv/tests/src/consumer/test_nest_multimeter.cpp @@ -26,7 +26,7 @@ #include "conduit/conduit_node.hpp" #include "niv/consumer/nest_multimeter.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" #include "test_utilities/vector_all_nan_or_empty.hpp" @@ -44,7 +44,7 @@ SCENARIO("NestMultimeter retrieves datum for time, attribute, neuron", const std::size_t DATUM_OFFSET{niv::testing::ANY_TIME_OFFSET + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + niv::testing::THIRD_ID_OFFSET}; - REQUIRE(datum == Approx(niv::testing::ANY_VALUES[DATUM_OFFSET])); + REQUIRE(datum == Approx(niv::testing::ANY_DATA_VALUES[DATUM_OFFSET])); } } @@ -92,7 +92,7 @@ SCENARIO("NestMultimeter provides time series data", const auto DATUM_INDEX{time_offset + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + niv::testing::THIRD_ID_OFFSET}; - expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + expected.push_back(niv::testing::ANY_DATA_VALUES[DATUM_INDEX]); } const std::vector nans(niv::testing::ANY_TIMES_STRING.size(), std::nan("")); @@ -154,7 +154,7 @@ SCENARIO("NestMultimeter provides timestep data for all neurons", const auto ID_OFFSET{i * niv::testing::ID_STRIDE}; const auto DATUM_INDEX{niv::testing::THIRD_TIME_OFFSET + niv::testing::ANOTHER_ATTRIBUTE_OFFSET + ID_OFFSET}; - expected.push_back(niv::testing::ANY_VALUES[DATUM_INDEX]); + expected.push_back(niv::testing::ANY_DATA_VALUES[DATUM_INDEX]); } GIVEN("a multimeter providing access to some data") { diff --git a/niv/tests/src/consumer/test_receiver.cpp b/niv/tests/src/consumer/test_receiver.cpp index c899577..d2b7b9a 100644 --- a/niv/tests/src/consumer/test_receiver.cpp +++ b/niv/tests/src/consumer/test_receiver.cpp @@ -23,7 +23,7 @@ #include "niv/consumer/receiver.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" #include "conduit_node_helper.hpp" @@ -36,17 +36,17 @@ SCENARIO("received data is aggregated in the consumer::Receiver", niv::exchange::RelaySharedMemory sender; WHEN("Data is sent and a receive is triggered") { - sender.Send(niv::testing::AnyNode()); + sender.Send(niv::testing::ANY_NODE); receiver.Receive(); THEN("it is received correctly") { - REQUIRE_THAT(receiving_node, Equals(niv::testing::AnyNode())); + REQUIRE_THAT(receiving_node, Equals(niv::testing::ANY_NODE)); } WHEN("an update is sent and a receive is triggered") { - sender.Send(niv::testing::Update()); + sender.Send(niv::testing::ANY_UPDATE); receiver.Receive(); THEN("then the data has been updated") { - REQUIRE_THAT(receiving_node, Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(receiving_node, Equals(niv::testing::UPDATED_NODE)); } } } diff --git a/niv/tests/src/exchange/test_node_storage.cpp b/niv/tests/src/exchange/test_node_storage.cpp index a972c53..1f1e3b2 100644 --- a/niv/tests/src/exchange/test_node_storage.cpp +++ b/niv/tests/src/exchange/test_node_storage.cpp @@ -26,7 +26,7 @@ #include "catch/catch.hpp" #include "niv/exchange/node_storage.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" #include "conduit_node_helper.hpp" @@ -59,9 +59,9 @@ SCENARIO("storing and reading a node", "[niv][niv::NodeStorage]") { GIVEN("a node storage") { ::NodeStorage storage; WHEN("a node is stored") { - storage.Store(niv::testing::AnyNode()); + storage.Store(niv::testing::ANY_NODE); THEN("it can be read") { - REQUIRE_THAT(storage.Read(), Equals(niv::testing::AnyNode())); + REQUIRE_THAT(storage.Read(), Equals(niv::testing::ANY_NODE)); } } } @@ -72,7 +72,7 @@ SCENARIO("storing and reading a node yields contifguous data", GIVEN("a node storage") { ::NodeStorage storage; WHEN("a node is stored and retrieved") { - storage.Store(niv::testing::AnyNode()); + storage.Store(niv::testing::ANY_NODE); conduit::Node read{storage.Read()}; THEN("the read node's data is contiguous") { REQUIRE(read.is_contiguous()); @@ -85,13 +85,13 @@ SCENARIO("a node can be stored and read multiple times", "[niv][niv::NodeStorage]") { GIVEN("a node stored and read back") { ::NodeStorage storage; - storage.Store(niv::testing::AnyNode()); + storage.Store(niv::testing::ANY_NODE); storage.Store(storage.Read()); WHEN("the node is read") { conduit::Node read_node{storage.Read()}; THEN("it is equal to the initial one") { - REQUIRE_THAT(read_node, Equals(niv::testing::AnyNode())); + REQUIRE_THAT(read_node, Equals(niv::testing::ANY_NODE)); } } } @@ -100,13 +100,13 @@ SCENARIO("a node can be stored and read multiple times", SCENARIO("a node can be listening to changes", "[niv][niv::NodeStorage]") { GIVEN("a node listening to data") { ::NodeStorage storage; - storage.Store(niv::testing::AnyNode()); + storage.Store(niv::testing::ANY_NODE); conduit::Node listening_node{storage.Listen()}; WHEN("stored data is changed") { - storage.Store(niv::testing::AnotherNode()); + storage.Store(niv::testing::ANOTHER_NODE); THEN("the listening node gets the change") { - REQUIRE_THAT(listening_node, Equals(niv::testing::AnotherNode())); + REQUIRE_THAT(listening_node, Equals(niv::testing::ANOTHER_NODE)); } } } diff --git a/niv/tests/src/exchange/test_relay_shared_memory.cpp b/niv/tests/src/exchange/test_relay_shared_memory.cpp index 3cb05b8..8e776ef 100644 --- a/niv/tests/src/exchange/test_relay_shared_memory.cpp +++ b/niv/tests/src/exchange/test_relay_shared_memory.cpp @@ -27,7 +27,7 @@ #include "niv/exchange/relay_shared_memory.hpp" #include "niv/exchange/shared_memory.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" #include "conduit_node_helper.hpp" @@ -37,13 +37,13 @@ SCENARIO("Data gets transported", "[niv][niv::RelaySharedMemory]") { niv::exchange::RelaySharedMemory simulation_relay; WHEN("a node is sent via the simulation relay") { - simulation_relay.Send(niv::testing::AnyNode()); + simulation_relay.Send(niv::testing::ANY_NODE); WHEN("data is received via the visualization relay") { conduit::Node received_node{visualization_relay.Receive()}; THEN("received data matches original data") { - REQUIRE_THAT(received_node, Equals(niv::testing::AnyNode())); + REQUIRE_THAT(received_node, Equals(niv::testing::ANY_NODE)); } } } @@ -54,14 +54,14 @@ SCENARIO("data in relay gets updated on sending update", "[niv][niv::RelaySharedMemory]") { GIVEN("a relay storing data") { niv::exchange::RelaySharedMemory simulation_relay; - simulation_relay.Send(niv::testing::AnyNode()); + simulation_relay.Send(niv::testing::ANY_NODE); WHEN("an update gets sent to the relay") { - simulation_relay.Send(niv::testing::Update()); + simulation_relay.Send(niv::testing::ANY_UPDATE); WHEN("the node is received from the relay") { conduit::Node received_node{simulation_relay.Receive()}; THEN("the received node includes the update") { - REQUIRE_THAT(received_node, Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(received_node, Equals(niv::testing::UPDATED_NODE)); } } } @@ -72,7 +72,7 @@ SCENARIO("Data in relay is cleared on receive", "[niv][niv::RelaySharedMemory]") { GIVEN("A synchronized relay with some data") { niv::exchange::RelaySharedMemory relay; - relay.Send(niv::testing::AnyNode()); + relay.Send(niv::testing::ANY_NODE); WHEN("Data is received") { auto node{relay.Receive()}; @@ -98,7 +98,7 @@ SCENARIO("Relay's emptyness is passed throug shared memory", } WHEN("Data is sent") { - relay_segment.Send(niv::testing::AnyNode()); + relay_segment.Send(niv::testing::ANY_NODE); THEN("both relays are not empty.") { REQUIRE_FALSE(relay_segment.IsEmpty()); REQUIRE_FALSE(relay_access.IsEmpty()); diff --git a/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp b/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp index 473a0b2..f61a500 100644 --- a/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp +++ b/niv/tests/src/exchange/test_relay_shared_memory_mutex.cpp @@ -24,7 +24,7 @@ #include "catch/catch.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" SCENARIO("Mutex does not stall multiple sends/receives", "[niv][niv::RelaySharedMemory]") { @@ -33,30 +33,30 @@ SCENARIO("Mutex does not stall multiple sends/receives", niv::exchange::RelaySharedMemory relay_access; THEN("send, receive works") { - relay_segment.Send(niv::testing::AnyNode()); + relay_segment.Send(niv::testing::ANY_NODE); relay_access.Receive(); } THEN("receive, send works") { relay_access.Receive(); - relay_segment.Send(niv::testing::AnyNode()); + relay_segment.Send(niv::testing::ANY_NODE); } THEN("send, send, receive works") { - relay_segment.Send(niv::testing::AnyNode()); - relay_segment.Send(niv::testing::AnotherNode()); + relay_segment.Send(niv::testing::ANY_NODE); + relay_segment.Send(niv::testing::ANOTHER_NODE); relay_access.Receive(); } THEN("send, receive, send, receive works") { - relay_segment.Send(niv::testing::AnyNode()); + relay_segment.Send(niv::testing::ANY_NODE); relay_access.Receive(); - relay_segment.Send(niv::testing::AnotherNode()); + relay_segment.Send(niv::testing::ANOTHER_NODE); } THEN("receive, send, send, receive works") { - relay_segment.Send(niv::testing::AnyNode()); - relay_segment.Send(niv::testing::AnotherNode()); + relay_segment.Send(niv::testing::ANY_NODE); + relay_segment.Send(niv::testing::ANOTHER_NODE); relay_access.Receive(); } } diff --git a/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp b/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp index 79810c1..99dd787 100644 --- a/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp +++ b/niv/tests/src/exchange/test_relay_shared_memory_threaded.cpp @@ -26,7 +26,7 @@ #include "catch/catch.hpp" #include "niv/exchange/relay_shared_memory.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" namespace { @@ -38,7 +38,7 @@ void Send(niv::exchange::RelaySharedMemory* relay) { for (auto i = 0u; i < 10; ++i) { const int wait = distribution(generator); std::this_thread::sleep_for(std::chrono::milliseconds(wait)); - relay->Send(niv::testing::AnyNode()); + relay->Send(niv::testing::ANY_NODE); } } diff --git a/niv/tests/src/exchange/test_shared_memory.cpp b/niv/tests/src/exchange/test_shared_memory.cpp index 9e0f75f..a8fcbe1 100644 --- a/niv/tests/src/exchange/test_shared_memory.cpp +++ b/niv/tests/src/exchange/test_shared_memory.cpp @@ -24,7 +24,7 @@ #include "conduit/conduit_node.hpp" #include "niv/exchange/shared_memory.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" #include "conduit_node_helper.hpp" @@ -43,13 +43,13 @@ SCENARIO("Shared memory creation", "[niv][niv::SharedMemory]") { WHEN("I store data in the segment") { auto free_size_before = segment.GetFreeSize(); - segment.Store(niv::testing::AnyNode()); + segment.Store(niv::testing::ANY_NODE); auto free_size_after = segment.GetFreeSize(); THEN("we have less free space in the segment") { REQUIRE(free_size_after < free_size_before); } THEN("I can read the data") { - REQUIRE_THAT(segment.Read(), Equals(niv::testing::AnyNode())); + REQUIRE_THAT(segment.Read(), Equals(niv::testing::ANY_NODE)); } } @@ -72,13 +72,13 @@ SCENARIO("write updated node to shared memory segment", "[niv][niv::SharedMemory]") { GIVEN("a shared memory segment with some data") { niv::exchange::SharedMemory segment{niv::exchange::SharedMemory::Create()}; - segment.Store(niv::testing::AnyNode()); + segment.Store(niv::testing::ANY_NODE); WHEN("a larger node is stored") { - segment.Store(niv::testing::UpdatedNode()); + segment.Store(niv::testing::UPDATED_NODE); WHEN("the node is read") { conduit::Node read_node{segment.Read()}; THEN("the content is equal to the written one") { - REQUIRE_THAT(read_node, Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(read_node, Equals(niv::testing::UPDATED_NODE)); } } } @@ -107,10 +107,10 @@ SCENARIO("Shared memory access", "[niv][niv::SharedMemory]") { niv::exchange::SharedMemory::Access()}; WHEN("data is stored in the shared memory access") { - segment_access.Store(niv::testing::AnyNode()); + segment_access.Store(niv::testing::ANY_NODE); THEN("it can be read") { - REQUIRE_THAT(segment_access.Read(), Equals(niv::testing::AnyNode())); + REQUIRE_THAT(segment_access.Read(), Equals(niv::testing::ANY_NODE)); } } } @@ -128,38 +128,38 @@ SCENARIO("storing and retrieving conduit nodes to/from shared memory", niv::exchange::SharedMemory::Access()}; WHEN("a node is stored in the shared memory segment") { - shared_memory_segment.Store(niv::testing::AnyNode()); + shared_memory_segment.Store(niv::testing::ANY_NODE); THEN("it can be read via access") { REQUIRE_THAT(shared_memory_access.Read(), - Equals(niv::testing::AnyNode())); + Equals(niv::testing::ANY_NODE)); } GIVEN("a node listening to shared memory") { conduit::Node listening_node{shared_memory_access.Listen()}; WHEN("the first node is updated and stored again") { - shared_memory_segment.Store(niv::testing::AnotherNode()); + shared_memory_segment.Store(niv::testing::ANOTHER_NODE); THEN("the result arrives at the listening node") { - REQUIRE_THAT(listening_node, Equals(niv::testing::AnotherNode())); + REQUIRE_THAT(listening_node, Equals(niv::testing::ANOTHER_NODE)); } } } } WHEN("a node is stored in the shared memory access") { - shared_memory_access.Store(niv::testing::AnyNode()); + shared_memory_access.Store(niv::testing::ANY_NODE); THEN("it can be read from the segment") { REQUIRE_THAT(shared_memory_segment.Read(), - Equals(niv::testing::AnyNode())); + Equals(niv::testing::ANY_NODE)); } GIVEN("a node listening to shared memory") { conduit::Node listening_node{shared_memory_segment.Listen()}; WHEN("the first node is updated and stored again") { - shared_memory_segment.Store(niv::testing::AnotherNode()); + shared_memory_segment.Store(niv::testing::ANOTHER_NODE); THEN("the result arrives at the listening node") { - REQUIRE_THAT(listening_node, Equals(niv::testing::AnotherNode())); + REQUIRE_THAT(listening_node, Equals(niv::testing::ANOTHER_NODE)); } } } @@ -176,13 +176,13 @@ SCENARIO("Overwriting data in shared memory", niv::exchange::SharedMemory::Create()}; niv::exchange::SharedMemory shared_memory_access{ niv::exchange::SharedMemory::Access()}; - shared_memory_segment.Store(niv::testing::AnyNode()); + shared_memory_segment.Store(niv::testing::ANY_NODE); WHEN("when new data is stored in the segment") { - shared_memory_segment.Store(niv::testing::ADifferentNode()); + shared_memory_segment.Store(niv::testing::A_DIFFERENT_NODE); WHEN("that data is read") { conduit::Node read_node{shared_memory_access.Read()}; THEN("the read data is equal to the stored one") { - REQUIRE_THAT(read_node, Equals(niv::testing::ADifferentNode())); + REQUIRE_THAT(read_node, Equals(niv::testing::A_DIFFERENT_NODE)); } } } @@ -199,15 +199,15 @@ SCENARIO("data can be updated in shared memory", niv::exchange::SharedMemory segment{niv::exchange::SharedMemory::Create()}; niv::exchange::SharedMemory segment_access{ niv::exchange::SharedMemory::Access()}; - segment.Store(niv::testing::AnyNode()); + segment.Store(niv::testing::ANY_NODE); WHEN("the data in the shared memory is updated") { - segment.Update(niv::testing::Update()); + segment.Update(niv::testing::ANY_UPDATE); THEN("the updated data can be read from the segment") { - REQUIRE_THAT(segment.Read(), Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(segment.Read(), Equals(niv::testing::UPDATED_NODE)); } THEN("the updated data can be read from the segment access") { - REQUIRE_THAT(segment.Read(), Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(segment.Read(), Equals(niv::testing::UPDATED_NODE)); } } segment.Destroy(); diff --git a/niv/tests/src/producer/test_arbor_multimeter.cpp b/niv/tests/src/producer/test_arbor_multimeter.cpp index 2b68569..e8197a2 100644 --- a/niv/tests/src/producer/test_arbor_multimeter.cpp +++ b/niv/tests/src/producer/test_arbor_multimeter.cpp @@ -29,7 +29,7 @@ #include "conduit/conduit.hpp" #include "niv/producer/arbor_multimeter.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" SCENARIO("A multimeter records to a conduit node", "[niv][niv::ArborMultimeter]") { @@ -41,14 +41,14 @@ SCENARIO("A multimeter records to a conduit node", niv::producer::ArborMultimeter::Datum datum{ niv::testing::ANY_TIME + niv::testing::ANY_TIME_OFFSET, niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING, - niv::testing::ANY_VALUE}; + niv::testing::ANY_DATA_VALUE}; multimeter.Record(datum, &node); THEN("the data is properly recorded") { REQUIRE(node[niv::testing::PathFor(niv::testing::ANY_MULTIMETER_NAME, niv::testing::ANY_TIME_STRING, niv::testing::ANOTHER_ATTRIBUTE, niv::testing::THIRD_ID_STRING)] - .as_double() == Approx(niv::testing::ANY_VALUE)); + .as_double() == Approx(niv::testing::ANY_DATA_VALUE)); } } } diff --git a/niv/tests/src/producer/test_nest_multimeter.cpp b/niv/tests/src/producer/test_nest_multimeter.cpp index 7bbdd4c..67e574f 100644 --- a/niv/tests/src/producer/test_nest_multimeter.cpp +++ b/niv/tests/src/producer/test_nest_multimeter.cpp @@ -28,7 +28,7 @@ #include "conduit/conduit_node.hpp" #include "niv/producer/nest_multimeter.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" SCENARIO("A multimeter records to a conduit node", "[niv][niv::NestMultimeter]") { @@ -39,7 +39,7 @@ SCENARIO("A multimeter records to a conduit node", WHEN("recording data") { niv::producer::NestMultimeter::Datum datum{ niv::testing::ANY_TIME, niv::testing::ANY_ID, - niv::testing::ANY_VALUES_FOR_ATTRIBUTES}; + niv::testing::ANY_DATA_VALUES_FOR_ATTRIBUTES}; multimeter.Record(datum); THEN("data is properly recorded") { REQUIRE(node[niv::testing::PathFor(niv::testing::ANY_MULTIMETER_NAME, diff --git a/niv/tests/src/producer/test_sender.cpp b/niv/tests/src/producer/test_sender.cpp index a064204..a41643e 100644 --- a/niv/tests/src/producer/test_sender.cpp +++ b/niv/tests/src/producer/test_sender.cpp @@ -25,7 +25,7 @@ #include "niv/exchange/relay_shared_memory.hpp" #include "niv/producer/sender.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/helpers.hpp" #include "conduit_node_helper.hpp" @@ -33,7 +33,7 @@ SCENARIO("data is sent via the producer::Sender", "[niv][niv::producer::Sender]") { GIVEN("sender and receiving relay") { niv::producer::Sender sender; - conduit::Node sending_node{niv::testing::AnyNode()}; + conduit::Node sending_node{niv::testing::ANY_NODE}; sender.SetNode(&sending_node); niv::exchange::RelaySharedMemory receiver; @@ -42,7 +42,7 @@ SCENARIO("data is sent via the producer::Sender", conduit::Node received_node = receiver.Receive(); THEN("data is received correctly") { - REQUIRE_THAT(received_node, Equals(niv::testing::AnyNode())); + REQUIRE_THAT(received_node, Equals(niv::testing::ANY_NODE)); } } } diff --git a/niv/tests/src/producer/test_spike_detector.cpp b/niv/tests/src/producer/test_spike_detector.cpp index d64ade4..6168314 100644 --- a/niv/tests/src/producer/test_spike_detector.cpp +++ b/niv/tests/src/producer/test_spike_detector.cpp @@ -27,7 +27,7 @@ #include "conduit/conduit_node.hpp" #include "niv/producer/spike_detector.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" SCENARIO("A spike detector records to a conduit node", "[niv][niv::SpikeDetector]") { diff --git a/niv/tests/src/test_conduit.cpp b/niv/tests/src/test_conduit.cpp index a24c5c1..44ae4f4 100644 --- a/niv/tests/src/test_conduit.cpp +++ b/niv/tests/src/test_conduit.cpp @@ -28,7 +28,8 @@ #include "conduit/conduit_node.hpp" #include "niv/exchange/node_storage.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/conduit_schema.hpp" +#include "niv/testing/helpers.hpp" #include "conduit_node_helper.hpp" @@ -98,7 +99,7 @@ SCENARIO( std::string schema; std::vector bytes; - SerializeConstRef(niv::testing::AnyNode(), &schema, &bytes); + SerializeConstRef(niv::testing::ANY_NODE, &schema, &bytes); conduit::Node second_node; second_node.set_data_using_schema(conduit::Schema(schema), bytes.data()); @@ -109,7 +110,7 @@ SCENARIO( conduit::Node third_node; third_node.set_data_using_schema(conduit::Schema(schema), bytes.data()); - REQUIRE(third_node.to_json() == niv::testing::AnyNode().to_json()); + REQUIRE(third_node.to_json() == niv::testing::ANY_NODE.to_json()); } } } @@ -129,7 +130,7 @@ SCENARIO( std::vector data; niv::exchange::NodeStorage> storage(&schema, &data); - storage.Store(niv::testing::AnyNode()); + storage.Store(niv::testing::ANY_NODE); constexpr bool external{true}; conduit::Node external_node(schema, data.data(), external); @@ -245,14 +246,14 @@ SCENARIO( SCENARIO("update inserts new nodes", "[conduit]") { GIVEN("A conduit tree") { - conduit::Node a = niv::testing::AnyNode(); + conduit::Node a = niv::testing::ANY_NODE; WHEN("A second node updates the tree") { - conduit::Node b = niv::testing::Update(); + conduit::Node b = niv::testing::ANY_UPDATE; a.update(b); THEN("the first node contains also the content of the second") { - REQUIRE_THAT(a, Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(a, Equals(niv::testing::UPDATED_NODE)); } } } @@ -262,10 +263,10 @@ SCENARIO("node updates into empty node with unexpected order", "[conduit]") { GIVEN("an empty conduit node") { conduit::Node target; WHEN("the target node is updated with some data in unexpected order") { - target.update(niv::testing::Update()); - target.update(niv::testing::AnyNode()); + target.update(niv::testing::ANY_UPDATE); + target.update(niv::testing::ANY_NODE); THEN("the node's layout is unexpected") { - REQUIRE_THAT(target, !Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(target, !Equals(niv::testing::UPDATED_NODE)); } } } @@ -274,12 +275,12 @@ SCENARIO("node updates into empty node with unexpected order", "[conduit]") { SCENARIO("node updates into pre-allocated node with unexpected order", "[conduit]") { GIVEN("an allocated conduit node") { - conduit::Node preallocated{niv::testing::UpdatedNodeAllZeros()}; + conduit::Node preallocated{niv::testing::UPDATED_NODE_ALL_ZEROS}; WHEN("the node is updated with some data in unexpected order") { - preallocated.update(niv::testing::Update()); - preallocated.update(niv::testing::AnyNode()); + preallocated.update(niv::testing::ANY_UPDATE); + preallocated.update(niv::testing::ANY_NODE); THEN("the node's layout is as expected") { - REQUIRE_THAT(preallocated, Equals(niv::testing::UpdatedNode())); + REQUIRE_THAT(preallocated, Equals(niv::testing::UPDATED_NODE)); } } } @@ -288,7 +289,7 @@ SCENARIO("node updates into pre-allocated node with unexpected order", SCENARIO("conduit data layout", "[conduit]") { GIVEN("a compacted conduit node") { conduit::Node node; - niv::testing::UpdatedNode().compact_to(node); + niv::testing::UPDATED_NODE.compact_to(node); THEN("the node's data is contiguous") { REQUIRE(node.is_contiguous()); } WHEN("the node's data is accessed via ptr") { @@ -296,16 +297,12 @@ SCENARIO("conduit data layout", "[conduit]") { reinterpret_cast(node.contiguous_data_ptr()); THEN("the leafs' data is accessible as an array") { - REQUIRE(data_ptr[0] == - niv::testing::UpdatedNode()["A/B/C"].as_double()); - REQUIRE(data_ptr[1] == - niv::testing::UpdatedNode()["A/B/D"].as_double()); - REQUIRE(data_ptr[2] == - niv::testing::UpdatedNode()["A/B/F"].as_double()); - REQUIRE(data_ptr[3] == - niv::testing::UpdatedNode()["A/B/G"].as_double()); - REQUIRE(data_ptr[4] == niv::testing::UpdatedNode()["A/E"].as_double()); - REQUIRE(data_ptr[5] == niv::testing::UpdatedNode()["A/H"].as_double()); + REQUIRE(data_ptr[0] == niv::testing::UPDATED_NODE["A/B/C"].as_double()); + REQUIRE(data_ptr[1] == niv::testing::UPDATED_NODE["A/B/D"].as_double()); + REQUIRE(data_ptr[2] == niv::testing::UPDATED_NODE["A/B/F"].as_double()); + REQUIRE(data_ptr[3] == niv::testing::UPDATED_NODE["A/B/G"].as_double()); + REQUIRE(data_ptr[4] == niv::testing::UPDATED_NODE["A/E"].as_double()); + REQUIRE(data_ptr[5] == niv::testing::UPDATED_NODE["A/H"].as_double()); } } } @@ -349,17 +346,17 @@ SCENARIO("create conduit::Node from data and schema (stringstream)", GIVEN("a schema and data") { std::stringstream schema; schema << "{\n"; - schema << " " << niv::testing::OpenTag(::ANY_TAG); - schema << " " << niv::testing::OpenTag("B"); - schema << " " << niv::testing::DoubleData(0); - schema << " " << niv::testing::CloseTagNext(); - schema << " " << niv::testing::OpenTag("C"); - schema << " " << niv::testing::DoubleData(8); - schema << " " << niv::testing::CloseTag(); - schema << " " << niv::testing::CloseTagNext(); - schema << " " << niv::testing::OpenTag("D"); - schema << " " << niv::testing::DoubleData(16); - schema << " " << niv::testing::CloseTag(); + schema << " " << niv::testing::conduit_schema::OpenTag(::ANY_TAG); + schema << " " << niv::testing::conduit_schema::OpenTag("B"); + schema << " " << niv::testing::conduit_schema::DoubleData(0); + schema << " " << niv::testing::conduit_schema::CloseTagNext(); + schema << " " << niv::testing::conduit_schema::OpenTag("C"); + schema << " " << niv::testing::conduit_schema::DoubleData(8); + schema << " " << niv::testing::conduit_schema::CloseTag(); + schema << " " << niv::testing::conduit_schema::CloseTagNext(); + schema << " " << niv::testing::conduit_schema::OpenTag("D"); + schema << " " << niv::testing::conduit_schema::DoubleData(16); + schema << " " << niv::testing::conduit_schema::CloseTag(); schema << "}"; std::vector data{1.23, 2.34, 3.45}; diff --git a/pyniv/src/testing/nest_test_data.cpp b/pyniv/src/testing/data.cpp similarity index 78% rename from pyniv/src/testing/nest_test_data.cpp rename to pyniv/src/testing/data.cpp index 8b175e4..d84793c 100644 --- a/pyniv/src/testing/nest_test_data.cpp +++ b/pyniv/src/testing/data.cpp @@ -24,29 +24,12 @@ #include // NOLINT #include // NOLINT -SUPPRESS_WARNINGS_BEGIN -#include "boost/python/numpy.hpp" -SUPPRESS_WARNINGS_END - #include "conduit/conduit_node.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" namespace pyniv { - namespace testing { -bool Equal(const conduit::Node& node1, const conduit::Node& node2) { - bool is_equal = (node1.to_json() == node2.to_json()); - if (!is_equal) { - std::cout << "Nodes are not equal:" << std::endl; - std::cout << "Node 1:" << std::endl; - std::cout << node1.to_json() << std::endl; - std::cout << "----------" << std::endl; - std::cout << "Node 2:" << std::endl; - std::cout << node2.to_json() << std::endl; - } - return is_equal; -} boost::python::list TimeOffsets() { boost::python::list ret_val; @@ -71,7 +54,7 @@ boost::python::list IdOffsets() { #endif template <> -void expose() { +void expose() { EXPOSE_CONSTANT(ANY_DEVICE_NAME); EXPOSE_CONSTANT(NOT_A_DEVICE_NAME); @@ -121,7 +104,7 @@ void expose() { EXPOSE_CONSTANT(ANY_NEST_DATA); - EXPOSE_CONSTANT(ANY_VALUE); + EXPOSE_CONSTANT(ANY_DATA_VALUE); EXPOSE_CONSTANT(TIME_STRIDE); EXPOSE_CONSTANT(ATTRIBUTE_STRIDE); EXPOSE_CONSTANT(ID_STRIDE); @@ -137,13 +120,6 @@ void expose() { def("TIME_OFFSETS", &pyniv::testing::TimeOffsets); def("ID_OFFSETS", &pyniv::testing::IdOffsets); - def("Send", &niv::testing::Send); - def("AnyNode", &niv::testing::AnyNode); - def("AnotherNode", &niv::testing::AnotherNode); - def("Update", &niv::testing::Update); - def("UpdatedNode", &niv::testing::UpdatedNode); - def("ADifferentNode", &niv::testing::ADifferentNode); - def("Equal", &pyniv::testing::Equal); def("ValueAt", &niv::testing::ValueAt); } diff --git a/pyniv/src/testing/helpers.cpp b/pyniv/src/testing/helpers.cpp new file mode 100644 index 0000000..446b84c --- /dev/null +++ b/pyniv/src/testing/helpers.cpp @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// nest in situ vis +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include "pyniv.hpp" + +#include // NOLINT +#include // NOLINT + +#include "conduit/conduit_node.hpp" + +#include "niv/testing/helpers.hpp" + +namespace pyniv { +namespace testing { + +bool Equal(const conduit::Node& node1, const conduit::Node& node2) { + bool is_equal = (node1.to_json() == node2.to_json()); + if (!is_equal) { + std::cout << "Nodes are not equal:" << std::endl; + std::cout << "Node 1:" << std::endl; + std::cout << node1.to_json() << std::endl; + std::cout << "----------" << std::endl; + std::cout << "Node 2:" << std::endl; + std::cout << node2.to_json() << std::endl; + } + return is_equal; +} + +} // namespace testing + +#ifndef EXPOSE_CONSTANT +#define EXPOSE_CONSTANT(a) scope().attr(#a) = niv::testing::a +#endif + +template <> +void expose() { + EXPOSE_CONSTANT(ANY_NODE); + EXPOSE_CONSTANT(ANOTHER_NODE); + EXPOSE_CONSTANT(ANY_UPDATE); + EXPOSE_CONSTANT(UPDATED_NODE); + EXPOSE_CONSTANT(A_DIFFERENT_NODE); + + def("Send", &niv::testing::Send); + def("Equal", &pyniv::testing::Equal); +} + +} // namespace pyniv diff --git a/pyniv/src/testing/testing.cpp b/pyniv/src/testing/testing.cpp index 61a98b3..d5a584a 100644 --- a/pyniv/src/testing/testing.cpp +++ b/pyniv/src/testing/testing.cpp @@ -21,10 +21,14 @@ #include "pyniv.hpp" -#include "niv/testing/nest_test_data.hpp" +#include "niv/testing/data.hpp" +#include "niv/testing/helpers.hpp" namespace pyniv { -BOOST_PYTHON_MODULE(_testing) { pyniv::expose(); } +BOOST_PYTHON_MODULE(_testing) { + pyniv::expose(); + pyniv::expose(); +} } // namespace pyniv diff --git a/pyniv/tests/src/consumer/test_receiver.py b/pyniv/tests/src/consumer/test_receiver.py index 4945d36..69653c6 100644 --- a/pyniv/tests/src/consumer/test_receiver.py +++ b/pyniv/tests/src/consumer/test_receiver.py @@ -26,12 +26,12 @@ def test_receiver_aggregates_data(): receiving_node = pyniv.conduit.Node() receiver.SetNode(receiving_node) - pyniv.testing.Send(pyniv.testing.AnyNode()) + pyniv.testing.Send(pyniv.testing.ANY_NODE) receiver.Receive() - assert pyniv.testing.Equal(receiving_node, pyniv.testing.AnyNode()) + assert pyniv.testing.Equal(receiving_node, pyniv.testing.ANY_NODE) - pyniv.testing.Send(pyniv.testing.Update()) + pyniv.testing.Send(pyniv.testing.ANY_UPDATE) receiver.Receive() - assert pyniv.testing.Equal(receiving_node, pyniv.testing.UpdatedNode()) + assert pyniv.testing.Equal(receiving_node, pyniv.testing.UPDATED_NODE) From 8a548c2ca77207eafe201b782f43191b7474e0b1 Mon Sep 17 00:00:00 2001 From: Tom Vierjahn Date: Fri, 30 Mar 2018 01:39:54 +0200 Subject: [PATCH 82/82] Fix style --- niv/include/niv/testing/conduit_schema.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/niv/include/niv/testing/conduit_schema.hpp b/niv/include/niv/testing/conduit_schema.hpp index fc7bad8..76dc7f1 100644 --- a/niv/include/niv/testing/conduit_schema.hpp +++ b/niv/include/niv/testing/conduit_schema.hpp @@ -22,6 +22,8 @@ #ifndef NIV_INCLUDE_NIV_TESTING_CONDUIT_SCHEMA_HPP_ #define NIV_INCLUDE_NIV_TESTING_CONDUIT_SCHEMA_HPP_ +#include + namespace niv { namespace testing { namespace conduit_schema {