Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #179

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

Dev #179

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 125 additions & 27 deletions plugins/data_recorder/data_recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "debug.hpp"
#include "fifo.hpp"
#include "rtos.hpp"
#include "userprefs/userprefs.hpp"

DataRecorder::Panel::Panel(QMainWindow* mwindow, Event::Manager* ev_manager)
: Widgets::Panel(
Expand All @@ -47,6 +48,7 @@ DataRecorder::Panel::Panel(QMainWindow* mwindow, Event::Manager* ev_manager)
, blockList(new QComboBox)
, channelList(new QComboBox)
, typeList(new QComboBox)
, timeTagType(new QComboBox())
, selectionBox(new QListWidget)
, recordStatus(new QLabel)
, downsampleSpin(new QSpinBox(this))
Expand Down Expand Up @@ -130,10 +132,20 @@ DataRecorder::Panel::Panel(QMainWindow* mwindow, Event::Manager* ev_manager)
auto* stampLayout = new QHBoxLayout;

// Add timestamp elements

stampLayout->addWidget(timeStampEdit);
addTag = new QPushButton(tr("Tag"));
stampLayout->addWidget(addTag);

auto* timeTagLabel = new QLabel(tr("Time Tag Type:"));
stampLayout->addWidget(timeTagLabel);
timeTagType->addItem("Index", TIME_TAG_TYPE::INDEX);
timeTagType->addItem("Time Stamp", TIME_TAG_TYPE::TIME);
timeTagType->addItem("No Tag", TIME_TAG_TYPE::NONE);
stampLayout->addWidget(timeTagType);
QObject::connect(timeTagType,
QOverload<int>::of(&QComboBox::activated),
this,
&DataRecorder::Panel::setTimeTagType);
QObject::connect(
addTag, &QPushButton::released, this, &DataRecorder::Panel::addNewTag);

Expand Down Expand Up @@ -333,12 +345,13 @@ void DataRecorder::Panel::changeDataFile()
fileDialog.setWindowTitle("Select Data File");

QSettings userprefs;
QSettings::setPath(QSettings::NativeFormat,
QSettings::SystemScope,
"/usr/local/share/rtxi/");
fileDialog.setDirectory(
userprefs.value("/dirs/data", getenv("HOME")).toString()); // NOLINT

userprefs.beginGroup("settings");
fileDialog.setDirectory(userprefs
.value(QString::fromStdString(std::string(
UserPrefs::HDF5_SAVE_LOCATION_KEY)))
.toString()); // NOLINT
userprefs.endGroup();
QStringList filterList;
filterList.push_back("HDF5 files (*.h5)");
filterList.push_back("All files (*.*)");
Expand All @@ -362,9 +375,6 @@ void DataRecorder::Panel::changeDataFile()
filename += ".h5";
}

// Write this directory to the user prefs as most recently used
userprefs.setValue("/dirs/data", fileDialog.directory().path());

auto* hplugin = dynamic_cast<DataRecorder::Plugin*>(this->getHostPlugin());
hplugin->change_file(filename.toStdString());
this->fileNameEdit->setText(QString(hplugin->getOpenFilename().c_str()));
Expand Down Expand Up @@ -470,6 +480,7 @@ void DataRecorder::Panel::startRecordClicked()
this->starting_record_time = QTime::currentTime();
this->trialNum->setNum(hplugin->getTrialCount());
this->trialLength->setText("Recording...");
this->timeTagType->setDisabled(true);
}
}

Expand All @@ -487,6 +498,7 @@ void DataRecorder::Panel::stopRecordClicked()
this->fileSize->setNum(
static_cast<double>(QFile(fileNameEdit->text()).size())
/ (1024.0 * 1024.0));
this->timeTagType->setDisabled(false);
}
}

Expand Down Expand Up @@ -527,6 +539,17 @@ void DataRecorder::Panel::syncEnableRecordingButtons(const QString& /*unused*/)
this->recordStatus->setText(ready ? "Ready" : "Not ready");
}

void DataRecorder::Panel::setTimeTagType()
{
this->time_type =
static_cast<TIME_TAG_TYPE>(timeTagType->currentData().toInt());
}

int DataRecorder::Panel::getTimeTagType() const
{
return static_cast<int>(this->time_type);
}

DataRecorder::Plugin::Plugin(Event::Manager* ev_manager)
: Widgets::Plugin(ev_manager, std::string(DataRecorder::MODULE_NAME))
, recording(false)
Expand Down Expand Up @@ -592,10 +615,12 @@ void DataRecorder::Plugin::startRecording()
this->append_new_trial();
const Event::Type event_type = Event::Type::RT_THREAD_UNPAUSE_EVENT;
std::vector<Event::Object> start_recording_event;
m_channel_data_counts.clear();
for (auto& rec_channel : this->m_recording_channels_list) {
start_recording_event.emplace_back(event_type);
start_recording_event.back().setParam(
"thread", static_cast<RT::Thread*>(rec_channel.component.get()));
m_channel_data_counts.push_back(0);
}
this->getEventManager()->postEvent(start_recording_event);
this->recording.store(true);
Expand Down Expand Up @@ -677,15 +702,32 @@ void DataRecorder::Plugin::open_trial_group()
H5P_DEFAULT,
H5P_DEFAULT,
H5P_DEFAULT);
for (auto& channel : this->m_recording_channels_list) {
compression_property = H5Pcreate(H5P_DATASET_CREATE);
H5Pset_deflate(compression_property, 7);
channel.hdf5_data_handle =
H5PTcreate(this->hdf5_handles.sync_group_handle,
channel.channel.name.c_str(),
this->hdf5_handles.channel_datatype_handle,
this->m_data_chunk_size,
compression_property);
const int data_type =
dynamic_cast<DataRecorder::Panel*>(this->getPanel())->getTimeTagType();
m_channel_data_counts.clear();
if (data_type == 2) {
for (auto& channel : this->m_recording_channels_list) {
compression_property = H5Pcreate(H5P_DATASET_CREATE);
H5Pset_deflate(compression_property, 7);
channel.hdf5_data_handle =
H5PTcreate(this->hdf5_handles.sync_group_handle,
channel.channel.name.c_str(),
H5T_IEEE_F64LE,
this->m_data_chunk_size,
compression_property);
}
} else {
for (auto& channel : this->m_recording_channels_list) {
m_channel_data_counts.push_back(0);
compression_property = H5Pcreate(H5P_DATASET_CREATE);
H5Pset_deflate(compression_property, 7);
channel.hdf5_data_handle =
H5PTcreate(this->hdf5_handles.sync_group_handle,
channel.channel.name.c_str(),
this->hdf5_handles.channel_datatype_handle,
this->m_data_chunk_size,
compression_property);
}
}
}

Expand Down Expand Up @@ -887,19 +929,64 @@ void DataRecorder::Plugin::process_data_worker()
return;
}
std::vector<DataRecorder::data_token_t> data_buffer(this->m_data_chunk_size);
std::vector<double> data_buffer_doubles;
data_buffer_doubles.reserve(this->m_data_chunk_size);
const size_t packet_byte_size = sizeof(DataRecorder::data_token_t);
int64_t read_bytes = 0;
size_t packet_count = 0;
size_t channel_id = 0;
const int time_type =
dynamic_cast<DataRecorder::Panel*>(this->getPanel())->getTimeTagType();
const std::shared_lock<std::shared_mutex> lk(this->m_channels_list_mut);
for (auto& channel : this->m_recording_channels_list) {
while (read_bytes = channel.channel.data_source->read(
data_buffer.data(), packet_byte_size * data_buffer.size()),
read_bytes > 0)
{
packet_count = static_cast<size_t>(read_bytes) / packet_byte_size;
DataRecorder::Plugin::save_data(
channel.hdf5_data_handle, data_buffer, packet_count);
}
switch (time_type) {
case 0:

for (auto& channel : this->m_recording_channels_list) {
while (read_bytes = channel.channel.data_source->read(
data_buffer.data(), packet_byte_size * data_buffer.size()),
read_bytes > 0)
{
packet_count = static_cast<size_t>(read_bytes) / packet_byte_size;
DataRecorder::Plugin::save_data(
channel.hdf5_data_handle, data_buffer, packet_count);
}
}
break;
case 1:

for (auto& channel : this->m_recording_channels_list) {
while (read_bytes = channel.channel.data_source->read(
data_buffer.data(), packet_byte_size * data_buffer.size()),
read_bytes > 0)
{
for (auto& token : data_buffer) {
token.time = m_channel_data_counts[channel_id++]++;
}
packet_count = static_cast<size_t>(read_bytes) / packet_byte_size;
DataRecorder::Plugin::save_data(
channel.hdf5_data_handle, data_buffer, packet_count);
}
}
break;
case 2:

for (auto& channel : this->m_recording_channels_list) {
while (read_bytes = channel.channel.data_source->read(
data_buffer.data(), packet_byte_size * data_buffer.size()),
read_bytes > 0)
{
for (auto& token : data_buffer) {
data_buffer_doubles.push_back(token.value);
}
packet_count = static_cast<size_t>(read_bytes) / packet_byte_size;
DataRecorder::Plugin::save_data(
channel.hdf5_data_handle, data_buffer_doubles, packet_count);
}
}
break;
default:
ERROR_MSG("DataRecorder::Plugin::process_data_worker : Bad time tagging type detected. Unable to save data to hdf5 file");
break;
}
}

Expand All @@ -915,6 +1002,17 @@ void DataRecorder::Plugin::save_data(
}
}

void DataRecorder::Plugin::save_data(hid_t data_id,
const std::vector<double>& data,
size_t packet_count)
{
const herr_t err =
H5PTappend(data_id, static_cast<hsize_t>(packet_count), data.data());
if (err < 0) {
ERROR_MSG("Unable to write data into hdf5 file!");
}
}

DataRecorder::Component::Component(Widgets::Plugin* hplugin,
const std::string& probe_name)
: Widgets::Component(hplugin,
Expand Down
18 changes: 17 additions & 1 deletion plugins/data_recorder/data_recorder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@

#include <hdf5_hl.h>

#include "fifo.hpp"
#include "io.hpp"
#include "widgets.hpp"
#include "fifo.hpp"

class QComboBox;
class QListWidget;
Expand Down Expand Up @@ -93,6 +93,13 @@ class Panel : public Widgets::Panel
{
Q_OBJECT

enum TIME_TAG_TYPE
{
INDEX = 0,
TIME,
NONE
};

public:
Panel(const Panel&) = delete;
Panel(Panel&&) = delete;
Expand All @@ -101,6 +108,8 @@ class Panel : public Widgets::Panel
Panel(QMainWindow* mwindow, Event::Manager* ev_manager);
~Panel() override = default;

int getTimeTagType() const;

signals:
void updateBlockInfo();
void record_signal(bool record);
Expand All @@ -121,11 +130,13 @@ private slots:
void addNewTag();
void processData();
void syncEnableRecordingButtons(const QString& /*unused*/);
void setTimeTagType();

private:
size_t m_buffer_size = DEFAULT_BUFFER_SIZE;
size_t downsample_rate {1};
std::vector<std::string> dataTags;
int time_type=TIME_TAG_TYPE::INDEX;

QGroupBox* channelGroup = nullptr;
QGroupBox* stampGroup = nullptr;
Expand All @@ -137,6 +148,7 @@ private slots:
QComboBox* blockList = nullptr;
QComboBox* channelList = nullptr;
QComboBox* typeList = nullptr;
QComboBox* timeTagType = nullptr;
QListWidget* selectionBox = nullptr;
QLabel* recordStatus = nullptr;
QPushButton* addRecorderButton = nullptr;
Expand Down Expand Up @@ -200,6 +212,9 @@ class Plugin : public Widgets::Plugin
static void save_data(hid_t data_id,
const std::vector<data_token_t>& data,
size_t packet_count);
static void save_data(hid_t data_id,
const std::vector<double>& data,
size_t packet_count);
hsize_t m_data_chunk_size = static_cast<hsize_t>(1000);
int m_compression_factor = 5;
struct hdf5_handles
Expand Down Expand Up @@ -231,6 +246,7 @@ class Plugin : public Widgets::Plugin
int trial_count = 0;
std::string hdf5_filename;
std::vector<recorder_t> m_recording_channels_list;
std::vector<int64_t> m_channel_data_counts;
std::shared_mutex m_channels_list_mut;
std::atomic<bool> open_file = false;
}; // class Plugin
Expand Down
9 changes: 8 additions & 1 deletion plugins/performance_measurement/performance_measurement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ PerformanceMeasurement::Panel::Panel(const std::string& mod_name,
PerformanceMeasurement::Component::Component(Widgets::Plugin* hplugin)
: Widgets::Component(hplugin,
std::string(MODULE_NAME),
std::vector<IO::channel_t>(),
PerformanceMeasurement::get_default_channels(),
PerformanceMeasurement::get_default_vars())
{
if (RT::OS::getFifo(this->fifo,
Expand Down Expand Up @@ -137,6 +137,13 @@ void PerformanceMeasurement::Component::execute()

switch (this->getState()) {
case RT::State::EXEC:
writeoutput(0, stats.duration);
writeoutput(1, stats.timestep);
writeoutput(2, stats.latency);
writeoutput(3, stats.max_timestep);
writeoutput(4, stats.max_duration);
writeoutput(5, stats.max_latency);
writeoutput(6, stats.jitter);
this->fifo->writeRT(&this->stats,
sizeof(PerformanceMeasurement::performance_stats_t));
break;
Expand Down
Loading
Loading