Permalink
Browse files

Add support for XDF files (#11)

Add support for XDF files; this requires the external library libxdf.
  • Loading branch information...
Yida-Lin authored and cbrnr committed Feb 16, 2017
1 parent d380fa2 commit 69f81e59e8a4599bd01ec6dd47ba2b3bc0b6e9a5
Showing with 1,858 additions and 244 deletions.
  1. +0 −1 .gitignore
  2. +3 −1 sigviewer.pro
  3. +4 −0 src/application_context_impl.h
  4. +40 −18 src/base/fixed_data_block.cpp
  5. +32 −0 src/base/signal_channel.cpp
  6. +1 −0 src/base/signal_channel.h
  7. +19 −5 src/base/signal_event.cpp
  8. +3 −1 src/base/signal_event.h
  9. +1 −1 src/base/sigviewer_user_types.h
  10. +1 −0 src/editing_commands/delete_event_undo_command.cpp
  11. +13 −0 src/editing_commands/new_event_undo_command.cpp
  12. +5 −0 src/file_handling/channel_manager.cpp
  13. +4 −0 src/file_handling/channel_manager.h
  14. +9 −2 src/file_handling/event_manager.h
  15. +4 −0 src/file_handling/file_handler_factory.h
  16. +36 −0 src/file_handling_impl/biosig_basic_header.cpp
  17. +10 −0 src/file_handling_impl/biosig_basic_header.h
  18. +42 −7 src/file_handling_impl/biosig_reader.cpp
  19. +5 −0 src/file_handling_impl/biosig_reader.h
  20. +16 −0 src/file_handling_impl/channel_manager_impl.cpp
  21. +3 −0 src/file_handling_impl/channel_manager_impl.h
  22. +16 −3 src/file_handling_impl/event_manager_impl.cpp
  23. +9 −0 src/file_handling_impl/event_manager_impl.h
  24. +4 −2 src/file_handling_impl/file_handling_impl.pri
  25. +390 −0 src/file_handling_impl/xdf_reader.cpp
  26. +90 −0 src/file_handling_impl/xdf_reader.h
  27. +64 −3 src/gui_impl/commands/open_file_gui_command.cpp
  28. +4 −0 src/gui_impl/commands/open_file_gui_command.h
  29. +58 −28 src/gui_impl/commands/save_gui_command.cpp
  30. +192 −105 src/gui_impl/dialogs/basic_header_info_dialog.cpp
  31. +16 −6 src/gui_impl/dialogs/channel_dialog.ui
  32. +237 −20 src/gui_impl/dialogs/channel_selection_dialog.cpp
  33. +15 −1 src/gui_impl/dialogs/channel_selection_dialog.h
  34. +6 −3 src/gui_impl/dialogs/dialogs.pri
  35. +1 −0 src/gui_impl/dialogs/event_types_selection_dialog.cpp
  36. +106 −0 src/gui_impl/dialogs/resampling_dialog.cpp
  37. +42 −0 src/gui_impl/dialogs/resampling_dialog.h
  38. +97 −0 src/gui_impl/dialogs/resampling_dialog.ui
  39. +2 −2 src/gui_impl/event_table/event_table_widget.cpp
  40. +53 −19 src/gui_impl/gui_helper_functions.cpp
  41. +6 −0 src/gui_impl/main_window.cpp
  42. +56 −2 src/gui_impl/signal_browser/event_creation_widget.cpp
  43. +13 −0 src/gui_impl/signal_browser/event_creation_widget.h
  44. +30 −3 src/gui_impl/signal_browser/event_creation_widget.ui
  45. +29 −0 src/gui_impl/signal_browser/event_editing_widget.cpp
  46. +2 −0 src/gui_impl/signal_browser/event_editing_widget.h
  47. +1 −1 src/gui_impl/signal_browser/signal_browser_model_4.cpp
  48. +5 −1 src/gui_impl/signal_browser/signal_browser_view.cpp
  49. +61 −7 src/gui_impl/signal_browser/signal_graphics_item.cpp
  50. +1 −1 src/tests/event_manager_tests.cpp
  51. +1 −1 src/tests/event_table_widget_tests.cpp
View
@@ -10,4 +10,3 @@ bin/
.qmake.stash
Makefile
src/Makefile
View
@@ -46,7 +46,7 @@ INCLUDEPATH += \
LIBS += \
-L$$PWD/external/lib \
-lbiosig
-lbiosig -lxdf
RESOURCES = $$PWD/src/src.qrc
win32:RC_FILE = $$PWD/src/src.rc
@@ -77,3 +77,5 @@ SOURCES += \
$$PWD/src/application_context_impl.cpp \
$$PWD/src/file_context.cpp \
$$PWD/src/tab_context.cpp
QMAKE_CFLAGS += -std=c99
@@ -11,6 +11,8 @@
#include "gui/main_window_model.h"
#include "gui/application_context.h"
#include "file_context.h"
#include "file_handling_impl/xdf_reader.h"
#include "file_handling_impl/biosig_reader.h"
#include <QObject>
#include <QSharedPointer>
@@ -26,6 +28,8 @@ namespace sigviewer
class ApplicationContextImpl : public QObject, public ApplicationContext
{
Q_OBJECT
friend class XDFReader;
friend class BioSigReader;
public:
//-------------------------------------------------------------------------
static QSharedPointer<ApplicationContextImpl> getInstance (bool cleanup = false);
@@ -46,31 +46,53 @@ float32 const& FixedDataBlock::operator[] (size_t index) const
}
//-------------------------------------------------------------------------------------------------
//! Get the minimal value in a data block, excluding any NANs
float32 FixedDataBlock::getMin () const
{
QVector<float32>::const_iterator start = data_->begin() + start_index_;
QVector<float32>::const_iterator end = data_->begin() + start_index_ + size ();
QVector<float32>::const_iterator min_element = std::min_element (start,
end);
if (min_element != end)
return *min_element;
else
return 0;
float32 min = 0;
for (auto const elem : *data_)
{
if (!std::isnan(elem))
{
min = elem;
break;
}
}
for (auto const elem : *data_)
{
if (!std::isnan(elem))
{
if (elem < min)
min = elem;
}
}
return min;
}
//-------------------------------------------------------------------------------------------------
//! Get the maximal value in a data block, excluding any NANs
float32 FixedDataBlock::getMax () const
{
QVector<float32>::const_iterator start = data_->begin() + start_index_;
QVector<float32>::const_iterator end = data_->begin() + start_index_ + size ();
QVector<float32>::const_iterator max_element = std::max_element (start,
end);
if (max_element != end)
return *max_element;
else
return 0;
float32 max = 0;
for (auto const elem : *data_)
{
if (!std::isnan(elem))
{
max = elem;
break;
}
}
for (auto const elem : *data_)
{
if (!std::isnan(elem))
{
if (elem > max)
max = elem;
}
}
return max;
}
//-----------------------------------------------------------------------------
@@ -4,6 +4,7 @@
#include "signal_channel.h"
#include "file_handling_impl/xdf_reader.h"
namespace sigviewer
{
@@ -30,6 +31,37 @@ SignalChannel::SignalChannel(unsigned ch, const HDRTYPE* hdr) :
samplerate_ = hdr->SampleRate * hdr->CHANNEL[ch].SPR / hdr->SPR;
}
//constructor for XDF
SignalChannel::SignalChannel(unsigned ch, QString XDF) :
label_ (QString::fromStdString(XDFdata.labels[ch]).trimmed())
{
phys_y_dimension_label_ = QString::number(ch);
samplerate_ = XDFdata.majSR;
}
SignalChannel::SignalChannel(unsigned number, CHANNEL_TYPE C) :
/* obsolete */
label_ (QString(C.Label).trimmed()),
physical_maximum_(C.PhysMax),
digital_maximum_(C.DigMax),
physical_minimum_(C.PhysMin),
digital_minimum_(C.DigMin),
data_type_(C.GDFTYP),
lowpass_(C.LowPass),
highpass_(C.HighPass),
notch_(C.Notch)
{
#if (BIOSIG_VERSION < 10400)
char tmpstr[30];
PhysDim(C.PhysDimCode), tmpstr);
#else
const char *tmpstr = PhysDim3(C.PhysDimCode);
#endif
phys_y_dimension_label_ = QString(tmpstr);
samplerate_ = -1.0;
}
//-----------------------------------------------------------------------------
float64 SignalChannel::getSampleRate() const
{
@@ -23,6 +23,7 @@ class SignalChannel
public:
//-------------------------------------------------------------------------
SignalChannel(unsigned ch, const HDRTYPE* hdr);
SignalChannel(unsigned ch, QString XDF);
SignalChannel(unsigned number, CHANNEL_TYPE C); /* obsolete, deprecated */
//-------------------------------------------------------------------------
View
@@ -15,20 +15,23 @@ SignalEvent::SignalEvent()
sample_rate_ (1),
type_(0xFFFF),
channel_(UNDEFINED_CHANNEL),
duration_(UNDEFINED_DURATION)
duration_(UNDEFINED_DURATION),
stream_(-1)
{
// nothing
}
// constructor
SignalEvent::SignalEvent(size_t position, EventType type, float64 sample_rate, ChannelID channel,
SignalEvent::SignalEvent(size_t position, EventType type, float64 sample_rate, int streamNumber, ChannelID channel,
size_t duration, int32 id)
: id_(id),
position_(position),
sample_rate_ (sample_rate),
type_(type),
channel_(channel),
duration_(duration)
duration_(duration),
stream_(streamNumber)
{
// nothing
}
@@ -40,7 +43,8 @@ SignalEvent::SignalEvent(const SignalEvent& src, int32 id)
sample_rate_ (src.sample_rate_),
type_(src.type_),
channel_(src.channel_),
duration_(src.duration_)
duration_(src.duration_),
stream_(src.stream_)
{
// nothing
}
@@ -52,7 +56,8 @@ SignalEvent::SignalEvent(const SignalEvent& src)
sample_rate_ (src.sample_rate_),
type_(src.type_),
channel_(src.channel_),
duration_(src.duration_)
duration_(src.duration_),
stream_(src.stream_)
{
// nothing
}
@@ -65,6 +70,7 @@ SignalEvent& SignalEvent::operator= (const SignalEvent& src)
type_ = src.type_;
channel_ = src.channel_;
duration_ = src.duration_;
stream_ = src.stream_;
return *this;
}
@@ -124,6 +130,11 @@ float64 SignalEvent::getSampleRate () const
return sample_rate_;
}
int SignalEvent::getStream() const
{
return stream_;
}
//-----------------------------------------------------------------------------
void SignalEvent::setId (EventID id)
{
@@ -167,6 +178,9 @@ bool SignalEvent::equals (SignalEvent const& event) const
return false;
if (channel_ != event.channel_)
return false;
if (stream_ != event.stream_)
return false;
return true;
}
View
@@ -17,7 +17,7 @@ class SignalEvent
public:
SignalEvent();
SignalEvent(size_t position, EventType type,
float64 sample_rate,
float64 sample_rate, int streamNumber,
ChannelID channel = UNDEFINED_CHANNEL,
size_t duration = 0, EventID id = UNDEFINED_EVENT_ID);
@@ -34,6 +34,7 @@ class SignalEvent
float64 getDurationInSec() const;
float64 getEndInSec () const;
float64 getSampleRate () const;
int getStream() const;
void setId (EventID id);
void setPosition(size_t position);
@@ -52,6 +53,7 @@ class SignalEvent
EventType type_;
ChannelID channel_;
size_t duration_;
int stream_;
};
}
@@ -57,7 +57,7 @@ typedef int ChannelID;
const ChannelID UNDEFINED_CHANNEL = -1;
const EventID UNDEFINED_EVENT_ID = -1;
const EventType UNDEFINED_EVENT_TYPE = -1;
const int UNDEFINED_STREAM_ID= -1;
}
#endif // SIGVIEWER_USER_TYPES_H
@@ -32,6 +32,7 @@ void DeleteEventUndoCommand::undo ()
deleted_event_->getPosition (),
deleted_event_->getDuration (),
deleted_event_->getType (),
deleted_event_->getStream(),
deleted_event_->getId ());
}
@@ -4,6 +4,7 @@
#include "new_event_undo_command.h"
#include "file_handling_impl/xdf_reader.h"
namespace sigviewer
{
@@ -29,6 +30,17 @@ NewEventUndoCommand::~NewEventUndoCommand ()
void NewEventUndoCommand::undo ()
{
event_manager_->removeEvent (created_signal_event_->getId ());
//If XDF file, also pop back the event added to the XDFdata object earlier
if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive))
{
XDFdata.userCreatedEvents.pop_back();
if (XDFdata.userCreatedEvents.empty())
{
XDFdata.streams.pop_back();
XDFdata.userAddedStream = 0;
}
}
}
//-----------------------------------------------------------------------------
@@ -43,6 +55,7 @@ void NewEventUndoCommand::redo ()
raw_signal_event_->getPosition(),
raw_signal_event_->getDuration(),
raw_signal_event_->getType(),
raw_signal_event_->getStream(),
id);
}
@@ -13,6 +13,11 @@ namespace sigviewer
{
//-------------------------------------------------------------------------
QString ChannelManager::getChannelLabel(ChannelID id, int streamNumber) const
{
}
void ChannelManager::addDownsampledMinMaxVersion (ChannelID id, QSharedPointer<DataBlock const> min,
QSharedPointer<DataBlock const> max, unsigned factor)
{
@@ -36,6 +36,9 @@ class ChannelManager
//-------------------------------------------------------------------------
virtual QString getChannelLabel (ChannelID id) const = 0;
//-------------------------------------------------------------------------
virtual QString getChannelLabel (ChannelID id, int streamNumber) const; //streamNumber is for XDF only
//-------------------------------------------------------------------------
virtual QString getChannelYUnitString (ChannelID id) const = 0;
@@ -100,6 +103,7 @@ class ChannelManager
mutable bool min_max_initialized_;
mutable std::map<ChannelID, float64> max_values_;
mutable std::map<ChannelID, float64> min_values_;
mutable std::map<ChannelID, float64> offsets_;
QString x_axis_unit_label_;
@@ -50,8 +50,8 @@ class EventManager : public QObject
///
/// @return const pointer to the newly created event
virtual QSharedPointer<SignalEvent const> createEvent
(ChannelID channel_id, unsigned pos, unsigned length,
EventType type, EventID id = UNDEFINED_EVENT_ID) = 0;
(ChannelID channel_id, unsigned pos, unsigned length, EventType type,
int stream_id, EventID id = UNDEFINED_EVENT_ID) = 0;
//-------------------------------------------------------------------------
/// removes the event with the given id
@@ -104,6 +104,13 @@ class EventManager : public QObject
//-------------------------------------------------------------------------
virtual EventID getPreviousEventOfSameType (EventID id) const = 0;
//-------------------------------------------------------------------------
virtual QString getFileType () const = 0;
//-------------------------------------------------------------------------
virtual void setEventName (EventType event_type_id, QString const& name) = 0;
signals:
void eventChanged (EventID id);
void eventCreated (QSharedPointer<SignalEvent const> event);
@@ -87,6 +87,10 @@ FileHandlerType* FileHandlerFactory<FileHandlerType>::getHandler (QString const&
QPair<FileHandlerType*, QString> handler = handler_map_[file_ending]->createInstance (file_path);
if (handler.first)
return handler.first;
else if (handler.second.compare("Cancelled", Qt::CaseInsensitive) == 0)
return 0;
else if (handler.second.compare("non-exist", Qt::CaseInsensitive) == 0)
return 0;
else
{
handler = default_handler_->createInstance (file_path);
Oops, something went wrong.

0 comments on commit 69f81e5

Please sign in to comment.