Skip to content
Snippets Groups Projects
Commit 0ade56ad authored by Simon Oehrl's avatar Simon Oehrl
Browse files

Merge branch 'revert-f3bd8a22' into 'stable'

Revert "Merge branch 'feature/#7_remove_conan' into 'stable'"

See merge request VR-Group/nest-streaming-module!4
parents f3bd8a22 cc15fbed
Branches stable
No related tags found
1 merge request!4Revert "Merge branch 'feature/#7_remove_conan' into 'stable'"
Showing
with 365 additions and 1555 deletions
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "qvtk-lib/animate.hpp"
namespace vtkexp
{
Animate::Animate(PointData *points) : points_(points)
{
rt_timer_ = new QTimer(this);
play_timer_ = new QTimer(this);
connect(rt_timer_, SIGNAL(timeout()), this, SLOT(ChangeData()));
connect(play_timer_, SIGNAL(timeout()), this, SLOT(Iterate()));
}
void Animate::ChangeData(int time_step)
{
points_->Update(time_step);
emit DataChanged();
}
void Animate::IncreaseSpeed() { play_speed_ += 1; }
void Animate::DecreaseSpeed() { play_speed_ -= 1; }
void Animate::Iterate()
{
rt_timer_->isActive() ? emit LastStep() : emit NextStep();
}
void Animate::StartTimer()
{
rt_timer_->start(1);
play_timer_->start(play_speed_);
}
void Animate::RealtimeButton()
{
if (rt_timer_->isActive())
{
rt_timer_->stop();
emit SwitchRealtime();
}
else
{
rt_timer_->start(1);
emit SwitchRealtime();
}
}
void Animate::SpeedMenu(int index)
{
switch (index)
{
case 0:
play_speed_ = 1000;
break;
case 1:
play_speed_ = 1000 / 5;
break;
case 2:
play_speed_ = 1000 / 10;
break;
case 3:
play_speed_ = 1000 / 50;
break;
case 4:
play_speed_ = 1000 / 100;
break;
default:
play_speed_ = 1000;
break;
}
play_timer_->setInterval(play_speed_);
}
void Animate::PlayButton()
{
play_timer_->isActive() ? play_timer_->stop()
: play_timer_->start(play_speed_);
emit SwitchPlayPause();
}
} // namespace vtkexp
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "qvtk-lib/data_stream.hpp"
#include <vector>
namespace vtkexp
{
DataStream::DataStream() { SetUpStream(); }
void DataStream::SetUpStream()
{
relay_ = new contra::Relay<contra::ZMQTransport>(
contra::ZMQTransport::Type::CLIENT, "tcp://localhost:5555");
multimeter_ = new nesci::consumer::NestMultimeter("recordingNode51");
multimeter_->SetNode(&node_);
}
void DataStream::Update(int time_step)
{
auto time_step_string = std::to_string(static_cast<double>(time_step));
const auto received_nodes = relay_->Receive();
for (auto node : received_nodes)
{
node_.update(node);
}
if (time_step == -1 && !multimeter_->GetTimesteps().empty())
{
time_step_string = multimeter_->GetTimesteps().back();
}
mult_values_ = multimeter_->GetTimestepData(time_step_string, "V_m");
}
std::vector<double> DataStream::GetMultValuesAt(int time_step)
{
Update(time_step);
return mult_values_;
}
std::vector<double> DataStream::GetTimeSteps()
{
std::vector<double> ret;
for (auto value : multimeter_->GetTimesteps())
{
ret.push_back(std::stod(value));
}
return ret;
}
} // namespace vtkexp
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "qvtk-lib/interaction.hpp"
#include <string>
SUPPRESS_WARNINGS_BEGIN
#include "vtkExtractSelection.h"
#include "vtkGeometryFilter.h"
#include "vtkHardwareSelector.h"
#include "vtkIdTypeArray.h"
#include "vtkPointData.h"
#include "vtkProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRendererCollection.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include "vtkVertexGlyphFilter.h"
SUPPRESS_WARNINGS_END
namespace vtkexp
{
vtkStandardNewMacro(Interaction)
Interaction::Interaction()
{
SetUpShaders();
SetUpMapper();
SetUpActor();
}
void Interaction::SetUpMapper()
{
mapper_ = vtkSmartPointer<vtkPointGaussianMapper>::New();
mapper_->SetSplatShaderCode(point_shader_.c_str());
mapper_->ScalarVisibilityOff();
mapper_->SetScaleFactor(0.35);
mapper_->UseLookupTableScalarRangeOn();
mapper_->EmissiveOff();
mapper_->Update();
}
void Interaction::SetUpActor()
{
actor_ = vtkSmartPointer<vtkActor>::New();
actor_->SetMapper(mapper_);
actor_->GetProperty()->SetColor(0.0, 1.0, 0.0);
actor_->GetProperty()->SetEdgeVisibility(1);
}
void Interaction::OnLeftButtonUp()
{
Pick();
vtkSmartPointer<vtkHardwareSelector> selector =
vtkSmartPointer<vtkHardwareSelector>::New();
selector->SetRenderer(
this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());
int *temp = this->Interactor->GetRenderWindow()->GetSize();
unsigned int windowSize[4];
windowSize[0] = temp[2];
windowSize[1] = temp[3];
windowSize[2] = temp[0];
windowSize[3] = temp[1];
/*
for(unsigned int i = 0; i < 4; i++)
{
windowSize[i] = temp[i];
}
*/
selector->SetArea(windowSize);
selector->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_POINTS);
vtkSelection *selection = selector->Select();
std::cout << "Selection has " << selection->GetNumberOfNodes() << " nodes."
<< std::endl;
vtkSmartPointer<vtkExtractSelection> extractSelection =
vtkSmartPointer<vtkExtractSelection>::New();
extractSelection->SetInputData(0, data_);
extractSelection->Update();
vtkSmartPointer<vtkDataSetMapper> mapper =
vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetInputConnection(extractSelection->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(1, 0, 0);
GetDefaultRenderer()->AddActor(actor);
if (id_ != -1)
{
ExtractSelection();
HighlightSelection();
}
else
{
Deselect();
}
vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
}
void Interaction::Pick()
{
int *pos = GetInteractor()->GetEventPosition();
picker_ = vtkSmartPointer<vtkPointPicker>::New();
picker_->SetTolerance(0.015);
picker_->Pick(pos[0], pos[1], 0, GetDefaultRenderer());
id_ = picker_->GetPointId();
std::cout << id_ << std::endl;
}
void Interaction::ExtractSelection()
{
vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New();
ids->SetNumberOfComponents(1);
ids->InsertNextValue(picker_->GetPointId());
vtkSmartPointer<vtkSelectionNode> selectionNode =
vtkSmartPointer<vtkSelectionNode>::New();
selectionNode->SetFieldType(vtkSelectionNode::POINT);
selectionNode->SetContentType(vtkSelectionNode::INDICES);
selectionNode->SetSelectionList(ids);
vtkSmartPointer<vtkSelection> selection =
vtkSmartPointer<vtkSelection>::New();
selection->AddNode(selectionNode);
vtkSmartPointer<vtkExtractSelection> extract_selection =
vtkSmartPointer<vtkExtractSelection>::New();
extract_selection->SetInputData(0, data_);
extract_selection->SetInputData(1, selection);
extract_selection->Update();
selected_ = vtkSmartPointer<vtkUnstructuredGrid>::New();
selected_->ShallowCopy(extract_selection->GetOutput());
neuron_value_ = selected_->GetPointData()->GetScalars()->GetComponent(0, 0);
}
void Interaction::HighlightSelection()
{
vtkSmartPointer<vtkGeometryFilter> geometryFilter =
vtkSmartPointer<vtkGeometryFilter>::New();
geometryFilter->SetInputData(selected_);
geometryFilter->Update();
vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =
vtkSmartPointer<vtkVertexGlyphFilter>::New();
glyphFilter->SetInputData(geometryFilter->GetOutput());
glyphFilter->Update();
mapper_->SetInputData(glyphFilter->GetOutput());
CurrentRenderer->AddActor(actor_);
GetInteractor()->GetRenderWindow()->Render();
}
void Interaction::Deselect()
{
vtkSmartPointer<vtkPolyData> empty = vtkSmartPointer<vtkPolyData>::New();
mapper_->SetInputData(empty);
mapper_->Update();
CurrentRenderer->AddActor(actor_);
GetInteractor()->GetRenderWindow()->Render();
}
void Interaction::SetData(vtkSmartPointer<vtkPolyData> data) { data_ = data; }
void Interaction::SwitchMapper(int rendertype)
{
if (rendertype == 0)
{
mapper_->SetSplatShaderCode(point_shader_.c_str());
}
else if (rendertype == 1)
{
mapper_->SetSplatShaderCode(sphere_shader_.c_str());
}
}
double Interaction::GetNeuronValue() { return neuron_value_; }
vtkIdType Interaction::GetNeuronId() { return id_; }
void Interaction::SetUpShaders()
{
sphere_shader_ =
"//VTK::Color::Impl\n"
"float dist = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
"if (dist > 0.9) {\n"
" discard;\n"
"} else {\n"
" float scale = (1.0 - dist);\n"
" ambientColor *= 0.5;\n"
" diffuseColor *= 0.7;\n"
"}\n";
point_shader_ =
"//VTK::Color::Impl\n"
"ambientColor *= 0.5;\n"
"diffuseColor *= 0.7;\n"
"if (abs(offsetVCVSOutput.x) > 0.3 || abs(offsetVCVSOutput.y) > 0.3) "
"{\n"
" discard;\n"
"}\n"
"if (abs(offsetVCVSOutput.x) < 0.0 && abs(offsetVCVSOutput.y) < 0.0) "
"{\n"
" discard;\n"
"}\n";
}
} // namespace vtkexp
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------
#include "qvtk-lib/main_widget.hpp"
#include "vtkGenericOpenGLRenderWindow.h"
#include "QString"
#include "QtWidgets"
namespace vtkexp
{
MainWidget::MainWidget(PointData *points, QVTKOpenGLWidget *parent)
: QVTKOpenGLWidget(parent)
{
renderwindow_ = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
this->SetRenderWindow(renderwindow_.Get());
style_ = vtkSmartPointer<Interaction>::New();
style_->SetData(points->GetPolyPoints());
this->GetInteractor()->SetInteractorStyle(style_);
vispoints_ = new Visualize(points);
vispoints_->Initialize(renderwindow_, this->GetInteractor());
}
void MainWidget::mouseReleaseEvent(QMouseEvent *event)
{
QVTKOpenGLWidget::mouseReleaseEvent(event);
if (event->button() == Qt::LeftButton && style_->GetNeuronId() != -1)
{
QToolTip::showText(this->mapToGlobal(event->pos()),
QString::number(style_->GetNeuronValue()));
}
}
void MainWidget::ChangeRendertype(int rendertype)
{
vispoints_->SwitchMapper(rendertype);
style_->SwitchMapper(rendertype);
}
void MainWidget::Rerender() { renderwindow_->Render(); }
} // namespace vtkexp
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "qvtk-lib/main_window.hpp"
namespace vtkexp
{
MainWindow::MainWindow(PointData *points) : points_(points)
{
setWindowTitle("QVTK-Neuron-Viewer");
SetUpVisualization();
SetUpContent();
setCentralWidget(dummywidget_);
ConnectSignals();
StartAnimation();
}
void MainWindow::SetUpVisualization()
{
animation_ = new Animate(points_);
mainwidget_ = new MainWidget(points_);
}
void MainWindow::SetUpContent()
{
SetUpSliders();
SetUpLineEdit();
SetUpButtons();
SetUpLayout();
}
void MainWindow::SetUpLayout()
{
dummywidget_ = new QWidget;
grid_ = new QGridLayout;
grid_->addWidget(mainwidget_, 0, 0, 1, -1);
grid_->addWidget(time_label_, 1, 0, 1, 1);
grid_->addWidget(time_slider_, 1, 1, 1, 1);
grid_->addWidget(slider_line_edit_, 1, 2, 1, 10);
grid_->addWidget(render_type_, 1, 14, 1, 1);
grid_->addWidget(rt_button_, 1, 15, 1, 1);
grid_->addWidget(play_button_, 1, 13, 1, 1);
grid_->addWidget(speed_menu_, 1, 12, 1, 1);
dummywidget_->setLayout(grid_);
resize(800, 600);
}
void MainWindow::SetUpLineEdit()
{
slider_line_edit_ = new QLineEdit();
slider_line_edit_->setText(std::to_string(0).c_str());
}
void MainWindow::SetUpSliders()
{
time_slider_ = new QSlider(Qt::Horizontal);
time_label_ = new QLabel("Time:");
InitSlider(time_slider_);
time_slider_->setEnabled(0);
}
void MainWindow::InitSlider(QSlider *slider)
{
slider->setFocusPolicy(Qt::StrongFocus);
slider->setTickPosition(QSlider::TicksAbove);
slider->setTickInterval(50);
slider->setSingleStep(20);
slider->setMinimum(0);
slider->setMaximum(100);
slider->setValue(100);
}
void MainWindow::SetUpButtons()
{
rt_button_ = new QPushButton("Replay", this);
rt_button_->setFixedSize(QSize(80, 32));
play_button_ = new QPushButton("⏸", this);
play_button_->setFixedSize(QSize(32, 32));
render_type_ = new QComboBox(this);
render_type_->setFixedSize(QSize(80, 32));
render_type_->addItems({"Points", "Spheres"});
speed_menu_ = new QComboBox(this);
speed_menu_->addItems({"1/sec", "5/sec", "10/sec", "50/sec", "100/sec"});
}
void MainWindow::StartAnimation() { animation_->StartTimer(); }
void MainWindow::ConnectSignals()
{
connect(speed_menu_, SIGNAL(activated(int)), animation_,
SLOT(SpeedMenu(int)));
connect(rt_button_, SIGNAL(clicked()), animation_, SLOT(RealtimeButton()));
connect(play_button_, SIGNAL(clicked()), animation_, SLOT(PlayButton()));
connect(time_slider_, SIGNAL(valueChanged(int)), animation_,
SLOT(ChangeData(int)));
connect(time_slider_, SIGNAL(valueChanged(int)), SLOT(SliderValue(int)));
connect(slider_line_edit_, SIGNAL(editingFinished()), SLOT(SliderValue()));
connect(render_type_, SIGNAL(currentIndexChanged(int)), mainwidget_,
SLOT(ChangeRendertype(int)));
connect(animation_, SIGNAL(SwitchRealtime()), this, SLOT(Realtime()));
connect(animation_, SIGNAL(SwitchPlayPause()), this, SLOT(PlayPause()));
connect(animation_, SIGNAL(DataChanged()), this, SLOT(Rerender()));
connect(animation_, SIGNAL(DataChanged()), this, SLOT(AdjustSlider()));
connect(animation_, SIGNAL(NextStep()), SLOT(IncrementSlider()));
connect(animation_, SIGNAL(LastStep()), SLOT(UpdateSlider()));
}
void MainWindow::Rerender() { mainwidget_->Rerender(); }
void MainWindow::IncrementSlider()
{
int newval;
if (time_slider_->value() + 1 < time_slider_->maximum())
{
newval = time_slider_->value() + 1;
}
else
{
newval = time_slider_->maximum();
}
time_slider_->setValue(newval);
slider_line_edit_->setText(std::to_string(newval).c_str());
}
void MainWindow::UpdateSlider()
{
time_slider_->setValue(points_->GetEndTime());
slider_line_edit_->setText(std::to_string(time_slider_->value()).c_str());
}
void MainWindow::AdjustSlider()
{
time_slider_->setMinimum(points_->GetStartTime());
time_slider_->setMaximum(points_->GetEndTime());
}
void MainWindow::SliderValue(int time_step)
{
slider_line_edit_->setText(std::to_string(time_step).c_str());
time_slider_->setMinimum(points_->GetStartTime());
time_slider_->setMaximum(points_->GetEndTime());
}
void MainWindow::SliderValue()
{
time_slider_->setValue(slider_line_edit_->text().toInt());
}
void MainWindow::Realtime()
{
if (realtime_)
{
realtime_ = false;
rt_button_->setText("Realtime");
time_slider_->setMinimum(points_->GetStartTime());
time_slider_->setMaximum(points_->GetEndTime());
time_slider_->setEnabled(1);
}
else
{
realtime_ = true;
time_slider_->setValue(points_->GetEndTime());
rt_button_->setText("Replay");
time_slider_->setEnabled(0);
}
}
void MainWindow::PlayPause()
{
if (play_)
{
play_ = false;
play_button_->setText("▶");
SliderValue(slider_line_edit_->text().toInt());
}
else
{
play_ = true;
play_button_->setText("⏸");
}
}
} // namespace vtkexp
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include <vector>
#include "include/qvtk-lib/suppress_warnings.hpp"
SUPPRESS_WARNINGS_BEGIN
#include "qvtk-lib/point_data.hpp"
#include "vtkCellArray.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include "vtkPointData.h"
#pragma GCC diagnostic pop
SUPPRESS_WARNINGS_END
namespace vtkexp
{
PointData::PointData(int num_x, int num_y, int num_z)
: num_points_(num_x * num_y * num_z)
{
Initialize(num_x, num_y, num_z);
}
void PointData::Initialize(int x, int y, int z)
{
points_polydata_ = vtkSmartPointer<vtkPolyData>::New();
points_polydata_->SetPoints(CreatePoints(x, y, z));
pointcolors_ = vtkSmartPointer<vtkFloatArray>::New();
pointcolors_->SetName("colors");
pointcolors_->SetNumberOfTuples(num_points_);
std::vector<double> init(num_points_);
std::fill(init.begin(), init.end(), 0);
AttachColorsToPoints(init);
stream_ = new DataStream();
}
vtkSmartPointer<vtkPoints> PointData::CreatePoints(int num_x, int num_y,
int num_z)
{
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
for (int i = 0; i < num_x; ++i)
{
for (int j = 0; j < num_y; ++j)
{
for (int k = 0; k < num_z; ++k)
{
points->InsertNextPoint(i, j, k);
}
}
}
return points;
}
void PointData::ColorsModified()
{
points_polydata_->GetPointData()->GetScalars()->Modified();
}
void PointData::AttachColorsToPoints(const std::vector<double> &scalars)
{
if (!scalars.empty())
{
for (int i = 0; i < num_points_; ++i)
{
pointcolors_->SetValue(
i, static_cast<float>(scalars.at(static_cast<int>(i))));
}
points_polydata_->GetPointData()->SetScalars(pointcolors_);
}
}
void PointData::Update(int time_step)
{
AttachColorsToPoints(stream_->GetMultValuesAt(time_step));
ColorsModified();
}
vtkSmartPointer<vtkPolyData> PointData::GetPolyPoints()
{
return points_polydata_;
}
vtkSmartPointer<vtkFloatArray> PointData::GetColors() const
{
return pointcolors_;
}
int PointData::GetStartTime() const
{
if (!stream_->GetTimeSteps().empty())
{
return static_cast<int>(stream_->GetTimeSteps().front());
}
return 0;
}
int PointData::GetEndTime() const
{
if (!stream_->GetTimeSteps().empty())
{
return static_cast<int>(stream_->GetTimeSteps().back());
}
return 100;
}
} // namespace vtkexp
//------------------------------------------------------------------------------
// QVTK-Demo
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualisation Group.
//------------------------------------------------------------------------------
// License
//
// This framework is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In the future, we may decide to add a commercial license
// at our own discretion without further notice.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "qvtk-lib/visualize.hpp"
#include <string>
namespace vtkexp
{
Visualize::Visualize(PointData *points) { points_ = points; }
vtkSmartPointer<vtkRenderer> Visualize::GetRenderer() { return renderer_; }
void Visualize::Initialize(
vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderwindow,
vtkSmartPointer<vtkRenderWindowInteractor> interactor)
{
renderwindow_ = renderwindow;
interactor_ = interactor;
SetUpTransferFunction();
SetUpMapper();
SetUpScene();
SetUpRenderer();
SetUpAxes();
SetUpLegend();
}
void Visualize::SetUpLegend()
{
scalar_bar_widget_ = vtkSmartPointer<vtkScalarBarWidget>::New();
scalar_bar_widget_->SetInteractor(interactor_);
scalar_bar_widget_->SetEnabled(true);
scalar_bar_ = scalar_bar_widget_->GetScalarBarActor();
// scalar_bar_->SetTitle("Legend");
scalar_bar_->SetLookupTable(transfer_function_);
scalar_bar_->SetOrientationToVertical();
scalar_bar_->SetNumberOfLabels(0);
scalar_bar_->SetPosition2(0, 0);
scalar_bar_->SetBarRatio(0.6);
}
void Visualize::SetUpAxes()
{
axes_ = vtkSmartPointer<vtkAxesActor>::New();
axes_widget_ = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
axes_widget_->SetOutlineColor(0.9300, 0.5700, 0.1300);
axes_widget_->SetOrientationMarker(axes_);
axes_widget_->SetInteractor(interactor_);
axes_widget_->SetViewport(0.0, 0.0, 0.2, 0.2);
axes_widget_->SetEnabled(1);
axes_widget_->InteractiveOn();
renderer_->ResetCamera();
}
void Visualize::SetUpScene()
{
actor_ = vtkSmartPointer<vtkActor>::New();
actor_->SetMapper(mapper_);
}
void Visualize::SetUpRenderer()
{
renderer_ = vtkSmartPointer<vtkRenderer>::New();
renderwindow_->AddRenderer(renderer_);
renderer_->AddActor(actor_);
interactor_->GetInteractorStyle()->SetDefaultRenderer(renderer_);
renderer_->GradientBackgroundOn();
renderer_->SetBackground(0.3, 0.4, 0.5);
renderer_->SetBackground2(0.1, 0.2, 0.3);
}
void Visualize::SetUpTransferFunction()
{
transfer_function_ = vtkSmartPointer<vtkColorTransferFunction>::New();
transfer_function_->SetColorSpaceToDiverging();
transfer_function_->AddRGBPoint(-15, 0, 0, 1);
transfer_function_->AddRGBPoint(5, 1, 0, 0);
}
void Visualize::SetUpMapper()
{
SetUpShaders();
mapper_ = vtkSmartPointer<vtkPointGaussianMapper>::New();
mapper_->SetInputData(points_->GetPolyPoints());
mapper_->SetSplatShaderCode(point_shader_.c_str());
mapper_->SetLookupTable(transfer_function_);
mapper_->SetScaleFactor(0.35);
mapper_->UseLookupTableScalarRangeOn();
mapper_->EmissiveOff();
mapper_->Update();
}
void Visualize::SetUpShaders()
{
point_shader_ =
"//VTK::Color::Impl\n"
"ambientColor *= 1.0;\n"
"diffuseColor *= 1.0;\n"
"if (abs(offsetVCVSOutput.x) > 0.2 || abs(offsetVCVSOutput.y) > 0.2) "
"{\n"
" discard;\n"
"}\n";
sphere_shader_ =
"//VTK::Color::Impl\n"
"float dist = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
"if (dist > 0.8) {\n"
" discard;\n"
"} else {\n"
" float scale = (1.0 - dist);\n"
" ambientColor *= scale;\n"
" diffuseColor *= scale;\n"
"}\n";
}
void Visualize::SwitchMapper(int rendertype)
{
if (rendertype == 0)
{
mapper_->SetSplatShaderCode(point_shader_.c_str());
}
else if (rendertype == 1)
{
mapper_->SetSplatShaderCode(sphere_shader_.c_str());
}
}
} // namespace vtkexp
#-------------------------------------------------------------------------------
# nest-streaming-module
#
# Copyright (c) 2018 RWTH Aachen University, Germany,
# Virtual Reality & Immersive Visualization 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.
#-------------------------------------------------------------------------------
get_filename_component(NEST_DIR ${with-nest} DIRECTORY)
set(SCRIPT_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/run_sim.sh")
execute_process(
COMMAND ${NEST_CONFIG} --python-executable
RESULT_VARIABLE RES_VAR
OUTPUT_VARIABLE PYTHON_EXECUTABLE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run_sim.sh.in ${SCRIPT_FILENAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/brunel_example.py ${CMAKE_CURRENT_SOURCE_DIR}/nest_sim.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(brunel_simulation ALL chmod "+x" "run_sim.sh"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${SCRIPT_FILENAME} ${CMAKE_CURRENT_BINARY_DIR}/brunel_example.py ${CMAKE_CURRENT_SOURCE_DIR}/nest_sim.py)
"""
Definition of spatially extended Brunel network.
This module provides layer and projections declarations suitable for
use with the NEST Topology Module.
It defines a Brunel-style network with neurons placed on a regular grid.
Connectivity is probabilitstic from the entire network, i.e., connectivity
is not structured spatially.
"""
from copy import deepcopy
from math import sqrt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import nest
import nest.raster_plot
import nest.topology as tp
class Brunel3D:
def __init__(self):
self.layer_dict = {}
nest.Install("streamingmodule")
# nest.SetKernelStatus({'print_time': True})
class Parameters:
"""
Define model parameters.
"""
order = 9 # must be square
NE = 4 * order # number of excitatory neurons.
NI = 1 * order # number of inhibitory neurons
lengthE = int(sqrt(NE))
lengthI = int(sqrt(NI))
if not (lengthE**2 == NE and lengthI**2 == NI):
raise ValueError('Order must be a square number (order = n**2)')
# neuron_model = 'iaf_psc_alpha'
neuron_model = 'mat2_psc_exp'
g = 5.0 # ratio inhibitory weight/excitatory weight
eta = 2.0 # external rate relative to threshold rate
epsilon = 0.1 # connection probability
delay = 1.5 # synaptic delay in ms
tauMem = 20.0 # time constant of membrane potential in ms
theta = 20.0 # membrane threshold potential in mV
J = 0.1 # postsynaptic amplitude in mV
J_ex = J # amplitude of excitatory postsynaptic potential
J_in = -g * J_ex # amplitude of inhibitory postsynaptic potential
CE = int(epsilon * NE) # number of excitatory synapses per neuron
nu_th = theta / (J * CE * tauMem)
nu_ex = eta * nu_th
p_rate = 1.0 * nu_ex * CE
neuron_params = {"C_m": 1.0,
"tau_m": tauMem,
"t_ref": 2.0,
"E_L": 0.0,
# "V_reset": 0.0, # doesn't work with mat2_psc_exp
# "V_th": theta, # doesn't work with mat2_psc_exp
"V_m": 0.0
}
mm_params = {'record_from': ['V_m', 'V_th'],
'record_to': ['streaming']}
poisson_params = {"rate": p_rate}
def modified_copy(self, orig, diff):
"""
Returns a deep copy of dictionary with changes applied.
@param orig original dictionary, will be deep-copied
@param diff copy will be updated with this dict
"""
tmp = deepcopy(orig)
tmp.update(diff)
return tmp
def make_layer_specs(self):
"""
Returns lists of dictionaries with model, layer, and synapse model
specifications.
"""
P = self.Parameters
self.models = [(P.neuron_model, 'excitatory', P.neuron_params),
(P.neuron_model, 'inhibitory', P.neuron_params),
('poisson_generator', 'noise', P.poisson_params),
('multimeter', 'recordingNode', P.mm_params)]
self.syn_models = [('static_synapse', 'static_excitatory', {})]
dE = 1.0 / float(P.lengthE)
limE = (1.0 - dE) / 2.0
posE = np.linspace(-limE, limE, num=P.lengthE)
dI = 1.0 / float(P.lengthI)
limI = (1.0 - dI) / 2.0
posI = np.linspace(-limI, limI, num=P.lengthI)
self.layers = [('Excitatory', {'positions': [[x, y, 0.4]
for x in posE
for y in posE],
'edge_wrap': True,
'elements': 'excitatory'}),
('Inhibitory', {'positions': [[x, y, -0.4]
for x in posI
for y in posI],
'edge_wrap': True,
'elements': 'inhibitory'})]
self.layers.append(('PoissonGenerator',
{'positions': [[0.0, 0.0, 0.0]],
'elements': 'noise'}))
self.layers.append(('Multimeter',
{'positions': [[0.0, 0.0, 0.0]],
'elements': 'recordingNode'}))
self.layers.append(('SpikeDetector',
{'positions': [[0.0, 0.0, 0.0]],
'elements': 'spike_detector'}))
def make_connection_specs(self):
"""
Returns list of dictionaries specifying projections for Brunel network.
"""
P = self.Parameters
self.projections = [('Excitatory', 'Excitatory',
{'connection_type': 'convergent',
'synapse_model': 'static_synapse',
'kernel': P.epsilon,
'weights': P.J_ex,
'delays': P.delay}),
('Excitatory', 'Inhibitory',
{'connection_type': 'convergent',
'synapse_model': 'static_synapse',
'kernel': P.epsilon,
'weights': P.J_ex,
'delays': P.delay}),
('Inhibitory', 'Excitatory',
{'connection_type': 'convergent',
'synapse_model': 'static_synapse',
'kernel': P.epsilon,
'weights': P.J_in,
'delays': P.delay}),
('Inhibitory', 'Excitatory',
{'connection_type': 'convergent',
'synapse_model': 'static_synapse',
'kernel': P.epsilon,
'weights': P.J_in,
'delays': P.delay}),
('Multimeter', 'Excitatory',
{'connection_type': 'convergent'}),
('Excitatory', 'SpikeDetector',
{'connection_type': 'convergent'}),
('Inhibitory', 'SpikeDetector',
{'connection_type': 'convergent'}),
('PoissonGenerator', 'Excitatory',
{'connection_type': 'convergent'})]
def make_layers(self):
# First, we copy the models with custom specifications
# Neuron models
for model in self.models:
old_name, new_name, spec = model
nest.CopyModel(old_name, new_name, spec)
# Synapse models
for model in self.syn_models:
old_name, new_name, spec = model
nest.CopyModel(old_name, new_name, spec)
# Next we make the layers
for l in self.layers:
name = l[0]
specs = l[1]
self.layer_dict.update({name: tp.CreateLayer(specs)})
def make_connections(self):
# Connect layers
for proj in self.projections:
pre_layer = self.layer_dict[proj[0]]
post_layer = self.layer_dict[proj[1]]
conn_specs = proj[2]
tp.ConnectLayers(pre_layer, post_layer, conn_specs)
def simulate(self):
nest.Simulate(1000)
def plot_positions(self):
ex_pos = self.layers[0][1]['positions']
in_pos = self.layers[1][1]['positions']
fig = plt.figure()
ax = Axes3D(fig)
for c, m, positions in [('b', 'o', ex_pos), ('r', '^', in_pos)]:
ax.scatter([x for x, y, z in positions],
[y for x, y, z in positions],
[z for x, y, z in positions],
c=c, marker=m)
def get_results(self):
mm = (self.layer_dict['Multimeter'][0] + 1,)
sd = (self.layer_dict['SpikeDetector'][0] + 1,)
mm_status = nest.GetStatus(mm)[0]
sd_status = nest.GetStatus(sd)[0]
nest.raster_plot.from_device(sd, hist=True)
senders = mm_status['events']['senders']
times = mm_status['events']['times']
v_m = mm_status['events']['V_m']
v_th = mm_status['events']['V_th']
step = int(max(senders)/100 + 1) # Only plot results from some GIDs
mm_events = []
for i in range(1, max(senders) + 1, step):
if i in senders:
indices = np.argwhere(senders == i)
mm_events.append({'GID': i,
'times': [times[n] for n in indices],
'V_m': [v_m[n] for n in indices],
'V_th': [v_th[n] for n in indices]})
return {'multimeter': mm_events,
'spike_detector': nest.GetStatus(sd)[0]}
if __name__ == '__main__':
nest.ResetKernel()
print('Making specifications')
brunel = Brunel3D()
brunel.make_layer_specs()
brunel.make_connection_specs()
print('Making layers')
brunel.make_layers()
nest.topology.DumpLayerNodes([l[0] for l in brunel.layer_dict.values()][:2],
'brunel_nodes.txt')
print('Making connections')
brunel.make_connections()
brunel.simulate()
print('Getting results')
brunel.plot_positions()
results = brunel.get_results()
for value in ['V_m', 'V_th']:
plt.figure()
for n in results['multimeter'][::20]:
plt.plot(n['times'], n[value], label='{}'.format(n['GID']))
plt.legend()
plt.title(value)
plt.show()
#-------------------------------------------------------------------------------
# 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 nest
import numpy
from PyQt5.QtWidgets import QApplication, QPushButton
from PyQt5.QtCore import QTimer
import brunel_example
class Simulation:
def __init__(self):
self.SetupSim()
def SetupSim(self):
nest.ResetKernel()
print('Making specifications')
self.brunel = brunel_example.Brunel3D()
self.brunel.make_layer_specs()
self.brunel.make_connection_specs()
print('Making layers')
self.brunel.make_layers()
nest.topology.DumpLayerNodes([l[0] for l in self.brunel.layer_dict.values()][:2],
'brunel_nodes.txt')
print('Making connections')
self.brunel.make_connections()
def Simulate(self, steps):
nest.Simulate(steps)
class MainWindow:
def __init__(self, screen_resolution):
self.screen_resolution = screen_resolution
self.SetupWindow()
self.simulation = Simulation()
def SetupWindow(self):
self.simulate_button = QPushButton("nest.Simulate(1000)")
self.simulate_button.clicked.connect(self.SimulateButtonClicked)
def SimulateButtonClicked(self):
self.simulate_button.setEnabled(False)
QApplication.processEvents()
self.simulation.Simulate(1000)
QApplication.processEvents()
self.simulate_button.setEnabled(True)
def Show(self):
self.simulate_button.show()
button_geometry = self.simulate_button.geometry()
self.simulate_button.setGeometry(
self.screen_resolution.width() - button_geometry.width(),
self.screen_resolution.height() - button_geometry.height(),
button_geometry.width(),
button_geometry.height())
def main(argv):
app = QApplication(argv)
screen_resolution = app.desktop().screenGeometry()
w = MainWindow(screen_resolution)
w.Show()
return app.exec_()
if __name__ == "__main__":
main(sys.argv)
#!/bin/bash
source ${NEST_DIR}/nest_vars.sh
LD_LIBRARY_PATH=$NEST_MODULE_PATH:$LD_LIBRARY_PATH ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/nest_sim.py
\ No newline at end of file
/*
* recording_backend_stream_niv.cpp
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "recording_backend_nesci_contra.h"
#include "recording_device.h"
#include <iostream>
#include <memory>
#include <sstream>
streamingnest::RecordingBackendNesciContra::RecordingBackendNesciContra()
: num_buffered_steps_( 0 ), datum_(0, std::string{}, std::vector<double>{})
{
datum_.values.reserve(10);
}
void
streamingnest::RecordingBackendNesciContra::enroll( const nest::RecordingDevice& device )
{
enroll( device, std::vector< Name >() );
}
void
streamingnest::RecordingBackendNesciContra::enroll( const nest::RecordingDevice& device,
const std::vector< Name >& value_names )
{
if ( !is_enrolled_( device ) )
{
do_enroll_( device, value_names );
}
}
bool
streamingnest::RecordingBackendNesciContra::is_enrolled_( const nest::RecordingDevice& device )
{
return recorders_.find( device.get_gid() ) != recorders_.end();
}
void
streamingnest::RecordingBackendNesciContra::do_enroll_( const nest::RecordingDevice& device,
const std::vector< Name >& value_names )
{
std::unique_ptr< nesci::producer::Device > recorder{ create_recorder_(
device, value_names ) };
recorders_[ device.get_gid() ] = std::move( recorder );
}
std::unique_ptr< nesci::producer::Device >
streamingnest::RecordingBackendNesciContra::create_recorder_(
const nest::RecordingDevice& device,
const std::vector< Name >& value_names )
{
if ( device.get_type() == nest::RecordingDevice::MULTIMETER )
{
const std::vector< std::string > converted_value_names{ convert_value_names(
value_names ) };
return std::unique_ptr< nesci::producer::Device >(
new nesci::producer::NestMultimeter(
generate_device_identifier_( device ), converted_value_names ) );
}
// Spike detector is currently not supported
// else if ( device.get_type() == nest::RecordingDevice::SPIKE_DETECTOR )
// {
// return std::unique_ptr< nesci::producer::Device >(
// new nesci::producer::SpikeDetector(
// generate_device_identifier_( device ) ) );
// }
return std::unique_ptr< nesci::producer::Device >( nullptr );
}
std::vector< std::string >
streamingnest::RecordingBackendNesciContra::convert_value_names(
const std::vector< Name >& value_names ) const
{
std::vector< std::string > converted_value_names;
std::for_each( value_names.begin(),
value_names.end(),
[&converted_value_names]( const Name& name ) {
converted_value_names.push_back( name.toString() );
} );
return converted_value_names;
}
std::string
streamingnest::RecordingBackendNesciContra::generate_device_identifier_(
const nest::RecordingDevice& device ) const
{
if ( device.get_label().size() == 0 )
{
std::stringstream device_identifier;
device_identifier << device.get_name();
device_identifier << device.get_gid();
return device_identifier.str();
}
return device.get_label();
}
void
streamingnest::RecordingBackendNesciContra::initialize()
{
num_buffered_steps_ = 0;
}
void
streamingnest::RecordingBackendNesciContra::finalize()
{
}
void
streamingnest::RecordingBackendNesciContra::synchronize()
{
#pragma omp barrier
#pragma omp master
{
++num_buffered_steps_;
if ( num_buffered_steps_ == 10 )
{
send_and_reset_node_();
num_buffered_steps_ = 0;
}
}
}
void
streamingnest::RecordingBackendNesciContra::send_and_reset_node_()
{
for ( const auto& indexRecorder : recorders_ )
{
relay_.Send( indexRecorder.second->node() );
indexRecorder.second->node().reset();
}
}
void
streamingnest::RecordingBackendNesciContra::write( const nest::RecordingDevice& device,
const nest::Event& event )
{
if ( !is_enrolled_( device ) )
{
return;
}
// nesci does currently not support spike detectors
// const auto time = event.get_stamp().get_ms() - event.get_offset();
// auto& recorder = recorders_[ device.get_gid() ];
// recorder->Record(
// niv::producer::SpikeDetector::Datum( time, event.get_sender_gid() ) );
}
void
streamingnest::RecordingBackendNesciContra::write( const nest::RecordingDevice& device,
const nest::Event& event,
const std::vector< double >& values )
{
if ( !is_enrolled_( device ) )
{
return;
}
const auto time = event.get_stamp().get_ms() - event.get_offset();
auto& recorder = recorders_[ device.get_gid() ];
datum_.time = time;
datum_.neuron_id = std::to_string(event.get_sender_gid());
datum_.values = values;
recorder->Record( datum_ );
}
void
streamingnest::RecordingBackendNesciContra::set_status( const DictionaryDatum& d )
{
Parameters_ ptmp = P_; // temporary copy in case of errors
ptmp.set( *this, d ); // throws if BadProperty
// if we get here, temporaries contain consistent set of properties
P_ = ptmp;
}
void
streamingnest::RecordingBackendNesciContra::get_status( DictionaryDatum& d ) const
{
P_.get( *this, d );
}
streamingnest::RecordingBackendNesciContra::Parameters_::Parameters_()
: stream_interval_( 10 )
{
}
void
streamingnest::RecordingBackendNesciContra::Parameters_::get(
const RecordingBackendNesciContra&,
DictionaryDatum& d ) const
{
( *d )[ "stream_interval" ] = stream_interval_;
}
void
streamingnest::RecordingBackendNesciContra::Parameters_::set(
const RecordingBackendNesciContra&,
const DictionaryDatum& d )
{
if ( updateValue< long >( d, "stream_interval", stream_interval_ ) )
{
// do nothing for now
}
}
......@@ -25,47 +25,78 @@
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "conduit/conduit_node.hpp"
#include "nest_types.h"
#include "recording_backend.h"
#include "contra/relay.hpp"
#include "contra/shared_memory/shared_memory_transport.hpp"
#include "contra/boost-shmem/shared_memory_transport.hpp"
#include "nesci/producer/device.hpp"
#include "nesci/producer/nest_multimeter.hpp"
namespace streamingnest {
namespace streamingnest
{
class StreamingRecordingBackend : public nest::RecordingBackend {
class RecordingBackendNesciContra : public nest::RecordingBackend
{
public:
StreamingRecordingBackend();
~StreamingRecordingBackend() throw() {}
RecordingBackendNesciContra();
~RecordingBackendNesciContra() throw()
{
}
void enroll(const nest::RecordingDevice &, const std::vector<Name> &,
const std::vector<Name> &) override;
void enroll( const nest::RecordingDevice& device );
void enroll( const nest::RecordingDevice& device,
const std::vector< Name >& value_names );
void initialize();
void finalize();
void synchronize();
void write( const nest::RecordingDevice& device, const nest::Event& event );
void write( const nest::RecordingDevice& device,
const nest::Event& event,
const std::vector< double >& );
void initialize() override;
void set_status( const DictionaryDatum& );
void get_status( DictionaryDatum& ) const;
void finalize() override;
void synchronize() override;
private:
bool is_enrolled_( const nest::RecordingDevice& device );
void do_enroll_( const nest::RecordingDevice& device,
const std::vector< Name >& value_names );
std::string generate_device_identifier_(
const nest::RecordingDevice& device ) const;
std::unique_ptr< nesci::producer::Device > create_recorder_(
const nest::RecordingDevice& device,
const std::vector< Name >& value_names );
void send_and_reset_node_();
void write(const nest::RecordingDevice &, const nest::Event &,
const std::vector<double> &, const std::vector<long> &) override;
struct Parameters_
private:
std::mutex relay_mutex_;
contra::Relay<contra::SharedMemoryTransport> relay_;
{
long stream_interval_;
Parameters_();
std::mutex write_mutex_;
void get( const RecordingBackendNesciContra&, DictionaryDatum& ) const;
void set( const RecordingBackendNesciContra&, const DictionaryDatum& );
};
std::map<std::thread::id,
std::map<std::string, std::unique_ptr<nesci::producer::Device>>>
devices_;
std::mutex enroll_mutex_;
Parameters_ P_;
std::size_t num_buffered_steps_;
std::vector< std::string > convert_value_names(
const std::vector< Name >& value_names ) const;
contra::Relay< contra::SharedMemoryTransport > relay_;
std::map< nest::index, std::unique_ptr< nesci::producer::Device > > recorders_;
nesci::producer::NestMultimeter::Datum datum_;
};
} // namespace streamingnest
}
#endif // RECORDING_BACKEND_STREAM_NIV_H
File moved
/*
* recording_backend_stream_niv.cpp
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "streaming_recording_backend.h"
#include "recording_device.h"
#include <iostream>
#include <memory>
#include <sstream>
#include <thread>
namespace streamingnest {
StreamingRecordingBackend::StreamingRecordingBackend() {}
void StreamingRecordingBackend::initialize() {
// Called once
std::cout << "initialize()" << std::endl;
}
void StreamingRecordingBackend::enroll(
const nest::RecordingDevice &device,
const std::vector<Name> &double_value_names,
const std::vector<Name> &long_value_names) {
// Called per thread
std::lock_guard<std::mutex> lock_guard(enroll_mutex_);
std::vector<std::string> double_parameter_names;
double_parameter_names.reserve(double_value_names.size());
for (const auto &value_name : double_value_names) {
double_parameter_names.push_back(value_name.toString());
}
std::vector<std::string> long_parameter_names;
long_parameter_names.reserve(long_value_names.size());
for (const auto &value_name : long_value_names) {
long_parameter_names.push_back(value_name.toString());
}
if (device.get_type() == nest::RecordingDevice::Type::MULTIMETER) {
devices_[std::this_thread::get_id()][device.get_name()] =
std::make_unique<nesci::producer::NestMultimeter>(
device.get_name(), double_parameter_names, long_parameter_names);
}
std::cout << std::this_thread::get_id() << ' ';
std::cout << device.get_name() << ' ';
std::cout << "double_value_names: ";
for (const auto &name : double_value_names) {
std::cout << name << ' ';
}
std::cout << ", long_value_names: ";
for (const auto &name : long_value_names) {
std::cout << name << ' ';
}
std::cout << std::endl;
}
void StreamingRecordingBackend::write(const nest::RecordingDevice &device,
const nest::Event &event,
const std::vector<double> &double_values,
const std::vector<long> &long_values) {
// Called per thread
// std::lock_guard<std::mutex> lock_guard(write_mutex_);
// std::cout << std::this_thread::get_id() << ' ';
// std::cout << device.get_name() << ' ';
// std::cout << event.get_sender_gid() << ' ';
// std::cout << event.get_stamp() << ' ';
// for (const auto value : double_values) {
// std::cout << value << ' ';
// }
// std::cout << ' ';
// for (const auto value : long_values) {
// std::cout << value << ' ';
// }
// std::cout << std::endl;
const auto thread_devices = devices_.find(std::this_thread::get_id());
if (thread_devices == devices_.end()) {
// std::cout << "Error: no devices assigned to this thread!" << std::endl;
return;
}
const auto thread_device = thread_devices->second.find(device.get_name());
if (thread_device == thread_devices->second.end()) {
// std::cout << "Error: device not found in this thread (device = "
// << device.get_name() << ")" << std::endl;
return;
}
auto &nesci_device = thread_device->second;
if (device.get_type() == nest::RecordingDevice::Type::MULTIMETER) {
auto multimeter =
static_cast<nesci::producer::NestMultimeter *>(nesci_device.get());
multimeter->Record(event.get_stamp().get_ms(), event.get_sender_gid(),
double_values.data(), long_values.data());
}
}
void StreamingRecordingBackend::synchronize() {
// Called per thread
for (const auto &device : devices_.at(std::this_thread::get_id())) {
{
std::lock_guard<std::mutex> lock_guard(relay_mutex_);
relay_.Send(device.second->node(), false);
}
static_cast<nesci::producer::NestMultimeter *>(device.second.get())
->Clear();
}
}
void StreamingRecordingBackend::finalize() {
// Called once
std::cout << "finalize()" << std::endl;
}
} // namespace streamingnest
......@@ -26,7 +26,7 @@
#include "config.h"
// include headers with your own stuff
#include "streaming_recording_backend.h"
#include "recording_backend_nesci_contra.h"
// Includes from nestkernel:
#include "connection_manager_impl.h"
......@@ -35,10 +35,10 @@
#include "exceptions.h"
#include "genericmodel.h"
#include "genericmodel_impl.h"
#include "io_manager_impl.h"
#include "kernel_manager.h"
#include "model.h"
#include "model_manager_impl.h"
#include "io_manager_impl.h"
#include "nestmodule.h"
#include "target_identifier.h"
......@@ -75,8 +75,9 @@ streamingnest::StreamingModule streamingmodule_LTX_mod;
#endif
// -- DynModule functions ------------------------------------------------------
streamingnest::StreamingModule::StreamingModule() {
#if defined(LINKED_MODULE) && defined(HAVE_LIBLTDL)
streamingnest::StreamingModule::StreamingModule()
{
#ifdef LINKED_MODULE
// register this module at the dynamic loader
// this is needed to allow for linking in this module at compile time
// all registered modules will be initialized by the main app's dynamic loader
......@@ -84,24 +85,30 @@ streamingnest::StreamingModule::StreamingModule() {
#endif
}
streamingnest::StreamingModule::~StreamingModule() {}
streamingnest::StreamingModule::~StreamingModule()
{
}
const std::string streamingnest::StreamingModule::name(void) const {
const std::string
streamingnest::StreamingModule::name( void ) const
{
return std::string( "Streaming NEST Module" ); // Return name of the module
}
const std::string streamingnest::StreamingModule::commandstring(void) const {
const std::string
streamingnest::StreamingModule::commandstring( void ) const
{
// Instruct the interpreter to load streamingmodule-init.sli
return std::string( "(streamingmodule-init) run" );
}
//-------------------------------------------------------------------------------------
void streamingnest::StreamingModule::init(SLIInterpreter *i) {
void
streamingnest::StreamingModule::init( SLIInterpreter* i )
{
// Register recording backend.
nest::kernel()
.io_manager
.register_recording_backend<streamingnest::StreamingRecordingBackend>(
nest::kernel().io_manager.register_recording_backend< streamingnest::RecordingBackendNesciContra >(
"streaming" );
} // StreamingModule::init()
......@@ -28,13 +28,15 @@
#include "slimodule.h"
// Put your stuff into your own namespace.
namespace streamingnest {
namespace streamingnest
{
/**
* Class defining your model.
* @note For each model, you must define one such class, with a unique name.
*/
class StreamingModule : public SLIModule {
class StreamingModule : public SLIModule
{
public:
// Interface functions ------------------------------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment