diff --git a/applications/mne_analyze/mne_analyze/main.cpp b/applications/mne_analyze/mne_analyze/main.cpp index d2a5a6221e6..9d8b5825102 100644 --- a/applications/mne_analyze/mne_analyze/main.cpp +++ b/applications/mne_analyze/mne_analyze/main.cpp @@ -78,6 +78,7 @@ Q_IMPORT_PLUGIN(SourceLocalization) Q_IMPORT_PLUGIN(ControlManager) Q_IMPORT_PLUGIN(ChannelSelection) Q_IMPORT_PLUGIN(CoRegistration) +Q_IMPORT_PLUGIN(TimeFrequency) #ifndef WASMBUILD Q_IMPORT_PLUGIN(View3D) #endif @@ -109,5 +110,7 @@ int main(int argc, char *argv[]) QScopedPointer pAnalyzeCore (new AnalyzeCore); pAnalyzeCore->showMainWindow(); - return app.exec(); + int main_return_value(app.exec()); + + return main_return_value; } diff --git a/applications/mne_analyze/mne_analyze/mne_analyze.pro b/applications/mne_analyze/mne_analyze/mne_analyze.pro index bd6fe66e6d3..b010b65ea1b 100644 --- a/applications/mne_analyze/mne_analyze/mne_analyze.pro +++ b/applications/mne_analyze/mne_analyze/mne_analyze.pro @@ -36,7 +36,7 @@ #============================================================================================================== include(../../../mne-cpp.pri) - +DEFINES += TRACE TEMPLATE = app QT += gui widgets network opengl svg concurrent charts @@ -88,6 +88,7 @@ contains(MNECPP_CONFIG, static) { -lcontrolmanager \ -lchannelselection \ -lcoregistration \ + -ltimefrequency \ # Add Qt3D/Disp3D based plugins only if not building against WASM, which does not support Qt3D !contains(DEFINES, WASMBUILD) { diff --git a/applications/mne_analyze/plugins/dataloader/dataloader.h b/applications/mne_analyze/plugins/dataloader/dataloader.h index 7c10578a8a9..9ff8f91a320 100644 --- a/applications/mne_analyze/plugins/dataloader/dataloader.h +++ b/applications/mne_analyze/plugins/dataloader/dataloader.h @@ -75,12 +75,6 @@ namespace DISPLIB { namespace DATALOADERPLUGIN { -//============================================================================================================= -// DATALOADERPLUGIN FORWARD DECLARATIONS -//============================================================================================================= - -class DataLoaderControl; - //============================================================================================================= /** * DataLoader Plugin diff --git a/applications/mne_analyze/plugins/plugins.pro b/applications/mne_analyze/plugins/plugins.pro index 0d151f6d920..df049c41f53 100644 --- a/applications/mne_analyze/plugins/plugins.pro +++ b/applications/mne_analyze/plugins/plugins.pro @@ -49,6 +49,7 @@ SUBDIRS += \ controlmanager \ coregistration \ dipolefit \ + timefrequency \ # sampleplugin \ # Exclude plugins which rely on the Qt3D module. Note: The Qt3D module is not yet supported by Wasm diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp new file mode 100644 index 00000000000..6b017b4e60c --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -0,0 +1,306 @@ +//============================================================================================================= +/** + * @file timefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequency class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace TIMEFREQUENCYPLUGIN; +using namespace ANSHAREDLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequency::TimeFrequency() +: m_sSettingsPath("MNEANALYZE/TimeFrequency") +, m_pAvgModel(Q_NULLPTR) +{ + m_pEvokedModel = QSharedPointer(new DISPLIB::EvokedSetModel()); + loadSettings(); +} + +//============================================================================================================= + +TimeFrequency::~TimeFrequency() +{ + +} + +//============================================================================================================= + +QSharedPointer TimeFrequency::clone() const +{ + QSharedPointer pTimeFrequencyClone(new TimeFrequency); + return pTimeFrequencyClone; +} + +//============================================================================================================= + +void TimeFrequency::init() +{ + m_pCommu = new Communicator(this); + + m_pTFModel = QSharedPointer(new DISPLIB::TimeFrequencyModel()); +} + +//============================================================================================================= + +void TimeFrequency::unload() +{ + +} + +//============================================================================================================= + +QString TimeFrequency::getName() const +{ + return "Time-Frequency"; +} + +//============================================================================================================= + +QMenu *TimeFrequency::getMenu() +{ + return Q_NULLPTR; +} + +//============================================================================================================= + +QDockWidget *TimeFrequency::getControl() +{ + QDockWidget* pDock = new QDockWidget(getName()); + +// QWidget* pWidget = new QWidget(pDock); +// QVBoxLayout* pLayout = new QVBoxLayout(pDock); +// QPushButton* pButton = new QPushButton("Press me.", pWidget); + +// pLayout->addWidget(pButton); +// pWidget->setLayout(pLayout); +// pDock->setWidget(pWidget); + +// connect(pButton, &QPushButton::pressed, +// this, &TimeFrequency::computeTimeFreqency); + + DISPLIB::TimeFrequencySettingsView* pSettings = new DISPLIB::TimeFrequencySettingsView(); + + connect(pSettings, &DISPLIB::TimeFrequencySettingsView::computePushed, + this, &TimeFrequency::computeTimeFreqency, Qt::UniqueConnection); + + connect(pSettings, &DISPLIB::TimeFrequencySettingsView::minFreqChanged, + m_pTFModel.data(), &DISPLIB::TimeFrequencyModel::setMinFreq, Qt::UniqueConnection); + + connect(pSettings, &DISPLIB::TimeFrequencySettingsView::maxFreqChanged, + m_pTFModel.data(), &DISPLIB::TimeFrequencyModel::setMaxFreq, Qt::UniqueConnection); + + + + pDock->setWidget(pSettings); + + + return pDock; +} + +//============================================================================================================= + +QWidget *TimeFrequency::getView() +{ + QWidget* pTimeFreqViewWidget = new QWidget(); + QTabWidget* pTabView = new QTabWidget(pTimeFreqViewWidget); + QVBoxLayout* pViewLayout = new QVBoxLayout(); + + m_pTimeFreqView = new DISPLIB::TimeFrequencyView(); + m_pTimeFreqLayoutView = new DISPLIB::TimeFrequencyLayoutView(); + + m_pTimeFreqView->setTimeFrequencyModel(m_pTFModel); + m_pTimeFreqLayoutView->setTimeFrequencyModel(m_pTFModel); + + pTabView->addTab(m_pTimeFreqView, "Average View"); + pTabView->addTab(m_pTimeFreqLayoutView, "Layout View"); + + pViewLayout->addWidget(pTabView); + pTimeFreqViewWidget->setLayout(pViewLayout); + + return pTimeFreqViewWidget; +} + +//============================================================================================================= + +void TimeFrequency::handleEvent(QSharedPointer e) +{ + switch (e->getType()) { + case EVENT_TYPE::SELECTED_MODEL_CHANGED:{ + onModelChanged(e->getData().value >()); + break; + } + case EVENT_TYPE::CHANNEL_SELECTION_ITEMS:{ + setChannelSelection(e->getData()); + } + default: + qWarning() << "[Averaging::handleEvent] Received an Event that is not handled by switch cases."; + } +} + +//============================================================================================================= + +QVector TimeFrequency::getEventSubscriptions(void) const +{ + QVector temp; + temp.push_back(SELECTED_MODEL_CHANGED); + temp.push_back(CHANNEL_SELECTION_ITEMS); + + return temp; +} + +//============================================================================================================= + +void TimeFrequency::saveSettings() +{ + QSettings settings("MNECPP"); + settings.beginGroup(m_sSettingsPath); +} + +//============================================================================================================= + +void TimeFrequency::loadSettings() +{ + QSettings settings("MNECPP"); + settings.beginGroup(m_sSettingsPath); +} + +//============================================================================================================= + +void TimeFrequency::onModelChanged(QSharedPointer pNewModel) +{ + if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_AVERAGING_MODEL) { + m_pAvgModel = qSharedPointerCast(pNewModel); + m_pEvokedModel->setEvokedSet(m_pAvgModel->data(QModelIndex()).value>()); + m_pTimeFreqView->setEvokedSetModel(m_pEvokedModel); + } + if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_FIFFRAW_MODEL) { + m_pFiffRawModel = qSharedPointerCast(pNewModel); + } +} + +//============================================================================================================= + +void TimeFrequency::setChannelSelection(const QVariant &data) +{ + if(data.value()->m_sViewsToApply.contains("layoutview")){ + if(m_pTimeFreqLayoutView){ + m_pTimeFreqLayoutView->channelSelectionChanged(data); + } + } + if(data.value()->m_sViewsToApply.contains("butterflyview")){ +// if(data.value()->m_bShowAll){ +// emit showAllChannels(); +// } else { +// emit showSelectedChannels(data.value()->m_iChannelNumber); +// } + + } + + if(m_pTFModel){ + if(data.value()->m_sViewsToApply.contains("butterflyview")){ + m_pTFModel->setChannelSelection(data.value()->m_iChannelNumber); + } + } +} + +//============================================================================================================= + +void TimeFrequency::computeTimeFreqency() +{ + qDebug() << "[TimeFrequency::computeTimeFreqency]"; + if (!m_pFiffRawModel){ + return; + } + + +// DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot->show(); + +// auto spectr2 = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + +// DISPLIB::TFplot* tfplot2 = new DISPLIB::TFplot(spectr2.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot2->show(); + +// DISPLIB::TFplot* tfplot3 = new DISPLIB::TFplot(spectr2.at(20), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot3->show(); + +// DISPLIB::TFplot* tfplot4 = new DISPLIB::TFplot(spectr2.at(80), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot4->show(); + + + auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeEpochListTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), + m_pFiffRawModel->getEventModel()->getEventMatrix(9999), + -0.100f, + 0.300f); + + auto averagedData = RTPROCESSINGLIB::TimeFrequencyData::averageEpochListTimeFrequency(tfData); + + m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); + + m_pTFModel->setSpectr(averagedData); + +// auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + +// m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); +// m_pTFModel->setSpectr(spectr); +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h new file mode 100644 index 00000000000..bf35ecd7deb --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -0,0 +1,176 @@ +//============================================================================================================= +/** + * @file timefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the TimeFrequency class. + * + */ + +#ifndef TIMEFREQUENCY_AN_PLUGIN_H +#define TIMEFREQUENCY_AN_PLUGIN_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency_global.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace ANSHAREDLIB { + class Communicator; + class AbstractModel; + class AveragingDataModel; +} + +namespace DISPLIB { + class ProgressView; + class TimeFrequencyView; + class TimeFrequencyLayoutView; + class TimeFrequencyModel; + class EvokedSetModel; +} + +//============================================================================================================= +// DEFINE NAMESPACE TIMEFREQUENCYPLUGIN +//============================================================================================================= + +namespace TIMEFREQUENCYPLUGIN +{ + +//============================================================================================================= +// TIMEFREQUENCYPLUGIN FORWARD DECLARATIONS +//============================================================================================================= + +class TimeFrequencyControl; + +//============================================================================================================= +/** + * TimeFrequency Plugin + * + * @brief The TimeFrequency class provides input and output capabilities for the fiff file format. + */ +class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "ansharedlib/1.0" FILE "timefrequency.json") //New Qt5 Plugin system replaces Q_EXPORT_PLUGIN2 macro + // Use the Q_INTERFACES() macro to tell Qt's meta-object system about the interfaces + Q_INTERFACES(ANSHAREDLIB::AbstractPlugin) +public: + //========================================================================================================= + /** + * Constructs a TimeFrequency. + */ + TimeFrequency(); + + //========================================================================================================= + /** + * Destroys the TimeFrequency. + */ + ~TimeFrequency() override; + + // AbstractPlugin functions + virtual QSharedPointer clone() const override; + virtual void init() override; + virtual void unload() override; + virtual QString getName() const override; + + virtual QMenu* getMenu() override; + virtual QDockWidget* getControl() override; + virtual QWidget* getView() override; + + virtual void handleEvent(QSharedPointer e) override; + virtual QVector getEventSubscriptions() const override; + +private: + //========================================================================================================= + /** + * Loads settings from the system. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Save the settings in the register/file/mechanism for lon-term storage. + */ + void saveSettings(); + + //========================================================================================================= + void onModelChanged(QSharedPointer pNewModel); + + //========================================================================================================= + void computeTimeFreqency(); + + //========================================================================================================= + /** + * Sets channel selection for views based on QVariant with a SelectionItem object + * + * @param [in] data QVariant with a SelectionItem object with channel selection information + */ + void setChannelSelection(const QVariant &data); + + QPointer m_pCommu; /**< Used for sending events */ + QString m_sSettingsPath; /**< Variable that stores the key where to store settings for this plugin.*/ + + QPointer m_pTimeFreqView; + QPointer m_pTimeFreqLayoutView; + + QSharedPointer m_pEvokedModel; /**< Pointer to model used to display averaging data from m_pFiffEvokedSet and m_pFiffEvoked */ + QSharedPointer m_pAvgModel; /**< Pointer to currently loaded FiffRawView Model */ + QSharedPointer m_pFiffRawModel; /**< Pointer to currently loaded FiffRawView Model. */ + + + QSharedPointer m_pTFModel; + + bool m_bComputeWithAverage; + +}; + +//============================================================================================================= +// INLINE DEFINITIONS +//============================================================================================================= + +} // NAMESPACE + +#endif // TIMEFREQUENCY_H diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.json b/applications/mne_analyze/plugins/timefrequency/timefrequency.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro new file mode 100644 index 00000000000..4759ef82002 --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro @@ -0,0 +1,125 @@ +#============================================================================================================== +# +# @file timefrequency.pro +# @author Gabriel Motta +# @since 0.1.9 +# @date April, 2021 +# +# @section LICENSE +# +# Copyright (C) 2021, Gabriel Motta. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that +# the following conditions are met: +# * Redistributions of source code must retain the above copyright notice, this list of conditions and the +# following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or other materials provided with the distribution. +# * Neither the name of MNE-CPP authors nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# +# @brief This project file generates the makefile for the timefrequency plugin. +# +#============================================================================================================== + +include(../../../../mne-cpp.pri) + +TEMPLATE = lib +DEFINES += TRACE +QT += gui widgets + +CONFIG += skip_target_version_ext plugin + +DEFINES += TIMEFREQUENCY_PLUGIN + +DESTDIR = $${MNE_BINARY_DIR}/mne_analyze_plugins + +contains(MNECPP_CONFIG, wasm) { + DEFINES += WASMBUILD +} + +TARGET = timefrequency +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lanSharedd \ + -lmnecppDispd \ + -lmnecppEventsd \ + -lmnecppConnectivityd \ + -lmnecppRtProcessingd \ + -lmnecppInversed \ + -lmnecppFwdd \ + -lmnecppMned \ + -lmnecppFiffd \ + -lmnecppFsd \ + -lmnecppUtilsd \ +} else { + LIBS += -lanShared \ + -lmnecppDisp \ + -lmnecppEvents \ + -lmnecppConnectivity \ + -lmnecppRtProcessing \ + -lmnecppInverse \ + -lmnecppFwd \ + -lmnecppMne \ + -lmnecppFiff \ + -lmnecppFs \ + -lmnecppUtils \ +} + +SOURCES += \ + timefrequency.cpp \ + +HEADERS += \ + timefrequency_global.h \ + timefrequency.h \ + +OTHER_FILES += timefrequency.json + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} +INCLUDEPATH += $${MNE_ANALYZE_INCLUDE_DIR} + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency_global.h b/applications/mne_analyze/plugins/timefrequency/timefrequency_global.h new file mode 100644 index 00000000000..87ff35cdb55 --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency_global.h @@ -0,0 +1,54 @@ +//============================================================================================================= +/** + * @file timefrequency_global.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the FiffIO library export/import macros. + * + */ + +#ifndef TIMEFREQUENCY_GLOBAL_H +#define TIMEFREQUENCY_GLOBAL_H + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// PREPROCESSOR DEFINES +//============================================================================================================= + +#if defined(TIMEFREQUENCY_PLUGIN) +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_EXPORT /**< Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library. */ +#else +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_IMPORT /**< Q_DECL_IMPORT must be added to the declarations of symbols used when compiling a client that uses the shared library. */ +#endif + +#endif // TIMEFREQUENCY_GLOBAL_H diff --git a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp new file mode 100644 index 00000000000..e8e204a9e07 --- /dev/null +++ b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp @@ -0,0 +1,49 @@ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "realtimetimefrequencywidget.h" + +#include + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace SCDISPLIB; +using namespace SCMEASLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +RealTimeTimeFrequencyWidget::RealTimeTimeFrequencyWidget(QSharedPointer &pTime, + QWidget* parent) +: MeasurementWidget(parent) +{ + m_pRTTFLayout = new QVBoxLayout(this); + + m_pTFView = new DISPLIB::TimeFrequencyView(); + + m_pRTTFLayout->addWidget(m_pTFView); + + this->setLayout(m_pRTTFLayout); +} + +//============================================================================================================= + +void RealTimeTimeFrequencyWidget::update(SCMEASLIB::Measurement::SPtr pMeasurement) +{ + if(!m_pRTTF) { + m_pRTTF = qSharedPointerDynamicCast(pMeasurement); + } +} diff --git a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h new file mode 100644 index 00000000000..5be59048d68 --- /dev/null +++ b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h @@ -0,0 +1,82 @@ +#ifndef REALTIMETIMEFREQUENCYWIDGET_H +#define REALTIMETIMEFREQUENCYWIDGET_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "scdisp_global.h" +#include "measurementwidget.h" + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class QTime; + +namespace SCMEASLIB { + class RealTimeTimeFrequency; +} + +namespace DISPLIB { + class TimeFrequencyView; + class TimeFrequencySettingsView; +} + +class QVBoxLayout; + +//============================================================================================================= +// DEFINE NAMESPACE SCDISPLIB +//============================================================================================================= + +namespace SCDISPLIB +{ + +class SCDISPSHARED_EXPORT RealTimeTimeFrequencyWidget : public MeasurementWidget +{ + Q_OBJECT +public: + RealTimeTimeFrequencyWidget(QSharedPointer &pTime, + QWidget* parent = 0); + + //========================================================================================================= + /** + * Initialise the MeasurementWidget. + */ + virtual void init(){} + + //========================================================================================================= + /** + * Is called when new data are available. + * + * @param [in] pMeasurement pointer to measurement -> not used because its direct attached to the measurement. + */ + virtual void update(SCMEASLIB::Measurement::SPtr pMeasurement); + +private: + + QSharedPointer m_pRTTF; + + QPointer m_pTFView; + + QPointer m_pRTTFLayout; /**< RTE Widget layout */ + + + +}; +}//namespace +#endif // REALTIMETIMEFREQUENCYWIDGET_H diff --git a/applications/mne_scan/libs/scDisp/scDisp.pro b/applications/mne_scan/libs/scDisp/scDisp.pro index 148086b87fd..5364d40073e 100644 --- a/applications/mne_scan/libs/scDisp/scDisp.pro +++ b/applications/mne_scan/libs/scDisp/scDisp.pro @@ -97,8 +97,10 @@ SOURCES += \ realtimecovwidget.cpp \ realtimespectrumwidget.cpp \ realtime3dwidget.cpp \ + realtimetimefrequencywidget.cpp HEADERS += \ + realtimetimefrequencywidget.h \ scdisp_global.h \ measurementwidget.h \ realtimemultisamplearraywidget.h \ diff --git a/applications/mne_scan/libs/scMeas/realtimeevokedset.h b/applications/mne_scan/libs/scMeas/realtimeevokedset.h index cf60b462314..9629b6f5e12 100644 --- a/applications/mne_scan/libs/scMeas/realtimeevokedset.h +++ b/applications/mne_scan/libs/scMeas/realtimeevokedset.h @@ -44,6 +44,7 @@ #include "realtimesamplearraychinfo.h" #include +#include //============================================================================================================= // QT INCLUDES diff --git a/applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp b/applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp new file mode 100644 index 00000000000..b0858741050 --- /dev/null +++ b/applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp @@ -0,0 +1,58 @@ +//============================================================================================================= +/** + * @file realtimetimefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the definition of the RealTimeTimeFrequency class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "realtimetimefrequency.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace SCMEASLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +RealTimeTimeFrequency::RealTimeTimeFrequency() +{ + +} diff --git a/applications/mne_scan/libs/scMeas/realtimetimefrequency.h b/applications/mne_scan/libs/scMeas/realtimetimefrequency.h new file mode 100644 index 00000000000..f7e787a41a4 --- /dev/null +++ b/applications/mne_scan/libs/scMeas/realtimetimefrequency.h @@ -0,0 +1,82 @@ +//============================================================================================================= +/** + * @file realtimetimefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the RealTimeTimeFrequency class. + * + */ + +#ifndef REALTIMETIMEFREQUENCY_H +#define REALTIMETIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "scmeas_global.h" +#include "measurement.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace FIFFLIB { + class FiffInfo; +} + +//============================================================================================================= +// DEFINE NAMESPACE SCMEASLIB +//============================================================================================================= + +namespace SCMEASLIB +{ + +class SCMEASSHARED_EXPORT RealTimeTimeFrequency : public Measurement +{ + Q_OBJECT +public: + RealTimeTimeFrequency(); + + Eigen::MatrixXcd m_matData; + QSharedPointer m_pFiffInfo; /**< Fiff info */ + + +}; +}//namespace +#endif // REALTIMETIMEFREQUENCY_H diff --git a/applications/mne_scan/libs/scMeas/scMeas.pro b/applications/mne_scan/libs/scMeas/scMeas.pro index 4f164fe9ffa..f0fb36585dd 100644 --- a/applications/mne_scan/libs/scMeas/scMeas.pro +++ b/applications/mne_scan/libs/scMeas/scMeas.pro @@ -82,7 +82,8 @@ SOURCES += \ realtimecov.cpp \ realtimehpiresult.cpp \ realtimespectrum.cpp \ - realtimefwdsolution.cpp + realtimefwdsolution.cpp \ + realtimetimefrequency.cpp \ HEADERS += \ scmeas_global.h \ @@ -97,7 +98,8 @@ HEADERS += \ realtimecov.h \ realtimehpiresult.h \ realtimespectrum.h \ - realtimefwdsolution.h + realtimefwdsolution.h \ + realtimetimefrequency.h \ INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} diff --git a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp index fe5d49c6975..72a77a05dcc 100644 --- a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp +++ b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,7 @@ #include #include #include +#include //============================================================================================================= // QT INCLUDES @@ -182,6 +184,16 @@ QWidget* DisplayManager::show(AbstractPlugin::OutputConnectorList &outputConnect vboxLayout->addWidget(fsWidget); fsWidget->init(); + } else if (pPluginOutputConnector.dynamicCast< PluginOutputData >()) { + RealTimeTimeFrequencyWidget* tfWidget = new RealTimeTimeFrequencyWidget(pT, newDisp); + + qListActions.append(tfWidget->getDisplayActions()); + + connect(pPluginOutputConnector.data(), &PluginOutputConnector::notify, + tfWidget, &RealTimeTimeFrequencyWidget::update, Qt::BlockingQueuedConnection); + + vboxLayout->addWidget(tfWidget); + tfWidget->init(); } } diff --git a/applications/mne_scan/mne_scan/main.cpp b/applications/mne_scan/mne_scan/main.cpp index 978cea99da6..bc177edbed9 100644 --- a/applications/mne_scan/mne_scan/main.cpp +++ b/applications/mne_scan/mne_scan/main.cpp @@ -94,6 +94,7 @@ Q_IMPORT_PLUGIN(NeuronalConnectivity) Q_IMPORT_PLUGIN(FtBuffer) Q_IMPORT_PLUGIN(WriteToFile) Q_IMPORT_PLUGIN(Hpi) +Q_IMPORT_PLUGIN(TimeFrequency) //Q_IMPORT_PLUGIN(DummyToolbox) #ifdef WITHGUSBAMP Q_IMPORT_PLUGIN(GUSBAmp) @@ -176,5 +177,7 @@ int main(int argc, char *argv[]) mainWin.hideSplashScreen(); - return app.exec(); + int return_value(app.exec()); + + return return_value; } diff --git a/applications/mne_scan/plugins/plugins.pro b/applications/mne_scan/plugins/plugins.pro index 9e4b48f69b5..3c385c5cd34 100644 --- a/applications/mne_scan/plugins/plugins.pro +++ b/applications/mne_scan/plugins/plugins.pro @@ -77,3 +77,4 @@ SUBDIRS += \ writetofile \ hpi \ rtfwd \ + #timefrequency \ diff --git a/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui new file mode 100644 index 00000000000..c7baf50bf05 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui @@ -0,0 +1,98 @@ + + + TimeFrequencySetupWidgetClass + + + + 0 + 0 + 600 + 450 + + + + DummySetupWidget + + + + + + + 75 + true + + + + TimeFrequency + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + + + 16777215 + 16777215 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Description:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">How to setup this plugin?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">How to control this plugin during the measurement?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Input data type:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Output data type:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + diff --git a/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp new file mode 100644 index 00000000000..00c7e7ba204 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp @@ -0,0 +1,70 @@ +//============================================================================================================= +/** + * @file timefrequencysetupwidget.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencySetupWidget class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencysetupwidget.h" + +#include "../timefrequency.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace TIMEFREQUENCYPLUGIN; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencySetupWidget::TimeFrequencySetupWidget(TimeFrequency* toolbox, QWidget *parent) +: QWidget(parent) +, m_pTimeFrequency(toolbox) +{ + ui.setupUi(this); +} + +//============================================================================================================= + +TimeFrequencySetupWidget::~TimeFrequencySetupWidget() +{ +} diff --git a/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h new file mode 100644 index 00000000000..cfea9b53db3 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h @@ -0,0 +1,99 @@ +//============================================================================================================= +/** + * @file timefrequencysetupwidget.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the TimeFrequencySetupWidget class. + * + */ + +#ifndef TIMEFREQUENCYSETUPWIDGET_H +#define TIMEFREQUENCYSETUPWIDGET_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "ui_timefrequencysetup.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// DEFINE NAMESPACE TIMEFREQUENCYPLUGIN +//============================================================================================================= + +namespace TIMEFREQUENCYPLUGIN +{ + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class TimeFrequency; + +//============================================================================================================= +/** + * DECLARE CLASS TimeFrequencySetupWidget + * + * @brief The TimeFrequencySetupWidget class provides the TimeFrequencyToolbox configuration window. + */ +class TimeFrequencySetupWidget : public QWidget +{ + Q_OBJECT + +public: + + //========================================================================================================= + /** + * Constructs a TimeFrequencySetupWidget which is a child of parent. + * + * @param [in] toolbox a pointer to the corresponding TimeFrequency toolbox. + * @param [in] parent pointer to parent widget; If parent is 0, the new TimeFrequencySetupWidget becomes a window. If parent is another widget, TimeFrequencySetupWidget becomes a child window inside parent. TimeFrequencySetupWidget is deleted when its parent is deleted. + */ + TimeFrequencySetupWidget(TimeFrequency* toolbox, QWidget *parent = 0); + + //========================================================================================================= + /** + * Destroys the TimeFrequencySetupWidget. + * All TimeFrequencySetupWidget's children are deleted first. The application exits if TimeFrequencySetupWidget is the main widget. + */ + ~TimeFrequencySetupWidget(); + +private: + + TimeFrequency* m_pTimeFrequency; /**< Holds a pointer to corresponding TimeFrequency.*/ + + Ui::TimeFrequencySetupWidgetClass ui; /**< Holds the user interface for the TimeFrequencySetupWidget.*/ +}; +} // NAMESPACE + +#endif // TIMEFREQUENCYSETUPWIDGET_H diff --git a/applications/mne_scan/plugins/timefrequency/images/icons/timefrequencyadjustments.png b/applications/mne_scan/plugins/timefrequency/images/icons/timefrequencyadjustments.png new file mode 100644 index 00000000000..56b43e9b54a Binary files /dev/null and b/applications/mne_scan/plugins/timefrequency/images/icons/timefrequencyadjustments.png differ diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp new file mode 100644 index 00000000000..35be6730b8a --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp @@ -0,0 +1,307 @@ +//============================================================================================================= +/** + * @file timefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequency class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency.h" +#include "FormFiles/timefrequencysetupwidget.h" + +#include + +#include +#include +#include + +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace TIMEFREQUENCYPLUGIN; +using namespace SCSHAREDLIB; +using namespace SCMEASLIB; +using namespace UTILSLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequency::TimeFrequency() +: m_pCircularEvokedBuffer(CircularBuffer::SPtr::create(40)) +, m_iDataQueueBlockSize(15) +{ +} + +//============================================================================================================= + +TimeFrequency::~TimeFrequency() +{ + if(this->isRunning()) + stop(); +} + +//============================================================================================================= + +QSharedPointer TimeFrequency::clone() const +{ + QSharedPointer pTimeFrequencyClone(new TimeFrequency); + return pTimeFrequencyClone; +} + +//============================================================================================================= + +void TimeFrequency::unload() +{ +} + +//============================================================================================================= + +bool TimeFrequency::start() +{ + QThread::start(); + + return true; +} + +//============================================================================================================= + +bool TimeFrequency::stop() +{ + requestInterruption(); + wait(500); + + m_bPluginControlWidgetsInit = false; + + return true; +} + +//============================================================================================================= + +AbstractPlugin::PluginType TimeFrequency::getType() const +{ + return _IAlgorithm; +} + +//============================================================================================================= + +QString TimeFrequency::getName() const +{ + return "TimeFrequency"; +} + +//============================================================================================================= + +QWidget* TimeFrequency::setupWidget() +{ + TimeFrequencySetupWidget* setupWidget = new TimeFrequencySetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new + return setupWidget; +} + +//============================================================================================================= + +void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) +{ + if(QSharedPointer pRTES = pMeasurement.dynamicCast()) { + if(!m_pFiffInfo) { + m_pFiffInfo = pRTES->info(); + } + + FIFFLIB::FiffEvokedSet::SPtr pFiffEvokedSet = pRTES->getValue(); + + if(this->isRunning()) { + for(int i = 0; i < pFiffEvokedSet->evoked.size(); ++i) { + while(!m_pCircularEvokedBuffer->push(pFiffEvokedSet->evoked.at(i))) { + //Do nothing until the circular buffer is ready to accept new data again + } + } + } + } + if(QSharedPointer pRTMSA = pMeasurement.dynamicCast()) { + //Fiff information + if(!m_pFiffInfo) { + m_pFiffInfo = pRTMSA->info(); + } + +// if (!m_pRTTF){ +// } + + if (m_pFiffInfo){ + QMutexLocker locker(&m_qMutex); + for(unsigned char i = 0; i < pRTMSA->getMultiSampleArray().size(); ++i) { + std::cout << "pRTMSA->getMultiSampleArray().size() " << pRTMSA->getMultiSampleArray().size(); + // Please note that we do not need a copy here since this function will block until + // the buffer accepts new data again. Hence, the data is not deleted in the actual + // Measurement function after it emitted the notify signal. +// m_DataQueue.push_back(pRTMSA->getMultiSampleArray()[i]); + while(!m_pCircularTimeSeriesBuffer->push(pRTMSA->getMultiSampleArray()[i])) { + //Do nothing until the circular buffer is ready to accept new data again + } + } + } + } +} + +//============================================================================================================= + +void TimeFrequency::init() +{ + // Input + m_pTimeFrequencyEvokedInput = PluginInputData::create(this, "TfEvokedIn", "Time frequency input data"); + connect(m_pTimeFrequencyEvokedInput.data(), &PluginInputConnector::notify, + this, &TimeFrequency::update, Qt::DirectConnection); + m_inputConnectors.append(m_pTimeFrequencyEvokedInput); + + m_pTimeFrequencyTimeSeriesInput = PluginInputData::create(this, "TfTimeSeiresIn", "Time frequency input data"); + connect(m_pTimeFrequencyTimeSeriesInput.data(), &PluginInputConnector::notify, + this, &TimeFrequency::update, Qt::DirectConnection); + m_inputConnectors.append(m_pTimeFrequencyTimeSeriesInput); + + //Output + m_pTimeFrequencyOutput = PluginOutputData::create(this, "TfOut", "Time frequency output data"); + m_pTimeFrequencyOutput->measurementData()->setName(getName()); + m_outputConnectors.append(m_pTimeFrequencyOutput); +} + +//============================================================================================================= + +void TimeFrequency::initPluginControlWidgets() +{ + if(m_pFiffInfo) { + + } +} + +//============================================================================================================= +#include +void TimeFrequency::run() +{ + FIFFLIB::FiffEvoked evoked; + QStringList lResponsibleTriggerTypes; + Eigen::MatrixXd matData; + + + while(!isInterruptionRequested()){ + if(m_pCircularTimeSeriesBuffer->pop(matData)){ + +// int iCols = 0; + +// std::cout<< "First matrix r:" << m_DataQueue.front().rows() << " | c: " << m_DataQueue.front().cols() << std::endl; + +// for (auto mat : m_DataQueue){ +// iCols += mat.cols(); +// } + +// std::cout << "COLS: " << iCols << std::endl; + +// Eigen::MatrixXd dataMat(m_DataQueue.front().rows(), iCols); + +// for (auto mat : m_DataQueue){ +// Eigen::MatrixXd temp = mat; +// dataMat << temp; +// } + +// std::cout << "New Matrix - r: " << dataMat.rows() << " | c: " << dataMat.cols() << std::endl; + +// if((testing_counter % 20) == 0){ +// Eigen::VectorXd dataCol = dataMat.row(1).transpose(); + +// Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, m_pFiffInfo->sfreq * 0.2); + +//// DISPLIB::TFplot* tfplot2 = new DISPLIB::TFplot(Spectrum, m_pFiffInfo->sfreq, 0, 50, DISPLIB::ColorMaps::Jet); + +//// tfplot2->show(); +// } + +// while(m_DataQueue.size() > m_iDataQueueBlockSize){ +// m_DataQueue.pop_front(); +// } +// testing_counter++; + } +// if(m_pCircularEvokedBuffer->pop(evoked)) { +// m_qMutex.lock(); +// lResponsibleTriggerTypes = m_lResponsibleTriggerTypes; +// m_qMutex.unlock(); + +// m_pTimeFrequencyOutput->measurementData()->setValue(evokedSet, +// m_pFiffInfo, +// lResponsibleTriggerTypes); +// } + } +} + +//============================================================================================================= + +void TimeFrequency::computeTimeFrequency() +{ + int iCols = 0; + + std::cout<< "First matrix r:" << m_DataQueue.front().rows() << " | c: " << m_DataQueue.front().cols() << std::endl; + + Eigen::MatrixXd dataMat(m_DataQueue.front().rows(), iCols); + + { + QMutexLocker locker(&m_qMutex); + for (auto mat : m_DataQueue){ + iCols += mat.cols(); + } + + std::cout << "COLS: " << iCols << std::endl; + for (auto mat : m_DataQueue){ + dataMat << mat; + } + } + std::cout << "New Matrix - r: " << dataMat.rows() << " | c: " << dataMat.cols() << std::endl; + +// for(int i = 0; i < dataMat.rows(); i++){ +// Eigen::VectorXd dataCol = dataMat.row(i).transpose(); + +// Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, m_pFiffInfo->sfreq * 0.2); +// } + +} diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.h b/applications/mne_scan/plugins/timefrequency/timefrequency.h new file mode 100644 index 00000000000..71b8a62a2ed --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.h @@ -0,0 +1,173 @@ +//============================================================================================================= +/** + * @file timefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the TimeFrequency class. + * + */ + +#ifndef TIMEFREQUENCY_H +#define TIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency_global.h" + +#include +#include + +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace SCMEASLIB{ + class RealTimeEvokedSet; + class RealTimeTimeFrequency; + class RealTimeMultiSampleArray; +} + +namespace RTPROCESSINGLIB{ + class RtTimeFrequency; +} + +//============================================================================================================= +// DEFINE NAMESPACE TIMEFREQUENCYPLUGIN +//============================================================================================================= + +namespace TIMEFREQUENCYPLUGIN +{ + +//============================================================================================================= +// TIMEFREQUENCYPLUGIN FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS TimeFrequency + * + * @brief The TimeFrequency class provides a TimeFrequency algorithm structure. + */ +class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public SCSHAREDLIB::AbstractAlgorithm +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "scsharedlib/1.0" FILE "timefrequency.json") //New Qt5 Plugin system replaces Q_EXPORT_PLUGIN2 macro + // Use the Q_INTERFACES() macro to tell Qt's meta-object system about the interfaces + Q_INTERFACES(SCSHAREDLIB::AbstractAlgorithm) + + friend class TimeFrequencySettingsWidget; + +public: + //========================================================================================================= + /** + * Constructs a TimeFrequency. + */ + TimeFrequency(); + + //========================================================================================================= + /** + * Destroys the TimeFrequency. + */ + ~TimeFrequency(); + + //========================================================================================================= + /** + * Inits widgets which are used to control this plugin, then emits them in form of a QList. + */ + void initPluginControlWidgets(); + + //========================================================================================================= + /** + * Reimplemented virtual functions + */ + virtual void unload(); + virtual QSharedPointer clone() const; + virtual bool start(); + virtual bool stop(); + virtual SCSHAREDLIB::AbstractPlugin::PluginType getType() const; + virtual QString getName() const; + virtual QWidget* setupWidget(); + void update(SCMEASLIB::Measurement::SPtr pMeasurement); + + //========================================================================================================= + /** + * Initialise input and output connectors. + */ + virtual void init(); + +private: + virtual void run(); + + void computeTimeFrequency(); + + SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyTimeSeriesInput; /**< The RealTimeMultiSampleArray of the NoiseReduction input.*/ + SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyEvokedInput; /**< The RealTimeSampleArray of the TimeFrequency input.*/ + SCSHAREDLIB::PluginOutputData::SPtr m_pTimeFrequencyOutput; /**< The RealTimeEvoked of the TimeFrequency output.*/ + + QSharedPointer> m_pCircularEvokedBuffer; /**< Holds incoming RealTimeMultiSampleArray data.*/ + QSharedPointer m_pCircularTimeSeriesBuffer; /**< Holds incoming raw data. */ + + QSharedPointer m_pRTTF; + + QMutex m_qMutex; /**< Provides access serialization between threads. */ + + FIFFLIB::FiffInfo::SPtr m_pFiffInfo; /**< Fiff measurement info.*/ + + std::deque m_DataQueue; + + QMap m_mapStimChsIndexNames; /**< The currently available stim channels and their corresponding index in the data. */ + + QFuture m_Future; + QFutureWatcher m_FutureWatcher; + + int m_iDataQueueBlockSize; +signals: + +}; +} // NAMESPACE + +#endif // TIMEFREQUENCY_H diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.json b/applications/mne_scan/plugins/timefrequency/timefrequency.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.pro b/applications/mne_scan/plugins/timefrequency/timefrequency.pro new file mode 100644 index 00000000000..3d745c95fe0 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.pro @@ -0,0 +1,132 @@ +#============================================================================================================== +# +# @file timefrequency.pro +# @author Gabriel Motta +# @since 0.1.9 +# @date April, 2021 +# +# @section LICENSE +# +# Copyright (C) 2021, Gabriel Motta. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that +# the following conditions are met: +# * Redistributions of source code must retain the above copyright notice, this list of conditions and the +# following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or other materials provided with the distribution. +# * Neither the name of MNE-CPP authors nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# +# @brief This project file generates the makefile for the timefrequency plug-in. +# +#============================================================================================================== + +include(../../../../mne-cpp.pri) + +TEMPLATE = lib + +QT += core widgets + +CONFIG += skip_target_version_ext plugin + +DEFINES += TIMEFREQUENCY_PLUGIN + +DESTDIR = $${MNE_BINARY_DIR}/mne_scan_plugins + +TARGET = timefrequency +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lscSharedd \ + -lscDispd \ + -lscMeasd \ + -lmnecppDispd \ + -lmnecppRtProcessingd \ + -lmnecppConnectivityd \ + -lmnecppInversed \ + -lmnecppFwdd \ + -lmnecppMned \ + -lmnecppFiffd \ + -lmnecppFsd \ + -lmnecppUtilsd \ +} else { + LIBS += -lscShared \ + -lscDisp \ + -lscMeas \ + -lmnecppDisp \ + -lmnecppRtProcessing \ + -lmnecppConnectivity \ + -lmnecppInverse \ + -lmnecppFwd \ + -lmnecppMne \ + -lmnecppFiff \ + -lmnecppFs \ + -lmnecppUtils \ +} + +SOURCES += \ + timefrequency.cpp \ + FormFiles/timefrequencysetupwidget.cpp \ + +HEADERS += \ + timefrequency_global.h \ + timefrequency.h \ + FormFiles/timefrequencysetupwidget.h \ + +FORMS += \ + FormFiles/timefrequencysetup.ui \ + +RESOURCES += \ + timefrequency.qrc + +OTHER_FILES += \ + timefrequency.json + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} +INCLUDEPATH += $${MNE_SCAN_INCLUDE_DIR} + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.qrc b/applications/mne_scan/plugins/timefrequency/timefrequency.qrc new file mode 100644 index 00000000000..f987ec0e96f --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.qrc @@ -0,0 +1,5 @@ + + + images/icons/timefrequencyadjustments.png + + diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency_global.h b/applications/mne_scan/plugins/timefrequency/timefrequency_global.h new file mode 100644 index 00000000000..54c5dc01a9f --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency_global.h @@ -0,0 +1,54 @@ +//============================================================================================================= +/** + * @file timefrequency_global.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the TimeFrequency library export/import macros. + * + */ + +#ifndef TIMEFREQUENCY_GLOBAL_H +#define TIMEFREQUENCY_GLOBAL_H + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// PREPROCESSOR DEFINES +//============================================================================================================= + +#if defined(TIMEFREQUENCY_PLUGIN) +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_EXPORT /**< Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library. */ +#else +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_IMPORT /**< Q_DECL_IMPORT must be added to the declarations of symbols used when compiling a client that uses the shared library. */ +#endif + +#endif // TIMEFREQUENCY_GLOBAL_H diff --git a/examples/ex_disp/ex_disp.pro b/examples/ex_disp/ex_disp.pro index ea126b2661d..dd39ec1b57f 100644 --- a/examples/ex_disp/ex_disp.pro +++ b/examples/ex_disp/ex_disp.pro @@ -113,4 +113,3 @@ contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { -lfftw3_threads \ } } - diff --git a/examples/ex_time_frequency/ex_time_frequency.pro b/examples/ex_time_frequency/ex_time_frequency.pro new file mode 100644 index 00000000000..6679017084a --- /dev/null +++ b/examples/ex_time_frequency/ex_time_frequency.pro @@ -0,0 +1,84 @@ +QT -= gui + +include(../../mne-cpp.pri) + +TEMPLATE = app + +QT += core gui charts opengl widgets concurrent network + +CONFIG += console +!contains(MNECPP_CONFIG, withAppBundles) { + CONFIG -= app_bundle +} + +DESTDIR = $${MNE_BINARY_DIR} + +TARGET = ex_time_frequency +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += static + DEFINES += STATICBUILD +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lmnecppDispd \ + -lmnecppEventsd \ + -lmnecppRtProcessingd \ + -lmnecppConnectivityd \ + -lmnecppInversed \ + -lmnecppFwdd \ + -lmnecppMned \ + -lmnecppFiffd \ + -lmnecppFsd \ + -lmnecppUtilsd \ + -lmnecppTimeFrequencyd \ +} else { + LIBS += -lmnecppDisp \ + -lmnecppEvents \ + -lmnecppRtProcessing \ + -lmnecppConnectivity \ + -lmnecppInverse \ + -lmnecppFwd \ + -lmnecppMne \ + -lmnecppFiff \ + -lmnecppFs \ + -lmnecppUtils \ + -lmnecppTimeFrequency \ +} + +SOURCES += main.cpp + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../lib +} + +macx { + QMAKE_LFLAGS += -Wl,-rpath,@executable_path/../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} diff --git a/examples/ex_time_frequency/main.cpp b/examples/ex_time_frequency/main.cpp new file mode 100644 index 00000000000..cda8169808a --- /dev/null +++ b/examples/ex_time_frequency/main.cpp @@ -0,0 +1,145 @@ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// Eigen +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +#include +#include + +//============================================================================================================= +// MAIN +//============================================================================================================= + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QCommandLineParser parser; + parser.setApplicationDescription("TF Example"); + parser.addHelpOption(); + + QCommandLineOption inputOption("fileIn", "The input file .", "in", QCoreApplication::applicationDirPath() + "/MNE-sample-data/MEG/sample/sample_audvis_raw.fif"); + parser.addOption(inputOption); + + QCommandLineOption fromOption("from", "Read data from (in seconds).", "from", "42.956"); + parser.addOption(fromOption); + + QCommandLineOption toOption("to", "Read data from (in seconds).", "to", "320.670"); + parser.addOption(toOption); + + parser.process(app); + + QFile t_fileRaw(parser.value(inputOption)); + + float from = parser.value(fromOption).toFloat(); + float to = parser.value(toOption).toFloat(); + + bool in_samples = false; + bool keep_comp = false; + + + FIFFLIB::FiffRawData raw(t_fileRaw); + + // + // Set up pick list: MEG + STI 014 - bad channels + // + // + QStringList include; + include << "STI 014"; + bool want_meg = true; + bool want_eeg = false; + bool want_stim = false; + + Eigen::RowVectorXi picks = raw.info.pick_types(want_meg, want_eeg, want_stim, include, raw.info.bads); + + // + // Set up projection + // + qint32 k = 0; + if (raw.info.projs.size() == 0) + qInfo("No projector specified for these data\n"); + else + { + // + // Activate the projection items + // + for (k = 0; k < raw.info.projs.size(); ++k) + raw.info.projs[k].active = true; + + qInfo("%d projection items activated\n",raw.info.projs.size()); + // + // Create the projector + // + FIFFLIB::fiff_int_t nproj = raw.info.make_projector(raw.proj); + + if (nproj == 0) + qWarning("The projection vectors do not apply to these channels\n"); + else + qInfo("Created an SSP operator (subspace dimension = %d)\n",nproj); + } + + // + // Set up the CTF compensator + // + qint32 current_comp = raw.info.get_current_comp(); + qint32 dest_comp = 0; + + if (current_comp > 0) + qInfo("Current compensation grade : %d\n",current_comp); + + if (keep_comp) + dest_comp = current_comp; + + if (current_comp != dest_comp) + { + if(MNELIB::MNE::make_compensator(raw.info, current_comp, dest_comp, raw.comp)) + { + raw.info.set_current_comp(dest_comp); + qInfo("Appropriate compensator added to change to grade %d.\n",dest_comp); + } + else + { + qWarning("Could not make the compensator\n"); + return -1; + } + } + // + // Read a data segment + // times output argument is optional + // + bool readSuccessful = false; + Eigen::MatrixXd data; + Eigen::MatrixXd times; + if (in_samples) + readSuccessful = raw.read_raw_segment(data, times, (qint32)from, (qint32)to, picks); + else + readSuccessful = raw.read_raw_segment_times(data, times, from, to, picks); + + if (!readSuccessful) + { + qWarning("Could not read raw segment.\n"); + return -1; + } + + + TIMEFREQUENCYLIB::TimeFrequencyAnalyzer analyzer(TIMEFREQUENCYLIB::SuperletSettings); + //data. + + return app.exec(); +} diff --git a/examples/examples.pro b/examples/examples.pro index 5587bc265ed..364dbf651f8 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -63,6 +63,7 @@ SUBDIRS += \ ex_read_fwd \ ex_read_raw \ ex_read_write_raw \ + ex_time_frequency \ qtHaveModule(charts) { SUBDIRS += \ diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index e02f9599908..7dbbe16c1b0 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -44,6 +44,11 @@ QT += core widgets svg concurrent opengl qtHaveModule(printsupport): QT += printsupport qtHaveModule(charts): QT += charts +qtHaveModule(datavisualization){ +QT += qml quick datavisualization quickwidgets +} + + DEFINES += DISP_LIBRARY DESTDIR = $${MNE_LIBRARY_DIR} @@ -105,7 +110,11 @@ SOURCES += \ viewers/filterdesignview.cpp \ viewers/averagelayoutview.cpp \ viewers/fwdsettingsview.cpp \ + viewers/helpers/colorlib.cpp \ viewers/helpers/scalecontrol.cpp \ + viewers/helpers/timefrequencymodel.cpp \ + viewers/helpers/timefrequencyscene.cpp \ + viewers/helpers/timefrequencysceneitem.cpp \ viewers/progressview.cpp \ viewers/spectrumview.cpp \ viewers/modalityselectionview.cpp \ @@ -119,6 +128,9 @@ SOURCES += \ viewers/spharasettingsview.cpp \ viewers/fiffrawviewsettings.cpp \ viewers/averageselectionview.cpp \ + viewers/timefrequencylayoutview.cpp \ + viewers/timefrequencysettingsview.cpp \ + viewers/timefrequencyview.cpp \ viewers/triggerdetectionview.cpp \ viewers/quickcontrolview.cpp \ viewers/connectivitysettingsview.cpp \ @@ -164,7 +176,11 @@ HEADERS += \ viewers/filterdesignview.h \ viewers/averagelayoutview.h \ viewers/fwdsettingsview.h \ + viewers/helpers/colorlib.h \ viewers/helpers/scalecontrol.h \ + viewers/helpers/timefrequencymodel.h \ + viewers/helpers/timefrequencyscene.h \ + viewers/helpers/timefrequencysceneitem.h \ viewers/progressview.h \ viewers/spectrumview.h \ viewers/modalityselectionview.h \ @@ -178,6 +194,9 @@ HEADERS += \ viewers/spharasettingsview.h \ viewers/fiffrawviewsettings.h \ viewers/averageselectionview.h \ + viewers/timefrequencylayoutview.h \ + viewers/timefrequencysettingsview.h \ + viewers/timefrequencyview.h \ viewers/triggerdetectionview.h \ viewers/quickcontrolview.h \ viewers/connectivitysettingsview.h \ @@ -230,6 +249,7 @@ FORMS += \ viewers/formfiles/progressview.ui \ viewers/formfiles/spharasettingsview.ui \ viewers/formfiles/fiffrawviewsettings.ui \ + viewers/formfiles/timefrequencysettingsview.ui \ viewers/formfiles/triggerdetectionview.ui \ viewers/formfiles/quickcontrolview.ui \ viewers/formfiles/tfsettingsview.ui \ diff --git a/libraries/disp/plots/tfplot.cpp b/libraries/disp/plots/tfplot.cpp index f2a6c551987..1c53ddef38d 100644 --- a/libraries/disp/plots/tfplot.cpp +++ b/libraries/disp/plots/tfplot.cpp @@ -305,10 +305,16 @@ void TFplot::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); + adjustViewSize(); +} + +//============================================================================================================= + +void TFplot::adjustViewSize() +{ QWidget *widget = this->layout()->itemAt(0)-> widget(); if (widget != NULL ) { QGraphicsView* view = (QGraphicsView*)widget; view->fitInView(view->sceneRect(),Qt::KeepAspectRatio); } } - diff --git a/libraries/disp/plots/tfplot.h b/libraries/disp/plots/tfplot.h index 6d3f654a5ac..4fe5ca67b6b 100644 --- a/libraries/disp/plots/tfplot.h +++ b/libraries/disp/plots/tfplot.h @@ -122,6 +122,8 @@ class DISPSHARED_EXPORT TFplot : public QWidget qreal sample_rate, ColorMaps cmap); + void adjustViewSize(); + protected: //========================================================================================================= /** diff --git a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui new file mode 100644 index 00000000000..8b41362da5f --- /dev/null +++ b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui @@ -0,0 +1,189 @@ + + + TimeFrequencySettingsWidget + + + + 0 + 0 + 322 + 432 + + + + Form + + + + + + + 0 + 0 + + + + Parameters + + + + + + + + + 0 + 0 + + + + Frequency: + + + + + + + + 0 + 0 + + + + Hz + + + 0 + + + 999 + + + 0 + + + + + + + - + + + + + + + + 0 + 0 + + + + Hz + + + 20 + + + 999 + + + 100 + + + + + + + + + + + + 0 + 0 + + + + Color Map: + + + + + + + + 0 + 0 + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Use average + + + true + + + + + + + Use raw data + + + false + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Compute + + + + + + + + diff --git a/libraries/disp/viewers/helpers/colorlib.cpp b/libraries/disp/viewers/helpers/colorlib.cpp new file mode 100644 index 00000000000..1b0723ba590 --- /dev/null +++ b/libraries/disp/viewers/helpers/colorlib.cpp @@ -0,0 +1,89 @@ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "colorlib.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE STATIC METHODS +//============================================================================================================= + +//ColorMap ColorMap::fromGradient(const ColorGradient &gradient, +// int resolution) +//{ +// ColorMap map; +// map.m_iResolution = resolution; + +// for (int i = 0 ; i < resolution; i++){ +// float value = static_cast(i) / static_cast(resolution); +// map.m_vColors.push_back(gradient.getColor(value)); +// } + +// return map; +//} + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +ColorGradient::ColorGradient(std::initializer_list list) +{ + for (ColorPoint color : list){ + m_vecColors.push_back(color); + } +} + +//============================================================================================================= + +Color ColorGradient::getColor(float value) const +{ + if(!m_vecColors.size()){ + return Color(0,0,0); + } + + Color color(0,0,0); + + for (int i = 0; i< m_vecColors.size(); i++){ + const ColorPoint& currentColor = m_vecColors[i]; + if(value < currentColor.val){ + int index = ((i-1) > 0) ? i-1 : 0; + const ColorPoint& prevColor = m_vecColors[index]; + + float fDifference = currentColor.val - prevColor.val; + float fRatio = (fDifference) ? ((value - currentColor.val)/fDifference) : 0; + + color.r = (fRatio * (currentColor.r() - prevColor.r())) + currentColor.r(); + color.g = (fRatio * (currentColor.g() - prevColor.g())) + currentColor.g(); + color.b = (fRatio * (currentColor.b() - prevColor.b())) + currentColor.b(); + + return color; + } + } + return color; +} + +//============================================================================================================= + +#ifdef QT_CORE_LIB +QLinearGradient ColorGradient::getQGradient(QPoint from, QPoint to) const +{ + QLinearGradient gradient(from, to); + for(const ColorPoint& color : m_vecColors){ + gradient.setColorAt(color.val, color.getQColor()); + } + + return gradient; +} +#endif diff --git a/libraries/disp/viewers/helpers/colorlib.h b/libraries/disp/viewers/helpers/colorlib.h new file mode 100644 index 00000000000..d10d65a5e56 --- /dev/null +++ b/libraries/disp/viewers/helpers/colorlib.h @@ -0,0 +1,127 @@ +#ifndef COLORLIB_H +#define COLORLIB_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#ifdef QT_CORE_LIB +#include +#include +#endif + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +struct Color; +struct ColorPoint; +class ColorMap; +class ColorGradient; + + +//============================================================================================================= +/** + * Holds data on an RBG Color + */ +struct Color{ + float r; + float g; + float b; + Color() : Color(0,0,0) {} + Color(float red, + float green, + float blue) : r(red), g(green), b(blue) {} +#ifdef QT_CORE_LIB + QColor getQColor() const {return QColor(r, g, b);} +#endif +}; + +//============================================================================================================= +/** + * Holds data on an RGB Color associated with a value between 0-1 + */ +struct ColorPoint +{ + ColorPoint(float red, + float green, + float blue, + float value): m_color(red, green, blue), val(value) {} + ColorPoint(Color color, + int value): m_color(color), val(value) {} + Color m_color; + float val; + float r() const {return m_color.r;} + float g() const {return m_color.g;} + float b() const {return m_color.b;} +#ifdef QT_CORE_LIB + QColor getQColor() const {return m_color.getQColor();} +#endif +}; + +//============================================================================================================= +/** + * Holds a colormap + */ +//class ColorMap +//{ +//public: +// uint size() const {return m_vColors.size();} + +// int resolution() const {return m_iResolution;} + +// static ColorMap fromGradient(const ColorGradient& gradient, +// int resolution = 256); +//private: +// ColorMap(); + +// int m_iResolution; +// std::vector m_vColors; +//}; + +//============================================================================================================= +/** + * A Gradient between multiple colors + */ +class ColorGradient +{ +public: + ColorGradient() = delete; + ColorGradient(std::initializer_list list); + + Color getColor(float value) const; + +#ifdef QT_CORE_LIB + QLinearGradient getQGradient(QPoint from, QPoint to) const; +#endif +// ColorMap getColorMap(); + +private: + + std::vector m_vecColors; +}; + + +}//namespace + +#endif // COLORGRADIENT_H diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp new file mode 100644 index 00000000000..269b79ed2d9 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -0,0 +1,250 @@ +//============================================================================================================= +/** + * @file timefrequencymodel.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencyModel Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencymodel.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyModel::TimeFrequencyModel() +: m_iMinFreq(0) +, m_iMaxFreq(100) +{ + +} + +//============================================================================================================= + +TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) +: m_vSpectr(std::move(spectr)) +, m_iMinFreq(0) +, m_iMaxFreq(100) +{ + +} + +//============================================================================================================= + +void TimeFrequencyModel::setSpectr(std::vector& spectr) +{ + m_vSpectr.clear(); + m_vSpectr = std::move(spectr); + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); +} + +//============================================================================================================= + +int TimeFrequencyModel::rowCount(const QModelIndex & /*parent*/) const +{ + return m_vSpectr.size(); +} + +//============================================================================================================= + +int TimeFrequencyModel::columnCount(const QModelIndex & /*parent*/) const +{ + return 3; +} + +//============================================================================================================= + +QVariant TimeFrequencyModel::data(const QModelIndex &index, + int role) const +{ + if(role != Qt::DisplayRole && role != Qt::BackgroundRole) { + return QVariant(); + } + + int row = index.row(); + + if(!index.isValid() && row >= m_vSpectr.size()) { + return QVariant(); + } + + if(index.column() == 0 && role == Qt::DisplayRole) { + // return QVariant(m_pEvokedSet->info.ch_names); + + } + + if(index.column() == 1) { //timefrequencyview + switch(role){ + case Qt::BackgroundRole:{ + return QVariant(); + } + case Qt::DisplayRole:{ + QVariant variant; + + Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); + + int a = 0; + if(m_listSelection.size() > 0){ + for (int iChIndex : m_listSelection){ + if (iChIndex < m_vSpectr.size()){ + matrix += m_vSpectr[iChIndex]; + qDebug() << a << "Adding channel" << iChIndex; + a++; + } + } + }else{ + for (auto& channel : m_vSpectr){ + matrix += channel; + } + } + + matrix /= m_vSpectr.size(); + + auto tempMat = matrix; + Eigen::MatrixXd mat = tempMat.cwiseAbs2().real(); + variant.setValue(mat); + + qDebug() << "Hi there"; + +// auto tempMat = m_vSpectr[0]; +// Eigen::MatrixXd mat = tempMat.cwiseAbs2(); +// variant.setValue(mat); + return variant; + } + } + } + if(index.column() == 2) { //timefrequencyview + switch(role){ + case Qt::BackgroundRole:{ + return QVariant(); + } + case Qt::DisplayRole:{ + QVariant variant; + + auto tempMat = m_vSpectr[0]; + Eigen::MatrixXd mat = tempMat.cwiseAbs2(); + variant.setValue(mat); + + return variant; + } + } + } + +} + +//============================================================================================================= + +QVariant TimeFrequencyModel::data(int row, int column, int role) const +{ + return data(index(row, column), role); +} + +//============================================================================================================= + +QVariant TimeFrequencyModel::headerData(int section, + Qt::Orientation orientation, + int role) const +{ + return QVariant(); +} + +//============================================================================================================= + +void TimeFrequencyModel::setFiffInfo(const FIFFLIB::FiffInfo &info) +{ + m_Info = info; +} + +//============================================================================================================= + +float TimeFrequencyModel::getSamplingFrequency() +{ + return m_Info.sfreq; +} + +//============================================================================================================= + +void TimeFrequencyModel::setMinFreq(int iFreq) +{ + m_iMinFreq = iFreq; + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); +} + +//============================================================================================================= + +void TimeFrequencyModel::setMaxFreq(int iFreq) +{ + m_iMaxFreq = iFreq; + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); +} + +//============================================================================================================= + +std::pair TimeFrequencyModel::getFreqRange() const +{ + return std::pair(m_iMinFreq,m_iMaxFreq); +} + +//============================================================================================================= + +void TimeFrequencyModel::computeAverage() +{ + +} + +//============================================================================================================= +#include +void TimeFrequencyModel::setChannelSelection(QList selectionList) +{ + m_listSelection.clear(); + for (int i = 0; i< selectionList.size(); i++){ + m_listSelection.append(selectionList.value(i)); + std::cout << selectionList.value(i) << std::endl; + } + + if(m_vSpectr.size() > 0){ + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); + } +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h new file mode 100644 index 00000000000..d4722ff2ed4 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -0,0 +1,183 @@ +//============================================================================================================= +/** + * @file timefrequencymodel.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyModel Class. + * + */ + +#ifndef TIMEFREQUENCYMODEL_H +#define TIMEFREQUENCYMODEL_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel +{ + Q_OBJECT +public: + TimeFrequencyModel(); + + TimeFrequencyModel(std::vector& spectr); + + void setSpectr(std::vector& spectr); + + void setFiffInfo(const FIFFLIB::FiffInfo& info); + + float getSamplingFrequency(); + + void setChannelSelection(QList selectionList); + + void computeAverage(); + + //========================================================================================================= + /** + * Returns the number of rows under the given parent. When the parent is valid it means that rowCount is returning the number of children of parent. + * + * @param[in] parent not used + * + * @return number of rows + */ + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const ; + + //========================================================================================================= + /** + * Returns the number of columns for the children of the given parent. + * + * @param[in] parent not used + * + * @return number of columns + */ + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + //========================================================================================================= + /** + * Returns the data stored under the given role for the item referred to by the index. + * + * @param[in] index determines item location + * @param[in] role role to return + * + * @return accessed data + */ + virtual QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const; + + //========================================================================================================= + /** + * Data for the row and column and given display role + * + * @param [in] row index row + * @param [in] column index column + * @param [in] role display role to access + * + * @return the accessed data + */ + QVariant data(int row, + int column, + int role = Qt::DisplayRole) const; + + //========================================================================================================= + /** + * Returns the data for the given role and section in the header with the specified orientation. + * + * @param[in] section For horizontal headers, the section number corresponds to the column number. Similarly, for vertical headers, the section number corresponds to the row number. + * @param[in] orientation Qt::Horizontal or Qt::Vertical + * @param[in] role role to show + * + * @return accessed eader data + */ + virtual QVariant headerData(int section, + Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + void setMinFreq(int iFreq); + + void setMaxFreq(int iFreq); + + std::pair getFreqRange() const; + + +private: +// QSharedPointer m_pChannelInfoModel; + +// QLinearGradient m_Gradient; + + std::vector m_vSpectr; + std::vector m_vTfData; + + QList m_listSelection; + + Eigen::MatrixXd m_Average; + + FIFFLIB::FiffInfo m_Info; + + int m_iMinFreq; + int m_iMaxFreq; + +}; +}//namespace + +#ifndef metatype_matrixXd +#define metatype_matrixXd +Q_DECLARE_METATYPE(Eigen::MatrixXd); +#endif + +//#ifndef metatype_matrixXcd +//#define metatype_matrixXcd +//Q_DECLARE_METATYPE(Eigen::MatrixXcd); +//#endif + +#endif // TIMEFREQUENCYMODEL_H diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp new file mode 100644 index 00000000000..8cdbd2bcddc --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -0,0 +1,120 @@ +//============================================================================================================= +/** + * @file timefrequencyscene.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencyScene Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencyscene.h" + +#include "timefrequencysceneitem.h" +#include "selectionsceneitem.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyScene::TimeFrequencyScene(QGraphicsView* view, + QObject* parent) +: LayoutScene(view, parent) +{ + +} + +//============================================================================================================= + +void TimeFrequencyScene::repaintItems(const QList &selectedChannelItems) +{ +// this->clear(); + +// QListIterator i(selectedChannelItems); + +// while (i.hasNext()) { +// SelectionSceneItem* selectionSceneItemTemp = static_cast(i.next()); +// TimeFrequencySceneItem* averageSceneItemTemp = new TimeFrequencySceneItem(); + +// this->addItem(averageSceneItemTemp); +// } +} + +//============================================================================================================= + +void TimeFrequencyScene::repaintSelectionItems(const DISPLIB::SelectionItem &selectedChannelItems) +{ + this->clear(); + m_vItems.clear(); + + for (int i = 0; i < selectedChannelItems.m_iChannelKind.size(); i++){ + TimeFrequencySceneItem* averageSceneItemTemp = new TimeFrequencySceneItem(selectedChannelItems.m_sChannelName[i], + selectedChannelItems.m_iChannelNumber[i], + selectedChannelItems.m_qpChannelPosition[i], + selectedChannelItems.m_iChannelKind[i], + selectedChannelItems.m_iChannelUnit[i]); + + /*QGraphicsProxyWidget* pWidget = */this->addItem(averageSceneItemTemp); + + m_vItems.push_back(averageSceneItemTemp); + +// pWidget->setPos(75*selectedChannelItems.m_qpChannelPosition[i].x(), -75*selectedChannelItems.m_qpChannelPosition[i].y()); +// pWidget->resize(200,150); + } +} + +//============================================================================================================= + +void TimeFrequencyScene::updateScene() +{ + this->update(); +} + +//============================================================================================================= + +std::vector TimeFrequencyScene::getItems() const +{ + return m_vItems; +} + + diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h new file mode 100644 index 00000000000..b8bed46aecc --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -0,0 +1,105 @@ +//============================================================================================================= +/** + * @file timefrequencyscene.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyScene Class. + * + */ + +#ifndef TIMEFREQUENCYSCENE_H +#define TIMEFREQUENCYSCENE_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include "layoutscene.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class SelectionSceneItem; +class SelectionItem; +class TimeFrequencySceneItem; + +class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene +{ + Q_OBJECT +public: + //========================================================================================================= + TimeFrequencyScene(QGraphicsView* view, + QObject *parent = 0); + + //========================================================================================================= + /** + * Repaints all items from the layout data in the scene. + * + * @param [in] selectedChannelItems items which are to painted to the average scene + */ + void repaintItems(const QList &selectedChannelItems); + + //========================================================================================================= + /** + * Repaints all items from the layout data in the scene from a SelectionItem object + * + * @param [in] selectedChannelItems data about items which are to be painted + */ + void repaintSelectionItems(const DISPLIB::SelectionItem &selectedChannelItems); + + //========================================================================================================= + /** + * Updates and repaints the scene + */ + void updateScene(); + + std::vector getItems() const; + +private: + std::vector m_vItems; +}; +}//namespace +#endif // TIMEFREQUENCYSCENE_H diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp new file mode 100644 index 00000000000..d35cae07730 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -0,0 +1,176 @@ +//============================================================================================================= +/** + * @file timefrequencysceneitem.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencySceneItem Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencysceneitem.h" +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencySceneItem::TimeFrequencySceneItem(const QString& channelName, + int channelNumber, + const QPointF& channelPosition, + int channelKind, + int channelUnit) +: m_sChannelName(channelName) +, m_iChannelNumber(channelNumber) +, m_iChannelKind(channelKind) +, m_iChannelUnit(channelUnit) +, m_iTotalNumberChannels(0) +, m_iFontTextSize(15) +, m_iMaxWidth(1500) +, m_iMaxHeigth(150) +, m_bIsBad(false) +, m_qpChannelPosition(channelPosition) +, m_pPlot(Q_NULLPTR) +{ + //initQMLView(); + +// m_rectBoundingRect = QRectF(-m_iMaxWidth/2, -m_iMaxHeigth/2, m_iMaxWidth, m_iMaxHeigth); +// QLabel* widget = new QLabel("Test"); + +// m_pLayout = new QVBoxLayout(); +//// m_pLayout->addWidget(widget); +// this->setLayout(m_pLayout); + + m_rectBoundingRect = QRectF(-m_iMaxWidth/2, -m_iMaxHeigth/2, m_iMaxWidth, m_iMaxHeigth); + + this->setPos(75*m_qpChannelPosition.x(), -75*m_qpChannelPosition.y()); +} + +//============================================================================================================= + +void TimeFrequencySceneItem::initQMLView() +{ +// QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); +// QQuickWidget* widget = new QQuickWidget(); +// widget->setSource(source); +// widget->setResizeMode(QQuickWidget::SizeRootObjectToView); + +// QLabel* widget = new QLabel("Test"); + +// QVBoxLayout* layout = new QVBoxLayout(); +// layout->addWidget(widget); + + +// this->setLayout(layout); +} + +//============================================================================================================= + +int TimeFrequencySceneItem::getChannelNumber() const +{ + return m_iChannelNumber; +} + +//============================================================================================================= + +void TimeFrequencySceneItem::setData(const Eigen::MatrixXd &data) +{ + m_data = data; + +// if(!m_pLayout->isEmpty()){ +// m_pLayout->removeWidget(m_pPlot); +// m_pPlot->deleteLater(); +// } + + //std::cout << data; + +// m_pPlot = new TFplot(m_data, m_fSampleRate, 0, 100, DISPLIB::ColorMaps::Jet); +// m_pPlot->show(); + + paintPlot(); + +// m_pLayout->addWidget(m_pPlot); + +// m_pLayout->addWidget(m_pPlot); +// this->setLayout(m_pLayout); + + +} + +//============================================================================================================= + +void TimeFrequencySceneItem::setSampleRate(float fFreq) +{ + m_fSampleRate = fFreq; + //qDebug() << "freq:" << fFreq; +} + +//============================================================================================================= + +QRectF TimeFrequencySceneItem::boundingRect() const +{ + return m_rectBoundingRect; +} + +void TimeFrequencySceneItem::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + Q_UNUSED(painter); +} + +//============================================================================================================= + +void TimeFrequencySceneItem::paintPlot() +{ + QGraphicsSimpleTextItem* item = new QGraphicsSimpleTextItem("TEST", this); + item->setPos(0,0); + item->show(); +} diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h new file mode 100644 index 00000000000..8d3d1289987 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -0,0 +1,118 @@ +//============================================================================================================= +/** + * @file timefrequencysceneitem.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencySceneItem Class. + * + */ + +#ifndef TIMEFREQUENCYSCENEITEM_H +#define TIMEFREQUENCYSCENEITEM_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +class DISPSHARED_EXPORT TimeFrequencySceneItem : public QGraphicsObject +{ + Q_OBJECT +public: + TimeFrequencySceneItem(const QString& channelName, + int channelNumber, + const QPointF& channelPosition, + int channelKind, + int channelUnit); + + void setData(const Eigen::MatrixXd& data); + + void setSampleRate(float fFreq); + + int getChannelNumber() const; + + QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +protected: + void initQMLView(); + + void paintPlot(); + +private: + + QString m_sChannelName; /**< The channel name.*/ + int m_iChannelNumber; /**< The channel number.*/ + int m_iChannelKind; /**< The channel kind.*/ + int m_iChannelUnit; /**< The channel unit.*/ + int m_iTotalNumberChannels; /**< The total number of channels loaded in the curent evoked data set.*/ + int m_iFontTextSize; /**< The font text size of the electrode names.*/ + int m_iMaxWidth; /**< The max width. */ + int m_iMaxHeigth; /**< The max heigth. */ + + bool m_bIsBad; /**< Whether this channel is bad. */ + + QPointF m_qpChannelPosition; /**< The channels 2D position in the scene.*/ + + Eigen::MatrixXd m_data; + float m_fSampleRate; + QRectF m_rectBoundingRect; /**< The bounding rect. */ + + QPointer m_pLayout; + + QPointer m_pPlot; + +}; +}//namespace +#endif // TIMEFREQUENCYSCENEITEM_H diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp new file mode 100644 index 00000000000..a328a01ce0d --- /dev/null +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -0,0 +1,198 @@ +//============================================================================================================= +/** + * @file timefrequencylaoutview.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyLayoutView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencylayoutview.h" + +#include "helpers/timefrequencyscene.h" +#include "helpers/timefrequencysceneitem.h" +#include "helpers/selectionsceneitem.h" +#include "helpers/timefrequencymodel.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#if !defined(NO_QOPENGLWIDGET) + #include +#endif + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyLayoutView::TimeFrequencyLayoutView() +: TimeFrequencyLayoutView("", Q_NULLPTR) +{ + +} + +//============================================================================================================= + + +TimeFrequencyLayoutView::TimeFrequencyLayoutView(const QString& sSettingsPath, + QWidget *parent, + Qt::WindowFlags f) +: AbstractView(parent, f) +{ + m_sSettingsPath = sSettingsPath; + this->setWindowTitle("Time-Frequency Layout"); + + m_pTimeFreqGraphicsView = new QGraphicsView(); + +#if !defined(NO_QOPENGLWIDGET) + m_pTimeFreqGraphicsView->setViewport(new QOpenGLWidget); +#endif + + m_pTimeFreqGraphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_pTimeFreqGraphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_pTimeFreqScene = new TimeFrequencyScene(m_pTimeFreqGraphicsView, this); + m_pTimeFreqScene->setBackgroundBrush(QBrush(Qt::white)); + + m_pTimeFreqGraphicsView->setScene(m_pTimeFreqScene); + + QVBoxLayout *neLayout = new QVBoxLayout(this); + neLayout->setContentsMargins(0,0,0,0); + neLayout->addWidget(m_pTimeFreqGraphicsView); + this->setLayout(neLayout); +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + break; + default: // default is realtime mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::saveSettings() +{ + +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::loadSettings() +{ + +} + + +//============================================================================================================= + +void TimeFrequencyLayoutView::clearView() +{ + +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::channelSelectionChanged(const QVariant &data) +{ + if(!m_pTimeFreqScene) { + qDebug() << "AverageLayoutView::channelSelectionManagerChanged - m_pAverageScene is NULL. Returning. "; + return; + } + +// if (m_listWidgets.empty()){ + +// } + + SelectionItem* pSelectionItem = data.value(); + + //Repaint the average items in the average scene based on the input parameter selectedChannelItems and update them with current data + m_pTimeFreqScene->repaintSelectionItems(*pSelectionItem); +// updateData(); +} +//============================================================================================================= + +void TimeFrequencyLayoutView::updateData() +{ + if(m_pTFModel){ + auto sceneItems = m_pTimeFreqScene->getItems(); + + for (auto item : sceneItems){ + item->setSampleRate(m_pTFModel->getSamplingFrequency()); +// item->setData(m_pTFModel->data(item->getChannelNumber(), 2).value()); +// qDebug() << "ch num:" << item->getChannelNumber(); + } + qDebug() << "vec size:" << sceneItems.size(); + sceneItems.front()->setData(m_pTFModel->data(sceneItems.front()->getChannelNumber(), 2).value()); + +// DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(m_pTFModel->data(1,2).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot->show(); + m_pTimeFreqScene->updateScene(); + } +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::setTimeFrequencyModel(QSharedPointer pModel) +{ + if(pModel){ + m_pTFModel = pModel; + connect(m_pTFModel.data(), &TimeFrequencyModel::dataChanged, + this, &TimeFrequencyLayoutView::updateData, Qt::UniqueConnection); + } +} diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h new file mode 100644 index 00000000000..affa688facf --- /dev/null +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -0,0 +1,146 @@ +//============================================================================================================= +/** + * @file timefrequencylayoutview.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyLayoutView Class. + * + */ + +#ifndef TIMEFREQUENCYLAYOUTVIEW_H +#define TIMEFREQUENCYLAYOUTVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +class EvokedSetModel; +class TimeFrequencyScene; +class TimeFrequencyModel; + +//============================================================================================================= +class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView +{ + Q_OBJECT +public: + TimeFrequencyLayoutView(); + + TimeFrequencyLayoutView(const QString& sSettingsPath, + QWidget* parent, + Qt::WindowFlags f = Qt::Widget); + + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Sets the currently viewable channels using the corrent name and location parameters + * + * @param [in] data QVariant containing a SelectionItem object with selected channel information + */ + void channelSelectionChanged(const QVariant &data); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); + + void setTimeFrequencyModel(QSharedPointer pModel); + +protected: + + //========================================================================================================= + /** + * call this function whenever the items' data needs to be updated + */ + void updateData(); + + QPointer m_pTimeFreqScene; + QPointer m_pTimeFreqGraphicsView; + + QSharedPointer m_pEvokedSetModel; /**< The evoked model */ + QSharedPointer m_pTFModel; + + std::list m_listWidgets(); + +}; +}//namespace + +#endif // TIMEFREQUENCYLAYOUTVIEW_H diff --git a/libraries/disp/viewers/timefrequencysettingsview.cpp b/libraries/disp/viewers/timefrequencysettingsview.cpp new file mode 100644 index 00000000000..b88a6dff450 --- /dev/null +++ b/libraries/disp/viewers/timefrequencysettingsview.cpp @@ -0,0 +1,147 @@ +//============================================================================================================= +/** + * @file timefrequencysettingsview.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencySettingsWidget Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencysettingsview.h" + +#include "ui_timefrequencysettingsview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencySettingsView::TimeFrequencySettingsView(const QString& sSettingsPath, + QWidget *parent) +: AbstractView(parent) +, m_pUi(new Ui::TimeFrequencySettingsWidget) +{ + + m_sSettingsPath = sSettingsPath; + m_pUi->setupUi(this); + + this->setWindowTitle("Time-Frequency Settings"); + this->setMinimumWidth(330); + + initGUI(); +} + +//============================================================================================================= + +void TimeFrequencySettingsView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencySettingsView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + + break; + default: // default is realtime mode + + break; + } +} + +//============================================================================================================= + +void TimeFrequencySettingsView::saveSettings() +{ + if(m_sSettingsPath.isEmpty()) { + return; + } + +} + +//============================================================================================================= + +void TimeFrequencySettingsView::loadSettings() +{ + if(m_sSettingsPath.isEmpty()) { + return; + } +} + +//============================================================================================================= + +void TimeFrequencySettingsView::clearView() +{ + +} + +//============================================================================================================= + +void TimeFrequencySettingsView::initGUI() +{ + //Freq + connect(m_pUi->spinBox_minFreq, QOverload::of(&QSpinBox::valueChanged), + this, &TimeFrequencySettingsView::minFreqChanged, Qt::UniqueConnection); + connect(m_pUi->spinBox_maxFreq, QOverload::of(&QSpinBox::valueChanged), + this, &TimeFrequencySettingsView::maxFreqChanged, Qt::UniqueConnection); + + //Color map + + connect(m_pUi->comboBox_colorMap, &QComboBox::currentTextChanged, + this, &TimeFrequencySettingsView::colorMapChanged, Qt::UniqueConnection); + + //Compute + + connect(m_pUi->pushButton_ciompute, &QPushButton::released, + this, &TimeFrequencySettingsView::computePushed, Qt::UniqueConnection); + + + connect(m_pUi->radioButton_avg, &QRadioButton::toggled, + this, &TimeFrequencySettingsView::computeWithAvg, Qt::UniqueConnection); +} diff --git a/libraries/disp/viewers/timefrequencysettingsview.h b/libraries/disp/viewers/timefrequencysettingsview.h new file mode 100644 index 00000000000..8cce1cf9ffa --- /dev/null +++ b/libraries/disp/viewers/timefrequencysettingsview.h @@ -0,0 +1,126 @@ +//============================================================================================================= +/** + * @file timefrequencysettingsview.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencySettingsWidget Class. + * + */ + +#ifndef TIMEFREQUENCYSETTINGSVIEW_H +#define TIMEFREQUENCYSETTINGSVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace Ui { + class TimeFrequencySettingsWidget; +} + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +class DISPSHARED_EXPORT TimeFrequencySettingsView : public AbstractView +{ + Q_OBJECT +public: + TimeFrequencySettingsView(const QString& sSettingsPath = "", + QWidget *parent = Q_NULLPTR); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); + +signals: + void minFreqChanged(int iMinFreq); + + void maxFreqChanged(int iMaxFreq); + + void computePushed(); + + void colorMapChanged(const QString &colormap); + + void computeWithAvg(bool checked); + +protected: + + void initGUI(); + + Ui::TimeFrequencySettingsWidget* m_pUi; /**< Holds the user interface for the AverageSettingsViewWidget.*/ + + +}; +}//namespace +#endif // TIMEFREQUENCYSETTINGSVIEW_H diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp new file mode 100644 index 00000000000..01e80926ae0 --- /dev/null +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -0,0 +1,433 @@ +//============================================================================================================= +/** + * @file timefrequencyview.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencyView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencyview.h" + +#include "helpers/evokedsetmodel.h" +#include "helpers/timefrequencymodel.h" +#include "helpers/timefrequencymodel.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyView::TimeFrequencyView() +: TimeFrequencyView("", Q_NULLPTR) +{ + m_pLayout = new QVBoxLayout(); + this->setLayout(m_pLayout); +} + +//============================================================================================================= + +TimeFrequencyView::TimeFrequencyView(const QString& sSettingsPath, + QWidget *parent, + Qt::WindowFlags f) +: AbstractView(parent, f) +, m_iChartBorderSpacing(30) +{ + m_sSettingsPath = sSettingsPath; + //initQMLView(); +} + +//============================================================================================================= + +void TimeFrequencyView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + break; + default: // default is realtime mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyView::saveSettings() +{ + +} + +//============================================================================================================= + +void TimeFrequencyView::loadSettings() +{ + +} + + +//============================================================================================================= + +void TimeFrequencyView::clearView() +{ + +} + +//============================================================================================================= + +void TimeFrequencyView::initQMLView() +{ +// QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); +// QQuickWidget* widget = new QQuickWidget(); +// widget->setSource(source); +// widget->setResizeMode(QQuickWidget::SizeRootObjectToView); + +// QVBoxLayout* layout = new QVBoxLayout(); +// layout->addWidget(widget); + + +// this->setLayout(layout); +} + +//============================================================================================================= + +void TimeFrequencyView::paintEvent(QPaintEvent *event) +{ +// if (m_pEvokedSetModel){ + QPainter painter(this); + + painter.save(); + painter.setBrush(QBrush()); + painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); + painter.restore(); + + //paint chart + painter.save(); + painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); + QRect chartBound(m_iChartBorderSpacing,m_iChartBorderSpacing,this->width()-m_iChartBorderSpacing * 4 ,this->height()- m_iChartBorderSpacing * 2); + painter.drawRect(chartBound); + painter.restore(); + + painter.save(); + painter.drawPixmap(chartBound, m_PlotPixmap); + + painter.restore(); + + //paint gradient bar + +// painter.save(); +// painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); +// QRect gradientBar(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); +// painter.drawRect(gradientBar); +// painter.restore(); + +// painter.save(); +// painter.drawPixmap(gradientBar, m_CoefficientPixmap); +// painter.restore(); + + painter.save(); + + painter.drawPixmap(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height(), m_CoefficientPixmap); + + painter.restore(); + +// QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); +// painter.save(); +// painter.setBrush(linGrad); +// painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); + + + +// //paint axis labels +// //test +// if(m_pEvokedSetModel->getNumSamples() > 0) { +// painter.save(); +// painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); + +// float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); +// float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); +// painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); + +// painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); + +// painter.restore(); + +// painter.save(); +// QColor colorTimeSpacer = Qt::black; +// colorTimeSpacer.setAlphaF(0.5); +// painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); + +// float yStart = chartBound.topLeft().y(); +// float yEnd = chartBound.bottomRight().y(); + +// float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); +// int counter = 1; +// float timeDistanceMSec = 50.0; +// float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency + +// //spacers before stim +// while(sampleCounter-timeDistanceSamples>0) { +// sampleCounter-=timeDistanceSamples; +// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; +// painter.drawLine(x, yStart, x, yEnd); +// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); +// counter++; +// } + +// //spacers after stim +// counter = 1; +// sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); +// while(sampleCounter+timeDistanceSamplesgetNumSamples()) { +// sampleCounter+=timeDistanceSamples; +// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; +// painter.drawLine(x, yStart, x, yEnd); +// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); +// counter++; +// } + +// painter.restore(); + +// } + +// } + + return QWidget::paintEvent(event); +} + +//============================================================================================================= + +void TimeFrequencyView::setEvokedSetModel(QSharedPointer model) +{ + m_pEvokedSetModel = model; + +// connect(m_pEvokedSetModel.data(), &EvokedSetModel::dataChanged, +// this, &ButterflyView::dataUpdate, Qt::UniqueConnection); +} + +//============================================================================================================= + +//void TimeFrequencyView::paintChart(QPainter& painter, +// const QRect chartBound) +//{ + +//} + +////============================================================================================================= + +//void TimeFrequencyView::paintAxes(QPainter& painter, +// const QRect chartBound) +//{ + +//} + +//============================================================================================================= + +void TimeFrequencyView::setTimeFrequencyModel(QSharedPointer pModel) +{ + qDebug() << "[TimeFrequencyView::setTimeFrequencyModel]"; + + m_pTFModel = pModel; + + if(pModel){ + m_pTFModel = pModel; + connect(m_pTFModel.data(), &TimeFrequencyModel::dataChanged, + this, &TimeFrequencyView::updateData, Qt::UniqueConnection); + } + +// DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); + +// tfplot->show(); +} + +//============================================================================================================= + +void TimeFrequencyView::updateData() +{ + if(!m_pTFModel){ + return; + } + +// if(!m_pLayout->isEmpty()){ +// m_pPlot->hide(); +// m_pLayout->removeWidget(m_pPlot); +// delete m_pPlot; +// } + + auto freqRange = m_pTFModel->getFreqRange(); + +// m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), freqRange.first, freqRange.second, DISPLIB::ColorMaps::Jet); +// m_pLayout->addWidget(m_pPlot); + +// //m_pPlot->adjustSize(); +// m_pPlot->adjustViewSize(); + + auto data = m_pTFModel->data(1,1); + if (!data.isNull()) { + Eigen::MatrixXd tf_matrix = data.value(); + qreal sample_rate = m_pTFModel->getSamplingFrequency(); + qreal lower_frq = freqRange.first; + qreal upper_frq = freqRange.second; + ColorMaps cmap = DISPLIB::ColorMaps::Jet; + + qreal max_frq = sample_rate/2.0; + qreal frq_per_px = max_frq/tf_matrix.rows(); + + if(upper_frq > max_frq || upper_frq <= 0) upper_frq = max_frq; + if(lower_frq < 0 || lower_frq >= max_frq) lower_frq = 0; + if(upper_frq < lower_frq) { + qreal temp = upper_frq; + upper_frq = lower_frq; + lower_frq = temp; + } + + qint32 lower_px = floor(lower_frq / frq_per_px); + qint32 upper_px = floor(upper_frq / frq_per_px); + + Eigen::MatrixXd zoomed_tf_matrix = Eigen::MatrixXd::Zero(upper_px-lower_px, tf_matrix.cols()); + + qint32 pxls = 0; + for(qint32 it = lower_px; it < upper_px; it++) { + zoomed_tf_matrix.row(pxls) = tf_matrix.row(it); + pxls++; + } + + generatePixmap(zoomed_tf_matrix, cmap); + } + + repaint(); +} + +//============================================================================================================= + +void TimeFrequencyView::generatePixmap(Eigen::MatrixXd tf_matrix, + ColorMaps cmap) +{ + + qreal norm1 = tf_matrix.maxCoeff(); + qreal mnorm = tf_matrix.minCoeff(); + if(std::fabs(mnorm) > norm1) norm1 = mnorm; + tf_matrix /= norm1; + + QImage * image_to_tf_plot = new QImage(tf_matrix.cols(), tf_matrix.rows(), QImage::Format_RGB32); + + //setup pixelcolors in image + QColor color; + for ( qint32 y = 0; y < tf_matrix.rows(); y++ ) { + for ( qint32 x = 0; x < tf_matrix.cols(); x++ ) { + switch (cmap) { + case Jet: + color.setRgb(ColorMap::valueToJet(std::fabs(tf_matrix(y, x)))); + break; + case Hot: + color.setRgb(ColorMap::valueToHot(std::fabs(tf_matrix(y, x)))); + break; + case HotNeg1: + color.setRgb(ColorMap::valueToHotNegative1(std::fabs(tf_matrix(y, x)))); + break; + case HotNeg2: + color.setRgb(ColorMap::valueToHotNegative2(std::fabs(tf_matrix(y, x)))); + break; + case Bone: + color.setRgb(ColorMap::valueToBone(std::fabs(tf_matrix(y, x)))); + break; + case RedBlue: + color.setRgb(ColorMap::valueToRedBlue(std::fabs(tf_matrix(y, x)))); + break; + } + image_to_tf_plot->setPixel(x, tf_matrix.rows() - 1 - y, color.rgb()); + } + } + + *image_to_tf_plot = image_to_tf_plot->scaled(tf_matrix.cols(), tf_matrix.cols()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + *image_to_tf_plot = image_to_tf_plot->scaledToWidth(/*0.9 **/ 1026, Qt::SmoothTransformation); + + m_PlotPixmap = QPixmap::fromImage(*image_to_tf_plot); + + QImage * coeffs_image = new QImage(10, tf_matrix.rows(), QImage::Format_RGB32); + qreal norm = tf_matrix.maxCoeff(); + for(qint32 it = 0; it < tf_matrix.rows(); it++) { + for ( qint32 x = 0; x < 10; x++ ) { + switch (cmap) { + case Jet: + color.setRgb(ColorMap::valueToJet(it*norm/tf_matrix.rows())); + break; + case Hot: + color.setRgb(ColorMap::valueToHot(it*norm/tf_matrix.rows())); + break; + case HotNeg1: + color.setRgb(ColorMap::valueToHotNegative1(it*norm/tf_matrix.rows())); + break; + case HotNeg2: + color.setRgb(ColorMap::valueToHotNegative2(it*norm/tf_matrix.rows())); + break; + case Bone: + color.setRgb(ColorMap::valueToBone(it*norm/tf_matrix.rows())); + break; + case RedBlue: + color.setRgb(ColorMap::valueToRedBlue(it*norm/tf_matrix.rows())); + break; + } + coeffs_image->setPixel(x, tf_matrix.rows() - 1 - it, color.rgb()); + } + } + + *coeffs_image = coeffs_image->scaled(10, tf_matrix.cols()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + *coeffs_image = coeffs_image->scaledToHeight(image_to_tf_plot->height(), Qt::SmoothTransformation); + + m_CoefficientPixmap = QPixmap::fromImage(*coeffs_image); +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h new file mode 100644 index 00000000000..c3b90fa053c --- /dev/null +++ b/libraries/disp/viewers/timefrequencyview.h @@ -0,0 +1,177 @@ +//============================================================================================================= +/** + * @file timefrequencyview.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyView Class. + * + */ + +#ifndef TIMEFREQUENCYVIEW_H +#define TIMEFREQUENCYVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +class EvokedSetModel; +class TimeFrequencyModel; + +//============================================================================================================= +/** + * @brief The TimeFrequencyView class + */ +class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView +{ + Q_OBJECT +public: + //========================================================================================================= + TimeFrequencyView(); + + //========================================================================================================= + TimeFrequencyView(const QString& sSettingsPath, + QWidget* parent, + Qt::WindowFlags f = Qt::Widget); + + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param[in] mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param[in] mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); + + //========================================================================================================= + /** + * Set the evoked set model. + * + * @param[in] model The new evoked set model. + */ + void setEvokedSetModel(QSharedPointer model); + + //========================================================================================================= + /** + * Sets spacing for time frequency chart + * + * @param[in] iSpacing Spacing value in pixels + */ + void setChartBorderSpacing(int iSpacing); + + void setTimeFrequencyModel(QSharedPointer pModel); + + void setSelectedChannels(QList selectionList); + + +protected: + void initQMLView(); + + virtual void paintEvent(QPaintEvent *event); + +// void paintChart(QPainter& painter, +// const QRect chartBound); + +// void paintAxes(QPainter& painter, +// const QRect chartBound); + + void generatePixmap(Eigen::MatrixXd tf_matrix, + ColorMaps cmap); + + //========================================================================================================= + /** + * call this function whenever the items' data needs to be updated + */ + void updateData(); + + QSharedPointer m_pEvokedSetModel; /**< The evoked model */ + int m_iChartBorderSpacing; + QSharedPointer m_pTFModel; + + QPointer m_pLayout; + QPointer m_pPlot; + + QPixmap m_PlotPixmap; + + QPixmap m_CoefficientPixmap; + +}; + +} //namespace +#endif // TIMEFREQUENCYVIEW_H diff --git a/libraries/libraries.pro b/libraries/libraries.pro index 9dbfedb00bb..f701d264230 100644 --- a/libraries/libraries.pro +++ b/libraries/libraries.pro @@ -51,6 +51,7 @@ SUBDIRS += \ rtprocessing \ connectivity \ disp \ + timefrequency \ qtHaveModule(charts) { # The Qt3D module is not yet Wasm supported diff --git a/libraries/rtprocessing/rtprocessing.pro b/libraries/rtprocessing/rtprocessing.pro index 9dae3b7da9b..2d13fed3377 100644 --- a/libraries/rtprocessing/rtprocessing.pro +++ b/libraries/rtprocessing/rtprocessing.pro @@ -36,7 +36,7 @@ include(../../mne-cpp.pri) TEMPLATE = lib - +DEFINES += TRACE CONFIG += skip_target_version_ext QT += network concurrent @@ -88,12 +88,14 @@ SOURCES += \ rthpis.cpp \ filter.cpp \ rtconnectivity.cpp \ + rttimefrequency.cpp \ sphara.cpp \ detecttrigger.cpp \ helpers/cosinefilter.cpp \ helpers/parksmcclellan.cpp \ helpers/filterkernel.cpp \ helpers/filterio.cpp \ + timefrequency.cpp HEADERS += \ icp.h \ @@ -106,12 +108,14 @@ HEADERS += \ rthpis.h \ filter.h \ detecttrigger.h \ + rttimefrequency.h \ sphara.h \ rtconnectivity.h \ helpers/cosinefilter.h \ helpers/parksmcclellan.h \ helpers/filterkernel.h \ helpers/filterio.h \ + timefrequency.h INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} diff --git a/libraries/rtprocessing/rttimefrequency.cpp b/libraries/rtprocessing/rttimefrequency.cpp new file mode 100644 index 00000000000..927bbdb15b9 --- /dev/null +++ b/libraries/rtprocessing/rttimefrequency.cpp @@ -0,0 +1,8 @@ +#include "rttimefrequency.h" + +using namespace RTPROCESSINGLIB; + +RtTimeFrequency::RtTimeFrequency() +{ + +} diff --git a/libraries/rtprocessing/rttimefrequency.h b/libraries/rtprocessing/rttimefrequency.h new file mode 100644 index 00000000000..125a784dd66 --- /dev/null +++ b/libraries/rtprocessing/rttimefrequency.h @@ -0,0 +1,48 @@ +#ifndef RTTIMEFREQUENCY_H +#define RTTIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "rtprocessing_global.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +// DEFINE NAMESPACE RTPROCESSINGLIB +//============================================================================================================= + +namespace RTPROCESSINGLIB +{ + +//============================================================================================================= +// RTPROCESSINGLIB FORWARD DECLARATIONS +//============================================================================================================= + + +class RtTimeFrequency : public QObject +{ +public: + RtTimeFrequency(); +}; +}//namespace +#endif // RTTIMEFREQUENCY_H diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp new file mode 100644 index 00000000000..5a4acf52f4f --- /dev/null +++ b/libraries/rtprocessing/timefrequency.cpp @@ -0,0 +1,231 @@ +//============================================================================================================= +/** + * @file timefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of TimeFrequency functions + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency.h" + +#include + +#include +#include + +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace RTPROCESSINGLIB; + +//============================================================================================================= +// DEFINE STATIC RTPROCESSINGLIB METHODS +//============================================================================================================= + +std::vector TimeFrequencyData::computeEpochListTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +{ + qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; + + int a = 0; + qDebug() << a; + + std::cout << "SIZE:" << evokedSet.evoked.size(); + + auto& evoked = evokedSet.evoked.first(); + float fSampFreq = evoked.info.sfreq; + + std::cout << "ROWS: " << evoked.data.rows(); + + std::vector tfvector; + + for (int i = 0; i < evoked.data.rows(); i++){ + Eigen::VectorXd dataCol = evoked.data.row(i).transpose(); + //std::cout << "First data sample from evoked: " << dataCol(0); + Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, fSampFreq * 0.2); + tfvector.push_back(Spectrum); + } + + return tfvector; +} + +//============================================================================================================= + +std::vector TimeFrequencyData::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +{ + qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; + + auto& evoked = evokedSet.evoked.first(); + float fSampFreq = evoked.info.sfreq; + + std::vector tfvector; + + for (int i = 0; i < evoked.data.rows(); i++){ + Eigen::VectorXd dataCol = evoked.data.row(i).transpose(); + Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeComplexSpectrogram(dataCol, fSampFreq * 0.2); + tfvector.push_back(Spectrum); + } + + return tfvector; +} + +//============================================================================================================= + +std::vector> TimeFrequencyData::computeEpochListTimeFrequency(const FIFFLIB::FiffRawData &raw, + const Eigen::MatrixXi &matEvents, + float fTMinS, + float fTMaxS) +{ + QMap mapReject; + mapReject.insert("eog", 300e-06); + int iType = 1; + + std::vector > epochTimeFrequencyList; //list of epochs x channels x tf + + MNELIB::MNEEpochDataList epochDataList = MNELIB::MNEEpochDataList::readEpochs(raw, + matEvents, + fTMinS, + fTMaxS, + iType, + mapReject); + + for(QSharedPointer& epoch : epochDataList){ + epochTimeFrequencyList.emplace_back(computeEpochTimeFrequency(epoch, + raw.info.sfreq)); + } + + return epochTimeFrequencyList; +} + +//============================================================================================================= + + +std::vector TimeFrequencyData::computeEpochTimeFrequency(const QSharedPointer& epoch, + float sampleFrequency) +{ + int numChannels(epoch->epoch.rows()); + + std::vector channelTimeFrequencyList; + + for(int channeli = 0; channeli < numChannels; channeli++){ + channelTimeFrequencyList.push_back(Eigen::MatrixXcd::Zero(10,10)); +// channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeComplexSpectrogram(epoch->epoch.row(channeli).transpose(), 200)); +// channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeSpectrogram(epoch->epoch.row(channeli).transpose(),0)); + } + + return channelTimeFrequencyList; +} + + + +//============================================================================================================= + +Eigen::MatrixXcd TimeFrequencyData::averageEpochTimeFrequency(const std::vector& epochTimeFrequency) +{ + if (epochTimeFrequency.empty()){ + return Eigen::MatrixXcd(); + } + + Eigen::MatrixXcd averageTimeFrequency(epochTimeFrequency.front().rows(), epochTimeFrequency.front().cols()); + + for(auto channelTimeFreq : epochTimeFrequency){ + averageTimeFrequency += channelTimeFreq; + } + + return averageTimeFrequency / epochTimeFrequency.size(); +} + +//============================================================================================================= + +std::vector TimeFrequencyData::averageEpochListTimeFrequency(const std::vector >& epochListTimeFrequency) +{ + int numFreqs(epochListTimeFrequency.front().front().rows()); + int numSamples(epochListTimeFrequency.front().front().cols()); + + int numEpochs(epochListTimeFrequency.size()); + + if (numSamples ==0 || numFreqs == 0 || numEpochs == 0){ + return std::vector(); + } + + int numChannelsInEpoch(epochListTimeFrequency.front().size()); + + for (int epochindex(1) ; epochindex < epochListTimeFrequency.size(); epochindex++){ + if (static_cast(epochListTimeFrequency[epochindex].size()) != numChannelsInEpoch){ + qDebug() << "Channel number does not match across epoch" << epochindex; + return std::vector(); + } + } + + std::vector averagedEpochListTimeFrequency; + Eigen::MatrixXcd auxMatrix; + + for (int iChannel = 0; iChannel < numChannelsInEpoch; iChannel++){ + auxMatrix = Eigen::MatrixXcd::Zero(numFreqs, numSamples); + for (auto epoch : epochListTimeFrequency){ + auxMatrix += epoch[iChannel]; + } + auxMatrix /= numEpochs; + averagedEpochListTimeFrequency.push_back(auxMatrix); + } + + return averagedEpochListTimeFrequency; +} + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyData::TimeFrequencyData() +{ + +} + +//============================================================================================================= + +TimeFrequencyData::TimeFrequencyData(Eigen::MatrixXcd mat) +{ + this->m_TFData = mat; +} diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h new file mode 100644 index 00000000000..f7b4d62271f --- /dev/null +++ b/libraries/rtprocessing/timefrequency.h @@ -0,0 +1,132 @@ +//============================================================================================================= +/** + * @file timefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of TimeFrequency functions + * + */ + +#ifndef TIMEFREQUENCY_RTPROCESSING_H +#define TIMEFREQUENCY_RTPROCESSING_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "rtprocessing_global.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace FIFFLIB { + class FiffRawData; + class FiffEvokedSet; +} + +namespace MNELIB { + class MNEEpochData; +} + +//============================================================================================================= +// DEFINE NAMESPACE RTPROCESSINGLIB +//============================================================================================================= + +namespace RTPROCESSINGLIB +{ + +class RTPROCESINGSHARED_EXPORT TimeFrequencyData +{ +public: + TimeFrequencyData(); + + TimeFrequencyData(Eigen::MatrixXcd mat); + + static std::vector computeEpochListTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + + static std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + + static std::vector > computeEpochListTimeFrequency(const FIFFLIB::FiffRawData& raw, + const Eigen::MatrixXi& matEvents, + float fTMinS, + float fTMaxS); + + static std::vector computeEpochTimeFrequency(const QSharedPointer& epoch, + float sampleFrequency); + + static Eigen::MatrixXcd averageEpochTimeFrequency(const std::vector& epochTimeFrequency); + + static std::vector averageEpochListTimeFrequency(const std::vector >& epochListTimeFrequency); + + + + Eigen::MatrixXcd getData(); + + TimeFrequencyData& operator=(const Eigen::MatrixXcd& mat) + { + this->m_TFData = mat; + return *this; + } + + TimeFrequencyData& operator+=(const Eigen::MatrixXcd& mat) + { + this->m_TFData += mat; + return *this; + } + + TimeFrequencyData& operator/=(int i) + { + this->m_TFData /= i; + return *this; + } + +private: + + void setTFData(Eigen::MatrixXcd matData); + + Eigen::MatrixXcd m_TFData; +}; + + +}//namespace +#endif // TIMEFREQUENCY_RTPROCESSING_H diff --git a/libraries/timefrequency/include/fftw.h b/libraries/timefrequency/include/fftw.h new file mode 100644 index 00000000000..307f76ecb48 --- /dev/null +++ b/libraries/timefrequency/include/fftw.h @@ -0,0 +1,27 @@ +#pragma once +#include + +#pragma comment(lib, "libfftw3f-3.lib") + +// FFTW MINIMAL INTERFACE +extern "C" +{ + extern void* fftwf_malloc(unsigned long long size); + extern void fftwf_free(void* p); + extern void* fftwf_plan_dft_1d(int size, std::complex* in, std::complex* out, int sign, unsigned flags); + extern void* fftwf_plan_dft_r2c_1d(int size, float* in, std::complex* out, unsigned flags); + extern void* fftwf_plan_dft_c2r_1d(int size, std::complex* in, float* out, unsigned flags); + extern void* fftwf_plan_dft_2d(int n0, int n1, std::complex* in, std::complex* out, int sign, unsigned flags); + + extern void fftwf_execute(void* p); + extern void fftwf_execute_dft(void* p, std::complex* in, std::complex* out); + extern void fftwf_execute_dft_r2c(void* p, float* in, std::complex* out); + extern void fftwf_execute_dft_c2r(void* p, std::complex* in, float* out); + extern void fftwf_destroy_plan(void* p); + + +#define FFTW_FORWARD (-1) +#define FFTW_BACKWARD (+1) +#define FFTW_ESTIMATE (1U << 6) +} + diff --git a/libraries/timefrequency/interface.cpp b/libraries/timefrequency/interface.cpp new file mode 100644 index 00000000000..0602746f19f --- /dev/null +++ b/libraries/timefrequency/interface.cpp @@ -0,0 +1,215 @@ +//#include "wavelet_spectrum_analyzer.h" + +//using namespace TIMEFREQUENCYLIB; + +//#define P_INPUT_DATA 0 +//#define P_SAMPLING_RATE 1 +//#define P_FREQ_INTERVAL 2 +//#define P_FREQ_COUNT 3 +//#define P_CYCLE_COUNT 4 +//#define P_SUPERRESOLUTION 5 +//#define P_MULTIPLICATIVE 6 +//#define P_FRACTIONAL 7 + + +//bool is_integer(double x) +//{ +// return x - (long long)x == 0; +//} + +//int mxGetSize(mxArray* arr) +//{ +// return arr +// ? (int)(mxGetM(arr) * mxGetN(arr)) +// : 0; +//} + + +////void validate_params(int nrhs, mxArray** prhs) +////{ +//// // check params +//// if (nrhs < 6) +//// mexErrMsgTxt("Parameter count not met! faslt expects at least 6 parameters! See below...\n \ +//// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ +//// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ +//// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ +//// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ +//// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ +//// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ +//// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ +//// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); +//// if (nrhs > 8) +//// mexErrMsgTxt("Parameter count exceeded! faslt expects at most 8 parameters! See below...\n \ +//// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ +//// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ +//// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ +//// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ +//// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ +//// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ +//// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ +//// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); + +//// // check data +//// if (!mxIsDouble(prhs[P_INPUT_DATA])) +//// mexErrMsgTxt("input_data needs to be a real-valued (double) matrix"); + +//// // check input size +//// if (!mxGetN(prhs[P_INPUT_DATA]) == 1) +//// mexErrMsgTxt("input_data is a column vector. faslt only accepts row vectors."); + +//// // check FS +//// if (mxGetScalar(prhs[P_SAMPLING_RATE]) <= 0.0) +//// mexErrMsgTxt("sampling_rate needs to be a positive non-zero scalar representing the sampling frequency of the input in Hz"); + +//// // check freq interval +//// if (!mxIsDouble(prhs[P_FREQ_INTERVAL]) || mxGetSize(prhs[P_FREQ_INTERVAL]) != 2) +//// mexErrMsgTxt("frequency_interval needs to be a tuple containing the lower and upper frequency bounds in Hz"); +//// else +//// { +//// double lower = mxGetPr(prhs[P_FREQ_INTERVAL])[0]; +//// double upper = mxGetPr(prhs[P_FREQ_INTERVAL])[1]; +//// double fs = mxGetScalar(prhs[P_SAMPLING_RATE]); + +//// if (lower <= 0 || lower >= fs / 2 || +//// upper <= 0 || upper >= fs / 2) +//// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +//// } + +//// // check frequency count +//// if (!is_integer(mxGetScalar(prhs[P_FREQ_COUNT])) || mxGetScalar(prhs[P_FREQ_COUNT]) <= 0) +//// mexErrMsgTxt("frequency_count needs to be a positive non-zero integer"); + +//// // check cycle count +//// if (mxGetScalar(prhs[P_CYCLE_COUNT]) <= 0.0) +//// mexErrMsgTxt("cycle_count needs to be a positive non-zero scalar representing the number of cycles of the shortest wavelets"); + +//// // check resolution +//// if (!mxIsDouble(prhs[P_SUPERRESOLUTION]) || mxGetSize(prhs[P_SUPERRESOLUTION]) != 2) +//// mexErrMsgTxt("superresolution needs to be a tuple containing the lower and upper frequency bounds in Hz"); +//// else +//// { +//// if (mxGetPr(prhs[P_SUPERRESOLUTION])[0] <= 0 || mxGetPr(prhs[P_SUPERRESOLUTION])[1] <= 0) +//// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +//// } + +//// // check multiplicative +//// if (nrhs > P_MULTIPLICATIVE && mxGetSize(prhs[P_MULTIPLICATIVE]) != 1) +//// mexErrMsgTxt("multiplicative needs to be a scalar (0 - false, !0 otherwise)"); + +//// // check fractional +//// if (nrhs > P_FRACTIONAL && mxGetSize(prhs[P_FRACTIONAL]) != 1) +//// mexErrMsgTxt("fractional needs to be a scalar (0 - false, !0 otherwise)"); +////} + + + +////void print_settings(wavelet_analyzer_settings& set) +////{ +//// mexPrintf("wavelet_analyzer_settings:\n\ +//// sampling_rate: %f\n\ +//// freq_low: %f\n\ +//// freq_high: %f\n\ +//// freq_count: %d\n\ +//// input_size: %d\n\ +//// wavelet_cycles: %f\n\ +//// resolution_low: %f\n\ +//// resolution_high: %f\n\ +//// multiplicative: %s\n\ +//// fractional: %s\n", +//// set.sampling_rate, +//// set.freq_low, +//// set.freq_high, +//// set.freq_count, +//// set.input_size, +//// set.wavelet_cycles, +//// set.resolution_low, +//// set.resolution_high, +//// set.multiplicative ? "true" : "false", +//// set.fractional ? "true" : "false"); +////} + + +//void mexFunction(int nlhs, mxArray** plhs, int nrhs, mxArray** prhs) +//{ +// // Parameter Name - Parameter Type - Description +// // +// // input_data - Scalar Matrix - Input buffers (row major) - each row is a trial +// // sampling_rate - Scalar Number - The sampling frequency in Hz +// // frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency +// // frequency_count - Integer Number - the number of frequency bins in the interval +// // cycle_count - Scalar Number - the number of cycles of the shortest wavelets +// // superresolution_order - Scalar Vector - tuple containing the lowest and the highest superresolution orders +// // multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true) +// // fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true) +// // +// //Return values +// // S - Scalar Matrix - A matrix of size length(frequencies) x size(input_data, 2) + +// validate_params(nrhs, prhs); + +// // read parameters +// wavelet_analyzer_settings set; + +// // input dimensions +// int input_count = (int)mxGetM(prhs[P_INPUT_DATA]); +// set.input_size = (int)mxGetN(prhs[P_INPUT_DATA]); + +// // sampling rate +// set.sampling_rate = (float)mxGetScalar(prhs[P_SAMPLING_RATE]); + +// // frequencies +// set.freq_low = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[0]; +// set.freq_high = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[1]; +// set.freq_count = (int)mxGetScalar(prhs[P_FREQ_COUNT]); + +// // res order +// set.wavelet_cycles = (float)mxGetScalar(prhs[P_CYCLE_COUNT]); +// set.resolution_low = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[0]; +// set.resolution_high = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[1]; + +// // flags +// set.multiplicative = nrhs > P_MULTIPLICATIVE ? (bool)mxGetScalar(prhs[P_MULTIPLICATIVE]) : true; +// set.fractional = nrhs > P_FRACTIONAL ? (bool)mxGetScalar(prhs[P_FRACTIONAL]) : true; + +// // create output +// nlhs = 1; +// plhs[0] = mxCreateDoubleMatrix(set.freq_count, set.input_size, mxREAL); + +// // alloc temporary buffers (for float conversion and IO) +// float *flt_input_data = static_cast(mxCalloc(set.input_size, sizeof(float))); +// float *flt_result = static_cast(mxCalloc(size_t(set.freq_count) * set.input_size, sizeof(float))); +// double* in_ptr = mxGetPr(prhs[P_INPUT_DATA]); +// double* out_ptr = mxGetPr(plhs[0]); + +// // check buffers +// if (!flt_input_data || !flt_result) +// { +// mexErrMsgTxt("Internal error!"); +// return; +// } + +// // create analyzer +// wavelet_spectrum_analyzer anl(set); + +// // perform analysis +// for (int i = 0; i < input_count; ++i) +// { +// for (int j = 0; j < set.input_size; ++j) +// flt_input_data[j] = (float)in_ptr[i + j * input_count]; + +// anl.analyze(flt_input_data, flt_result); +// } + +// // normalize and copy output +// double idiv = 1.0 / input_count; +// for (int i = 0; i < set.freq_count; ++i) +// { +// for (int j = 0; j < set.input_size; ++j) +// { +// out_ptr[i + j * set.freq_count] = flt_result[i * set.input_size + j] * idiv; +// } +// } + +// mxFree(flt_input_data); +// mxFree(flt_result); +//} diff --git a/libraries/timefrequency/lib/libfftw3f-3.def b/libraries/timefrequency/lib/libfftw3f-3.def new file mode 100644 index 00000000000..d61a2c36c76 --- /dev/null +++ b/libraries/timefrequency/lib/libfftw3f-3.def @@ -0,0 +1,1017 @@ +LIBRARY libfftw3f-3.dll +EXPORTS +fftwf_alignment_of +fftwf_alloc_complex +fftwf_alloc_real +fftwf_assertion_failed +fftwf_bufdist +fftwf_check_alignment_of_sse2_pm +fftwf_choose_radix +fftwf_cleanup +fftwf_cleanup_threads +fftwf_codelet_e01_8 +fftwf_codelet_e10_8 +fftwf_codelet_hb_10 +fftwf_codelet_hb_12 +fftwf_codelet_hb_15 +fftwf_codelet_hb_16 +fftwf_codelet_hb_2 +fftwf_codelet_hb_20 +fftwf_codelet_hb2_16 +fftwf_codelet_hb2_20 +fftwf_codelet_hb2_25 +fftwf_codelet_hb2_32 +fftwf_codelet_hb2_4 +fftwf_codelet_hb_25 +fftwf_codelet_hb2_5 +fftwf_codelet_hb2_8 +fftwf_codelet_hb_3 +fftwf_codelet_hb_32 +fftwf_codelet_hb_4 +fftwf_codelet_hb_5 +fftwf_codelet_hb_6 +fftwf_codelet_hb_64 +fftwf_codelet_hb_7 +fftwf_codelet_hb_8 +fftwf_codelet_hb_9 +fftwf_codelet_hc2cb_10 +fftwf_codelet_hc2cb_12 +fftwf_codelet_hc2cb_16 +fftwf_codelet_hc2cb_2 +fftwf_codelet_hc2cb_20 +fftwf_codelet_hc2cb2_16 +fftwf_codelet_hc2cb2_20 +fftwf_codelet_hc2cb2_32 +fftwf_codelet_hc2cb2_4 +fftwf_codelet_hc2cb2_8 +fftwf_codelet_hc2cb_32 +fftwf_codelet_hc2cb_4 +fftwf_codelet_hc2cb_6 +fftwf_codelet_hc2cb_8 +fftwf_codelet_hc2cbdft_10 +fftwf_codelet_hc2cbdft_12 +fftwf_codelet_hc2cbdft_16 +fftwf_codelet_hc2cbdft_2 +fftwf_codelet_hc2cbdft_20 +fftwf_codelet_hc2cbdft2_16 +fftwf_codelet_hc2cbdft2_20 +fftwf_codelet_hc2cbdft2_32 +fftwf_codelet_hc2cbdft2_4 +fftwf_codelet_hc2cbdft2_8 +fftwf_codelet_hc2cbdft_32 +fftwf_codelet_hc2cbdft_4 +fftwf_codelet_hc2cbdft_6 +fftwf_codelet_hc2cbdft_8 +fftwf_codelet_hc2cbdftv_10_avx +fftwf_codelet_hc2cbdftv_10_sse2 +fftwf_codelet_hc2cbdftv_12_avx +fftwf_codelet_hc2cbdftv_12_sse2 +fftwf_codelet_hc2cbdftv_16_avx +fftwf_codelet_hc2cbdftv_16_sse2 +fftwf_codelet_hc2cbdftv_20_avx +fftwf_codelet_hc2cbdftv_20_sse2 +fftwf_codelet_hc2cbdftv_2_avx +fftwf_codelet_hc2cbdftv_2_sse2 +fftwf_codelet_hc2cbdftv_32_avx +fftwf_codelet_hc2cbdftv_32_sse2 +fftwf_codelet_hc2cbdftv_4_avx +fftwf_codelet_hc2cbdftv_4_sse2 +fftwf_codelet_hc2cbdftv_6_avx +fftwf_codelet_hc2cbdftv_6_sse2 +fftwf_codelet_hc2cbdftv_8_avx +fftwf_codelet_hc2cbdftv_8_sse2 +fftwf_codelet_hc2cf_10 +fftwf_codelet_hc2cf_12 +fftwf_codelet_hc2cf_16 +fftwf_codelet_hc2cf_2 +fftwf_codelet_hc2cf_20 +fftwf_codelet_hc2cf2_16 +fftwf_codelet_hc2cf2_20 +fftwf_codelet_hc2cf2_32 +fftwf_codelet_hc2cf2_4 +fftwf_codelet_hc2cf2_8 +fftwf_codelet_hc2cf_32 +fftwf_codelet_hc2cf_4 +fftwf_codelet_hc2cf_6 +fftwf_codelet_hc2cf_8 +fftwf_codelet_hc2cfdft_10 +fftwf_codelet_hc2cfdft_12 +fftwf_codelet_hc2cfdft_16 +fftwf_codelet_hc2cfdft_2 +fftwf_codelet_hc2cfdft_20 +fftwf_codelet_hc2cfdft2_16 +fftwf_codelet_hc2cfdft2_20 +fftwf_codelet_hc2cfdft2_32 +fftwf_codelet_hc2cfdft2_4 +fftwf_codelet_hc2cfdft2_8 +fftwf_codelet_hc2cfdft_32 +fftwf_codelet_hc2cfdft_4 +fftwf_codelet_hc2cfdft_6 +fftwf_codelet_hc2cfdft_8 +fftwf_codelet_hc2cfdftv_10_avx +fftwf_codelet_hc2cfdftv_10_sse2 +fftwf_codelet_hc2cfdftv_12_avx +fftwf_codelet_hc2cfdftv_12_sse2 +fftwf_codelet_hc2cfdftv_16_avx +fftwf_codelet_hc2cfdftv_16_sse2 +fftwf_codelet_hc2cfdftv_20_avx +fftwf_codelet_hc2cfdftv_20_sse2 +fftwf_codelet_hc2cfdftv_2_avx +fftwf_codelet_hc2cfdftv_2_sse2 +fftwf_codelet_hc2cfdftv_32_avx +fftwf_codelet_hc2cfdftv_32_sse2 +fftwf_codelet_hc2cfdftv_4_avx +fftwf_codelet_hc2cfdftv_4_sse2 +fftwf_codelet_hc2cfdftv_6_avx +fftwf_codelet_hc2cfdftv_6_sse2 +fftwf_codelet_hc2cfdftv_8_avx +fftwf_codelet_hc2cfdftv_8_sse2 +fftwf_codelet_hf_10 +fftwf_codelet_hf_12 +fftwf_codelet_hf_15 +fftwf_codelet_hf_16 +fftwf_codelet_hf_2 +fftwf_codelet_hf_20 +fftwf_codelet_hf2_16 +fftwf_codelet_hf2_20 +fftwf_codelet_hf2_25 +fftwf_codelet_hf2_32 +fftwf_codelet_hf2_4 +fftwf_codelet_hf_25 +fftwf_codelet_hf2_5 +fftwf_codelet_hf2_8 +fftwf_codelet_hf_3 +fftwf_codelet_hf_32 +fftwf_codelet_hf_4 +fftwf_codelet_hf_5 +fftwf_codelet_hf_6 +fftwf_codelet_hf_64 +fftwf_codelet_hf_7 +fftwf_codelet_hf_8 +fftwf_codelet_hf_9 +fftwf_codelet_n1_10 +fftwf_codelet_n1_11 +fftwf_codelet_n1_12 +fftwf_codelet_n1_13 +fftwf_codelet_n1_14 +fftwf_codelet_n1_15 +fftwf_codelet_n1_16 +fftwf_codelet_n1_2 +fftwf_codelet_n1_20 +fftwf_codelet_n1_25 +fftwf_codelet_n1_3 +fftwf_codelet_n1_32 +fftwf_codelet_n1_4 +fftwf_codelet_n1_5 +fftwf_codelet_n1_6 +fftwf_codelet_n1_64 +fftwf_codelet_n1_7 +fftwf_codelet_n1_8 +fftwf_codelet_n1_9 +fftwf_codelet_n1bv_10_avx +fftwf_codelet_n1bv_10_sse2 +fftwf_codelet_n1bv_11_avx +fftwf_codelet_n1bv_11_sse2 +fftwf_codelet_n1bv_128_avx +fftwf_codelet_n1bv_128_sse2 +fftwf_codelet_n1bv_12_avx +fftwf_codelet_n1bv_12_sse2 +fftwf_codelet_n1bv_13_avx +fftwf_codelet_n1bv_13_sse2 +fftwf_codelet_n1bv_14_avx +fftwf_codelet_n1bv_14_sse2 +fftwf_codelet_n1bv_15_avx +fftwf_codelet_n1bv_15_sse2 +fftwf_codelet_n1bv_16_avx +fftwf_codelet_n1bv_16_sse2 +fftwf_codelet_n1bv_20_avx +fftwf_codelet_n1bv_20_sse2 +fftwf_codelet_n1bv_25_avx +fftwf_codelet_n1bv_25_sse2 +fftwf_codelet_n1bv_2_avx +fftwf_codelet_n1bv_2_sse2 +fftwf_codelet_n1bv_32_avx +fftwf_codelet_n1bv_32_sse2 +fftwf_codelet_n1bv_3_avx +fftwf_codelet_n1bv_3_sse2 +fftwf_codelet_n1bv_4_avx +fftwf_codelet_n1bv_4_sse2 +fftwf_codelet_n1bv_5_avx +fftwf_codelet_n1bv_5_sse2 +fftwf_codelet_n1bv_64_avx +fftwf_codelet_n1bv_64_sse2 +fftwf_codelet_n1bv_6_avx +fftwf_codelet_n1bv_6_sse2 +fftwf_codelet_n1bv_7_avx +fftwf_codelet_n1bv_7_sse2 +fftwf_codelet_n1bv_8_avx +fftwf_codelet_n1bv_8_sse2 +fftwf_codelet_n1bv_9_avx +fftwf_codelet_n1bv_9_sse2 +fftwf_codelet_n1fv_10_avx +fftwf_codelet_n1fv_10_sse2 +fftwf_codelet_n1fv_11_avx +fftwf_codelet_n1fv_11_sse2 +fftwf_codelet_n1fv_128_avx +fftwf_codelet_n1fv_128_sse2 +fftwf_codelet_n1fv_12_avx +fftwf_codelet_n1fv_12_sse2 +fftwf_codelet_n1fv_13_avx +fftwf_codelet_n1fv_13_sse2 +fftwf_codelet_n1fv_14_avx +fftwf_codelet_n1fv_14_sse2 +fftwf_codelet_n1fv_15_avx +fftwf_codelet_n1fv_15_sse2 +fftwf_codelet_n1fv_16_avx +fftwf_codelet_n1fv_16_sse2 +fftwf_codelet_n1fv_20_avx +fftwf_codelet_n1fv_20_sse2 +fftwf_codelet_n1fv_25_avx +fftwf_codelet_n1fv_25_sse2 +fftwf_codelet_n1fv_2_avx +fftwf_codelet_n1fv_2_sse2 +fftwf_codelet_n1fv_32_avx +fftwf_codelet_n1fv_32_sse2 +fftwf_codelet_n1fv_3_avx +fftwf_codelet_n1fv_3_sse2 +fftwf_codelet_n1fv_4_avx +fftwf_codelet_n1fv_4_sse2 +fftwf_codelet_n1fv_5_avx +fftwf_codelet_n1fv_5_sse2 +fftwf_codelet_n1fv_64_avx +fftwf_codelet_n1fv_64_sse2 +fftwf_codelet_n1fv_6_avx +fftwf_codelet_n1fv_6_sse2 +fftwf_codelet_n1fv_7_avx +fftwf_codelet_n1fv_7_sse2 +fftwf_codelet_n1fv_8_avx +fftwf_codelet_n1fv_8_sse2 +fftwf_codelet_n1fv_9_avx +fftwf_codelet_n1fv_9_sse2 +fftwf_codelet_n2bv_10_avx +fftwf_codelet_n2bv_10_sse2 +fftwf_codelet_n2bv_12_avx +fftwf_codelet_n2bv_12_sse2 +fftwf_codelet_n2bv_14_avx +fftwf_codelet_n2bv_14_sse2 +fftwf_codelet_n2bv_16_avx +fftwf_codelet_n2bv_16_sse2 +fftwf_codelet_n2bv_20_avx +fftwf_codelet_n2bv_20_sse2 +fftwf_codelet_n2bv_2_avx +fftwf_codelet_n2bv_2_sse2 +fftwf_codelet_n2bv_32_avx +fftwf_codelet_n2bv_32_sse2 +fftwf_codelet_n2bv_4_avx +fftwf_codelet_n2bv_4_sse2 +fftwf_codelet_n2bv_64_avx +fftwf_codelet_n2bv_64_sse2 +fftwf_codelet_n2bv_6_avx +fftwf_codelet_n2bv_6_sse2 +fftwf_codelet_n2bv_8_avx +fftwf_codelet_n2bv_8_sse2 +fftwf_codelet_n2fv_10_avx +fftwf_codelet_n2fv_10_sse2 +fftwf_codelet_n2fv_12_avx +fftwf_codelet_n2fv_12_sse2 +fftwf_codelet_n2fv_14_avx +fftwf_codelet_n2fv_14_sse2 +fftwf_codelet_n2fv_16_avx +fftwf_codelet_n2fv_16_sse2 +fftwf_codelet_n2fv_20_avx +fftwf_codelet_n2fv_20_sse2 +fftwf_codelet_n2fv_2_avx +fftwf_codelet_n2fv_2_sse2 +fftwf_codelet_n2fv_32_avx +fftwf_codelet_n2fv_32_sse2 +fftwf_codelet_n2fv_4_avx +fftwf_codelet_n2fv_4_sse2 +fftwf_codelet_n2fv_64_avx +fftwf_codelet_n2fv_64_sse2 +fftwf_codelet_n2fv_6_avx +fftwf_codelet_n2fv_6_sse2 +fftwf_codelet_n2fv_8_avx +fftwf_codelet_n2fv_8_sse2 +fftwf_codelet_n2sv_16_avx +fftwf_codelet_n2sv_16_sse2 +fftwf_codelet_n2sv_32_avx +fftwf_codelet_n2sv_32_sse2 +fftwf_codelet_n2sv_4_avx +fftwf_codelet_n2sv_4_sse2 +fftwf_codelet_n2sv_64_avx +fftwf_codelet_n2sv_64_sse2 +fftwf_codelet_n2sv_8_avx +fftwf_codelet_n2sv_8_sse2 +fftwf_codelet_q1_2 +fftwf_codelet_q1_3 +fftwf_codelet_q1_4 +fftwf_codelet_q1_5 +fftwf_codelet_q1_6 +fftwf_codelet_q1_8 +fftwf_codelet_q1bv_2_avx +fftwf_codelet_q1bv_2_sse2 +fftwf_codelet_q1bv_4_avx +fftwf_codelet_q1bv_4_sse2 +fftwf_codelet_q1bv_5_avx +fftwf_codelet_q1bv_5_sse2 +fftwf_codelet_q1bv_8_avx +fftwf_codelet_q1bv_8_sse2 +fftwf_codelet_q1fv_2_avx +fftwf_codelet_q1fv_2_sse2 +fftwf_codelet_q1fv_4_avx +fftwf_codelet_q1fv_4_sse2 +fftwf_codelet_q1fv_5_avx +fftwf_codelet_q1fv_5_sse2 +fftwf_codelet_q1fv_8_avx +fftwf_codelet_q1fv_8_sse2 +fftwf_codelet_r2cb_10 +fftwf_codelet_r2cb_11 +fftwf_codelet_r2cb_12 +fftwf_codelet_r2cb_128 +fftwf_codelet_r2cb_13 +fftwf_codelet_r2cb_14 +fftwf_codelet_r2cb_15 +fftwf_codelet_r2cb_16 +fftwf_codelet_r2cb_2 +fftwf_codelet_r2cb_20 +fftwf_codelet_r2cb_25 +fftwf_codelet_r2cb_3 +fftwf_codelet_r2cb_32 +fftwf_codelet_r2cb_4 +fftwf_codelet_r2cb_5 +fftwf_codelet_r2cb_6 +fftwf_codelet_r2cb_64 +fftwf_codelet_r2cb_7 +fftwf_codelet_r2cb_8 +fftwf_codelet_r2cb_9 +fftwf_codelet_r2cbIII_10 +fftwf_codelet_r2cbIII_12 +fftwf_codelet_r2cbIII_15 +fftwf_codelet_r2cbIII_16 +fftwf_codelet_r2cbIII_2 +fftwf_codelet_r2cbIII_20 +fftwf_codelet_r2cbIII_25 +fftwf_codelet_r2cbIII_3 +fftwf_codelet_r2cbIII_32 +fftwf_codelet_r2cbIII_4 +fftwf_codelet_r2cbIII_5 +fftwf_codelet_r2cbIII_6 +fftwf_codelet_r2cbIII_64 +fftwf_codelet_r2cbIII_7 +fftwf_codelet_r2cbIII_8 +fftwf_codelet_r2cbIII_9 +fftwf_codelet_r2cf_10 +fftwf_codelet_r2cf_11 +fftwf_codelet_r2cf_12 +fftwf_codelet_r2cf_128 +fftwf_codelet_r2cf_13 +fftwf_codelet_r2cf_14 +fftwf_codelet_r2cf_15 +fftwf_codelet_r2cf_16 +fftwf_codelet_r2cf_2 +fftwf_codelet_r2cf_20 +fftwf_codelet_r2cf_25 +fftwf_codelet_r2cf_3 +fftwf_codelet_r2cf_32 +fftwf_codelet_r2cf_4 +fftwf_codelet_r2cf_5 +fftwf_codelet_r2cf_6 +fftwf_codelet_r2cf_64 +fftwf_codelet_r2cf_7 +fftwf_codelet_r2cf_8 +fftwf_codelet_r2cf_9 +fftwf_codelet_r2cfII_10 +fftwf_codelet_r2cfII_12 +fftwf_codelet_r2cfII_15 +fftwf_codelet_r2cfII_16 +fftwf_codelet_r2cfII_2 +fftwf_codelet_r2cfII_20 +fftwf_codelet_r2cfII_25 +fftwf_codelet_r2cfII_3 +fftwf_codelet_r2cfII_32 +fftwf_codelet_r2cfII_4 +fftwf_codelet_r2cfII_5 +fftwf_codelet_r2cfII_6 +fftwf_codelet_r2cfII_64 +fftwf_codelet_r2cfII_7 +fftwf_codelet_r2cfII_8 +fftwf_codelet_r2cfII_9 +fftwf_codelet_t1_10 +fftwf_codelet_t1_12 +fftwf_codelet_t1_15 +fftwf_codelet_t1_16 +fftwf_codelet_t1_2 +fftwf_codelet_t1_20 +fftwf_codelet_t1_25 +fftwf_codelet_t1_3 +fftwf_codelet_t1_32 +fftwf_codelet_t1_4 +fftwf_codelet_t1_5 +fftwf_codelet_t1_6 +fftwf_codelet_t1_64 +fftwf_codelet_t1_7 +fftwf_codelet_t1_8 +fftwf_codelet_t1_9 +fftwf_codelet_t1buv_10_avx +fftwf_codelet_t1buv_10_sse2 +fftwf_codelet_t1buv_2_avx +fftwf_codelet_t1buv_2_sse2 +fftwf_codelet_t1buv_3_avx +fftwf_codelet_t1buv_3_sse2 +fftwf_codelet_t1buv_4_avx +fftwf_codelet_t1buv_4_sse2 +fftwf_codelet_t1buv_5_avx +fftwf_codelet_t1buv_5_sse2 +fftwf_codelet_t1buv_6_avx +fftwf_codelet_t1buv_6_sse2 +fftwf_codelet_t1buv_7_avx +fftwf_codelet_t1buv_7_sse2 +fftwf_codelet_t1buv_8_avx +fftwf_codelet_t1buv_8_sse2 +fftwf_codelet_t1buv_9_avx +fftwf_codelet_t1buv_9_sse2 +fftwf_codelet_t1bv_10_avx +fftwf_codelet_t1bv_10_sse2 +fftwf_codelet_t1bv_12_avx +fftwf_codelet_t1bv_12_sse2 +fftwf_codelet_t1bv_15_avx +fftwf_codelet_t1bv_15_sse2 +fftwf_codelet_t1bv_16_avx +fftwf_codelet_t1bv_16_sse2 +fftwf_codelet_t1bv_20_avx +fftwf_codelet_t1bv_20_sse2 +fftwf_codelet_t1bv_25_avx +fftwf_codelet_t1bv_25_sse2 +fftwf_codelet_t1bv_2_avx +fftwf_codelet_t1bv_2_sse2 +fftwf_codelet_t1bv_32_avx +fftwf_codelet_t1bv_32_sse2 +fftwf_codelet_t1bv_3_avx +fftwf_codelet_t1bv_3_sse2 +fftwf_codelet_t1bv_4_avx +fftwf_codelet_t1bv_4_sse2 +fftwf_codelet_t1bv_5_avx +fftwf_codelet_t1bv_5_sse2 +fftwf_codelet_t1bv_64_avx +fftwf_codelet_t1bv_64_sse2 +fftwf_codelet_t1bv_6_avx +fftwf_codelet_t1bv_6_sse2 +fftwf_codelet_t1bv_7_avx +fftwf_codelet_t1bv_7_sse2 +fftwf_codelet_t1bv_8_avx +fftwf_codelet_t1bv_8_sse2 +fftwf_codelet_t1bv_9_avx +fftwf_codelet_t1bv_9_sse2 +fftwf_codelet_t1fuv_10_avx +fftwf_codelet_t1fuv_10_sse2 +fftwf_codelet_t1fuv_2_avx +fftwf_codelet_t1fuv_2_sse2 +fftwf_codelet_t1fuv_3_avx +fftwf_codelet_t1fuv_3_sse2 +fftwf_codelet_t1fuv_4_avx +fftwf_codelet_t1fuv_4_sse2 +fftwf_codelet_t1fuv_5_avx +fftwf_codelet_t1fuv_5_sse2 +fftwf_codelet_t1fuv_6_avx +fftwf_codelet_t1fuv_6_sse2 +fftwf_codelet_t1fuv_7_avx +fftwf_codelet_t1fuv_7_sse2 +fftwf_codelet_t1fuv_8_avx +fftwf_codelet_t1fuv_8_sse2 +fftwf_codelet_t1fuv_9_avx +fftwf_codelet_t1fuv_9_sse2 +fftwf_codelet_t1fv_10_avx +fftwf_codelet_t1fv_10_sse2 +fftwf_codelet_t1fv_12_avx +fftwf_codelet_t1fv_12_sse2 +fftwf_codelet_t1fv_15_avx +fftwf_codelet_t1fv_15_sse2 +fftwf_codelet_t1fv_16_avx +fftwf_codelet_t1fv_16_sse2 +fftwf_codelet_t1fv_20_avx +fftwf_codelet_t1fv_20_sse2 +fftwf_codelet_t1fv_25_avx +fftwf_codelet_t1fv_25_sse2 +fftwf_codelet_t1fv_2_avx +fftwf_codelet_t1fv_2_sse2 +fftwf_codelet_t1fv_32_avx +fftwf_codelet_t1fv_32_sse2 +fftwf_codelet_t1fv_3_avx +fftwf_codelet_t1fv_3_sse2 +fftwf_codelet_t1fv_4_avx +fftwf_codelet_t1fv_4_sse2 +fftwf_codelet_t1fv_5_avx +fftwf_codelet_t1fv_5_sse2 +fftwf_codelet_t1fv_64_avx +fftwf_codelet_t1fv_64_sse2 +fftwf_codelet_t1fv_6_avx +fftwf_codelet_t1fv_6_sse2 +fftwf_codelet_t1fv_7_avx +fftwf_codelet_t1fv_7_sse2 +fftwf_codelet_t1fv_8_avx +fftwf_codelet_t1fv_8_sse2 +fftwf_codelet_t1fv_9_avx +fftwf_codelet_t1fv_9_sse2 +fftwf_codelet_t1sv_16_avx +fftwf_codelet_t1sv_16_sse2 +fftwf_codelet_t1sv_2_avx +fftwf_codelet_t1sv_2_sse2 +fftwf_codelet_t1sv_32_avx +fftwf_codelet_t1sv_32_sse2 +fftwf_codelet_t1sv_4_avx +fftwf_codelet_t1sv_4_sse2 +fftwf_codelet_t1sv_8_avx +fftwf_codelet_t1sv_8_sse2 +fftwf_codelet_t2_10 +fftwf_codelet_t2_16 +fftwf_codelet_t2_20 +fftwf_codelet_t2_25 +fftwf_codelet_t2_32 +fftwf_codelet_t2_4 +fftwf_codelet_t2_5 +fftwf_codelet_t2_64 +fftwf_codelet_t2_8 +fftwf_codelet_t2bv_10_avx +fftwf_codelet_t2bv_10_sse2 +fftwf_codelet_t2bv_16_avx +fftwf_codelet_t2bv_16_sse2 +fftwf_codelet_t2bv_20_avx +fftwf_codelet_t2bv_20_sse2 +fftwf_codelet_t2bv_25_avx +fftwf_codelet_t2bv_25_sse2 +fftwf_codelet_t2bv_2_avx +fftwf_codelet_t2bv_2_sse2 +fftwf_codelet_t2bv_32_avx +fftwf_codelet_t2bv_32_sse2 +fftwf_codelet_t2bv_4_avx +fftwf_codelet_t2bv_4_sse2 +fftwf_codelet_t2bv_5_avx +fftwf_codelet_t2bv_5_sse2 +fftwf_codelet_t2bv_64_avx +fftwf_codelet_t2bv_64_sse2 +fftwf_codelet_t2bv_8_avx +fftwf_codelet_t2bv_8_sse2 +fftwf_codelet_t2fv_10_avx +fftwf_codelet_t2fv_10_sse2 +fftwf_codelet_t2fv_16_avx +fftwf_codelet_t2fv_16_sse2 +fftwf_codelet_t2fv_20_avx +fftwf_codelet_t2fv_20_sse2 +fftwf_codelet_t2fv_25_avx +fftwf_codelet_t2fv_25_sse2 +fftwf_codelet_t2fv_2_avx +fftwf_codelet_t2fv_2_sse2 +fftwf_codelet_t2fv_32_avx +fftwf_codelet_t2fv_32_sse2 +fftwf_codelet_t2fv_4_avx +fftwf_codelet_t2fv_4_sse2 +fftwf_codelet_t2fv_5_avx +fftwf_codelet_t2fv_5_sse2 +fftwf_codelet_t2fv_64_avx +fftwf_codelet_t2fv_64_sse2 +fftwf_codelet_t2fv_8_avx +fftwf_codelet_t2fv_8_sse2 +fftwf_codelet_t2sv_16_avx +fftwf_codelet_t2sv_16_sse2 +fftwf_codelet_t2sv_32_avx +fftwf_codelet_t2sv_32_sse2 +fftwf_codelet_t2sv_4_avx +fftwf_codelet_t2sv_4_sse2 +fftwf_codelet_t2sv_8_avx +fftwf_codelet_t2sv_8_sse2 +fftwf_codelet_t3bv_10_avx +fftwf_codelet_t3bv_10_sse2 +fftwf_codelet_t3bv_16_avx +fftwf_codelet_t3bv_16_sse2 +fftwf_codelet_t3bv_20_avx +fftwf_codelet_t3bv_20_sse2 +fftwf_codelet_t3bv_25_avx +fftwf_codelet_t3bv_25_sse2 +fftwf_codelet_t3bv_32_avx +fftwf_codelet_t3bv_32_sse2 +fftwf_codelet_t3bv_4_avx +fftwf_codelet_t3bv_4_sse2 +fftwf_codelet_t3bv_5_avx +fftwf_codelet_t3bv_5_sse2 +fftwf_codelet_t3bv_8_avx +fftwf_codelet_t3bv_8_sse2 +fftwf_codelet_t3fv_10_avx +fftwf_codelet_t3fv_10_sse2 +fftwf_codelet_t3fv_16_avx +fftwf_codelet_t3fv_16_sse2 +fftwf_codelet_t3fv_20_avx +fftwf_codelet_t3fv_20_sse2 +fftwf_codelet_t3fv_25_avx +fftwf_codelet_t3fv_25_sse2 +fftwf_codelet_t3fv_32_avx +fftwf_codelet_t3fv_32_sse2 +fftwf_codelet_t3fv_4_avx +fftwf_codelet_t3fv_4_sse2 +fftwf_codelet_t3fv_5_avx +fftwf_codelet_t3fv_5_sse2 +fftwf_codelet_t3fv_8_avx +fftwf_codelet_t3fv_8_sse2 +fftwf_compute_tilesz +fftwf_configure_planner +fftwf_cost +fftwf_cpy1d +fftwf_cpy2d +fftwf_cpy2d_ci +fftwf_cpy2d_co +fftwf_cpy2d_pair +fftwf_cpy2d_pair_ci +fftwf_cpy2d_pair_co +fftwf_cpy2d_tiled +fftwf_cpy2d_tiledbuf +fftwf_ct_applicable +fftwf_ct_genericbuf_register +fftwf_ct_generic_register +fftwf_ct_uglyp +fftwf_destroy_plan +fftwf_dft_bluestein_register +fftwf_dft_buffered_register +fftwf_dft_conf_standard +fftwf_dft_generic_register +fftwf_dft_indirect_register +fftwf_dft_indirect_transpose_register +fftwf_dft_nop_register +fftwf_dft_r2hc_register +fftwf_dft_rader_register +fftwf_dft_rank_geq2_register +fftwf_dft_solve +fftwf_dft_thr_vrank_geq1_register +fftwf_dft_vrank_geq1_register +fftwf_dft_zerotens +fftwf_dht_r2hc_register +fftwf_dht_rader_register +fftwf_dimcmp +fftwf_elapsed_since +fftwf_estimate_cost +fftwf_execute +fftwf_execute_dft +fftwf_execute_dft_c2r +fftwf_execute_dft_r2c +fftwf_execute_r2r +fftwf_execute_split_dft +fftwf_execute_split_dft_c2r +fftwf_execute_split_dft_r2c +fftwf_export_wisdom +fftwf_export_wisdom_to_file +fftwf_export_wisdom_to_filename +fftwf_export_wisdom_to_string +fftwf_extract_reim +fftwf_factors_into +fftwf_factors_into_small_primes +fftwf_find_generator +fftwf_first_divisor +fftwf_flops +fftwf_forget_wisdom +fftwf_fprint_plan +fftwf_free +fftwf_get_crude_time +fftwf_guru64_kosherp +fftwf_guru_kosherp +fftwf_hash +fftwf_have_simd_avx +fftwf_have_simd_sse2 +fftwf_hc2hc_applicable +fftwf_hc2hc_generic_register +fftwf_iabs +fftwf_ialignment_of +fftwf_iestimate_cost +fftwf_ifree +fftwf_ifree0 +fftwf_imax +fftwf_imin +fftwf_import_system_wisdom +fftwf_import_wisdom +fftwf_import_wisdom_from_file +fftwf_import_wisdom_from_filename +fftwf_import_wisdom_from_string +fftwf_init_threads +fftwf_is_prime +fftwf_isqrt +fftwf_ithreads_init +fftwf_join_taint +fftwf_kdft_dif_register +fftwf_kdft_difsq_register +fftwf_kdft_dit_register +fftwf_kdft_register +fftwf_kernel_free +fftwf_kernel_malloc +fftwf_khc2c_register +fftwf_khc2hc_register +fftwf_kr2c_register +fftwf_kr2r_register +fftwf_make_planner_thread_safe +fftwf_malloc +fftwf_malloc_plain +fftwf_many_kosherp +fftwf_mapflags +fftwf_map_r2r_kind +fftwf_md5begin +fftwf_md5end +fftwf_md5int +fftwf_md5INT +fftwf_md5putb +fftwf_md5putc +fftwf_md5puts +fftwf_md5unsigned +fftwf_measure_execution_time +fftwf_mkapiplan +fftwf_mkplan +fftwf_mkplan_d +fftwf_mkplan_dft +fftwf_mkplan_dftw +fftwf_mkplan_f_d +fftwf_mkplan_hc2c +fftwf_mkplan_hc2hc +fftwf_mkplanner +fftwf_mkplan_rdft +fftwf_mkplan_rdft2 +fftwf_mkprinter +fftwf_mkprinter_cnt +fftwf_mkprinter_file +fftwf_mkprinter_str +fftwf_mkproblem +fftwf_mkproblem_dft +fftwf_mkproblem_dft_d +fftwf_mkproblem_rdft +fftwf_mkproblem_rdft_0_d +fftwf_mkproblem_rdft_1 +fftwf_mkproblem_rdft_1_d +fftwf_mkproblem_rdft2 +fftwf_mkproblem_rdft2_d +fftwf_mkproblem_rdft2_d_3pointers +fftwf_mkproblem_rdft_d +fftwf_mkproblem_unsolvable +fftwf_mkscanner +fftwf_mksolver +fftwf_mksolver_ct +fftwf_mksolver_ct_threads +fftwf_mksolver_dft_direct +fftwf_mksolver_dft_directbuf +fftwf_mksolver_hc2c +fftwf_mksolver_hc2hc +fftwf_mksolver_hc2hc_threads +fftwf_mksolver_rdft2_direct +fftwf_mksolver_rdft_r2c_direct +fftwf_mksolver_rdft_r2c_directbuf +fftwf_mksolver_rdft_r2r_direct +fftwf_mkstride +fftwf_mktensor +fftwf_mktensor_0d +fftwf_mktensor_1d +fftwf_mktensor_2d +fftwf_mktensor_3d +fftwf_mktensor_4d +fftwf_mktensor_5d +fftwf_mktensor_iodims +fftwf_mktensor_iodims64 +fftwf_mktensor_rowmajor +fftwf_mktriggen +fftwf_modulo +fftwf_nbuf +fftwf_nbuf_redundant +fftwf_next_prime +fftwf_null_awake +fftwf_ops_add +fftwf_ops_add2 +fftwf_ops_cpy +fftwf_ops_madd +fftwf_ops_madd2 +fftwf_ops_other +fftwf_ops_zero +fftwf_pickdim +fftwf_plan_awake +fftwf_plan_destroy_internal +fftwf_plan_dft +fftwf_plan_dft_1d +fftwf_plan_dft_2d +fftwf_plan_dft_3d +fftwf_plan_dft_c2r +fftwf_plan_dft_c2r_1d +fftwf_plan_dft_c2r_2d +fftwf_plan_dft_c2r_3d +fftwf_plan_dft_r2c +fftwf_plan_dft_r2c_1d +fftwf_plan_dft_r2c_2d +fftwf_plan_dft_r2c_3d +fftwf_plan_guru64_dft +fftwf_plan_guru64_dft_c2r +fftwf_plan_guru64_dft_r2c +fftwf_plan_guru64_r2r +fftwf_plan_guru64_split_dft +fftwf_plan_guru64_split_dft_c2r +fftwf_plan_guru64_split_dft_r2c +fftwf_plan_guru_dft +fftwf_plan_guru_dft_c2r +fftwf_plan_guru_dft_r2c +fftwf_plan_guru_r2r +fftwf_plan_guru_split_dft +fftwf_plan_guru_split_dft_c2r +fftwf_plan_guru_split_dft_r2c +fftwf_plan_many_dft +fftwf_plan_many_dft_c2r +fftwf_plan_many_dft_r2c +fftwf_plan_many_r2r +fftwf_planner_destroy +fftwf_plan_null_destroy +fftwf_plan_r2r +fftwf_plan_r2r_1d +fftwf_plan_r2r_2d +fftwf_plan_r2r_3d +fftwf_plan_with_nthreads +fftwf_power_mod +fftwf_printer_destroy +fftwf_print_plan +fftwf_problem_destroy +fftwf_rader_tl_delete +fftwf_rader_tl_find +fftwf_rader_tl_insert +fftwf_rdft2_buffered_register +fftwf_rdft2_complex_n +fftwf_rdft2_inplace_strides +fftwf_rdft2_nop_register +fftwf_rdft2_pad +fftwf_rdft2_rank0_register +fftwf_rdft2_rank_geq2_register +fftwf_rdft2_rdft_register +fftwf_rdft2_solve +fftwf_rdft2_strides +fftwf_rdft2_tensor_max_index +fftwf_rdft2_thr_vrank_geq1_register +fftwf_rdft2_vrank_geq1_register +fftwf_rdft_buffered_register +fftwf_rdft_conf_standard +fftwf_rdft_dht_register +fftwf_rdft_generic_register +fftwf_rdft_indirect_register +fftwf_rdft_kind_str +fftwf_rdft_nop_register +fftwf_rdft_rank0_register +fftwf_rdft_rank_geq2_register +fftwf_rdft_solve +fftwf_rdft_thr_vrank_geq1_register +fftwf_rdft_vrank3_transpose_register +fftwf_rdft_vrank_geq1_register +fftwf_rdft_zerotens +fftwf_redft00e_r2hc_pad_register +fftwf_regsolver_ct_directw +fftwf_regsolver_ct_directwsq +fftwf_regsolver_hc2c_direct +fftwf_regsolver_hc2hc_direct +fftwf_reodft00e_splitradix_register +fftwf_reodft010e_r2hc_register +fftwf_reodft11e_r2hc_odd_register +fftwf_reodft11e_radix2_r2hc_register +fftwf_reodft_conf_standard +fftwf_rodft00e_r2hc_pad_register +fftwf_safe_mulmod +fftwf_scanner_destroy +fftwf_set_planner_hooks +fftwf_set_timelimit +fftwf_solver_destroy +fftwf_solver_register +fftwf_solver_use +fftwf_solvtab_exec +fftwf_spawn_loop +fftwf_sprint_plan +fftwf_stride_destroy +fftwf_taint +fftwf_tensor_append +fftwf_tensor_compress +fftwf_tensor_compress_contiguous +fftwf_tensor_copy +fftwf_tensor_copy_except +fftwf_tensor_copy_inplace +fftwf_tensor_copy_sub +fftwf_tensor_destroy +fftwf_tensor_destroy2 +fftwf_tensor_destroy4 +fftwf_tensor_equal +fftwf_tensor_inplace_locations +fftwf_tensor_inplace_strides +fftwf_tensor_inplace_strides2 +fftwf_tensor_kosherp +fftwf_tensor_max_index +fftwf_tensor_md5 +fftwf_tensor_min_istride +fftwf_tensor_min_ostride +fftwf_tensor_min_stride +fftwf_tensor_print +fftwf_tensor_split +fftwf_tensor_strides_decrease +fftwf_tensor_sz +fftwf_tensor_tornk1 +fftwf_the_planner +fftwf_threads_cleanup +fftwf_threads_conf_standard +fftwf_threads_register_planner_hooks +fftwf_tile2d +fftwf_toobig +fftwf_transpose +fftwf_transpose_tiled +fftwf_transpose_tiledbuf +fftwf_triggen_destroy +fftwf_twiddle_awake +fftwf_twiddle_length +fftwf_zero1d_pair +sfftw_cleanup_ +sfftw_cleanup__ +sfftw_cleanup_threads_ +sfftw_cleanup_threads__ +sfftw_cost_ +sfftw_cost__ +sfftw_destroy_plan_ +sfftw_destroy_plan__ +sfftw_estimate_cost_ +sfftw_estimate_cost__ +sfftw_execute_ +sfftw_execute__ +sfftw_execute_dft_ +sfftw_execute_dft__ +sfftw_execute_dft_c2r_ +sfftw_execute_dft_c2r__ +sfftw_execute_dft_r2c_ +sfftw_execute_dft_r2c__ +sfftw_execute_r2r_ +sfftw_execute_r2r__ +sfftw_execute_split_dft_ +sfftw_execute_split_dft__ +sfftw_execute_split_dft_c2r_ +sfftw_execute_split_dft_c2r__ +sfftw_execute_split_dft_r2c_ +sfftw_execute_split_dft_r2c__ +sfftw_export_wisdom_ +sfftw_export_wisdom__ +sfftw_flops_ +sfftw_flops__ +sfftw_forget_wisdom_ +sfftw_forget_wisdom__ +sfftw_import_system_wisdom_ +sfftw_import_system_wisdom__ +sfftw_import_wisdom_ +sfftw_import_wisdom__ +sfftw_init_threads_ +sfftw_init_threads__ +sfftw_plan_dft_ +sfftw_plan_dft__ +sfftw_plan_dft_1d_ +sfftw_plan_dft_1d__ +sfftw_plan_dft_2d_ +sfftw_plan_dft_2d__ +sfftw_plan_dft_3d_ +sfftw_plan_dft_3d__ +sfftw_plan_dft_c2r_ +sfftw_plan_dft_c2r__ +sfftw_plan_dft_c2r_1d_ +sfftw_plan_dft_c2r_1d__ +sfftw_plan_dft_c2r_2d_ +sfftw_plan_dft_c2r_2d__ +sfftw_plan_dft_c2r_3d_ +sfftw_plan_dft_c2r_3d__ +sfftw_plan_dft_r2c_ +sfftw_plan_dft_r2c__ +sfftw_plan_dft_r2c_1d_ +sfftw_plan_dft_r2c_1d__ +sfftw_plan_dft_r2c_2d_ +sfftw_plan_dft_r2c_2d__ +sfftw_plan_dft_r2c_3d_ +sfftw_plan_dft_r2c_3d__ +sfftw_plan_guru_dft_ +sfftw_plan_guru_dft__ +sfftw_plan_guru_dft_c2r_ +sfftw_plan_guru_dft_c2r__ +sfftw_plan_guru_dft_r2c_ +sfftw_plan_guru_dft_r2c__ +sfftw_plan_guru_r2r_ +sfftw_plan_guru_r2r__ +sfftw_plan_guru_split_dft_ +sfftw_plan_guru_split_dft__ +sfftw_plan_guru_split_dft_c2r_ +sfftw_plan_guru_split_dft_c2r__ +sfftw_plan_guru_split_dft_r2c_ +sfftw_plan_guru_split_dft_r2c__ +sfftw_plan_many_dft_ +sfftw_plan_many_dft__ +sfftw_plan_many_dft_c2r_ +sfftw_plan_many_dft_c2r__ +sfftw_plan_many_dft_r2c_ +sfftw_plan_many_dft_r2c__ +sfftw_plan_many_r2r_ +sfftw_plan_many_r2r__ +sfftw_plan_r2r_ +sfftw_plan_r2r__ +sfftw_plan_r2r_1d_ +sfftw_plan_r2r_1d__ +sfftw_plan_r2r_2d_ +sfftw_plan_r2r_2d__ +sfftw_plan_r2r_3d_ +sfftw_plan_r2r_3d__ +sfftw_plan_with_nthreads_ +sfftw_plan_with_nthreads__ +sfftw_print_plan_ +sfftw_print_plan__ +sfftw_set_timelimit_ +sfftw_set_timelimit__ diff --git a/libraries/timefrequency/methods/analysismethod.h b/libraries/timefrequency/methods/analysismethod.h new file mode 100644 index 00000000000..c4f801d6a77 --- /dev/null +++ b/libraries/timefrequency/methods/analysismethod.h @@ -0,0 +1,18 @@ +#ifndef ANALYSISMETHOD_H +#define ANALYSISMETHOD_H + +#include "helpers/analysisIO.h" + +namespace TIMEFREQUENCYLIB { + +class AnalysisMethod +{ +public: + AnalysisMethod() = default; + + virtual bool compute(TimeFrequencyInput input, TimeFrequencyResult output) = 0; + virtual bool validateSettings() = 0; + virtual TimeFrequencyResult getResult() = 0; +}; +}//namespace +#endif // ANALYSISMETHOD_H diff --git a/libraries/timefrequency/methods/helpers/.Rhistory b/libraries/timefrequency/methods/helpers/.Rhistory new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/timefrequency/methods/helpers/analysisIO.h b/libraries/timefrequency/methods/helpers/analysisIO.h new file mode 100644 index 00000000000..bd796cf3213 --- /dev/null +++ b/libraries/timefrequency/methods/helpers/analysisIO.h @@ -0,0 +1,30 @@ +#ifndef ANALYSISSETTINGS_H +#define ANALYSISSETTINGS_H + +#include +#include + +namespace TIMEFREQUENCYLIB { + +struct AnalysisSettings +{ + float sampling_rate; + float freq_low; + float freq_high; + int input_size; +}; + +struct TimeFrequencyInput +{ + TimeFrequencyInput(Eigen::MatrixXd); +}; + +struct TimeFrequencyResult +{ + template + std::complex getArray(); + + Eigen::MatrixXcd getEigenMatrix(); +}; +}//namepace +#endif // ANALYSISSETTINGS_H diff --git a/libraries/timefrequency/methods/helpers/convolver.cpp b/libraries/timefrequency/methods/helpers/convolver.cpp new file mode 100644 index 00000000000..278f548ac66 --- /dev/null +++ b/libraries/timefrequency/methods/helpers/convolver.cpp @@ -0,0 +1,200 @@ +#include "convolver.h" +#include "fftw.h" + +#include +#include +#include + +using namespace TIMEFREQUENCYLIB; + +std::mutex fftw_mutex; + + +int nextpow2(int x) +{ + if (x < 0) + return 0; + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; +} + + std::complex conj(const std::complex& z) +{ + return std::complex(z.real(), -z.imag()); +} + + + + +void convolver::initialize(int signal_size, int kernel_size) +{ + _signal_size = signal_size; + _kernel_size = kernel_size; + _method = method::fft_convolution; + _shape = shape::same; + _operation = operation::convolution; + _convol_size = _signal_size + _kernel_size - 1; + + + switch (_method) + { + case method::fft_convolution: + _segment_size = 0; + _segment_count = 0; + _fft_size = nextpow2(_convol_size); + + alloc_fft_buffers(_fft_size); + break; + + default: + exit(-1); + } + +} + +void convolver::clear() +{ + _signal_size = 0; + _kernel_size = 0; + _convol_size = 0; + _fft_size = 0; + _segment_count = 0; + _segment_size = 0; + _shape = shape::same; + _operation = operation::convolution; + _method = method::automatic; + + fftw_mutex.lock(); + if (_signal_buffer) fftwf_free(_signal_buffer); + if (_fft_fwd) fftwf_destroy_plan(_fft_fwd); + if (_fft_rev) fftwf_destroy_plan(_fft_rev); + fftw_mutex.unlock(); + + _signal_buffer = nullptr; + _kernel_buffer = nullptr; + _output_buffer = nullptr; + _fft_fwd = nullptr; + _fft_rev = nullptr; +} + + + +void convolver::assign_kernel(std::complex* kernel, int size) +{ + int n = std::min(size, _kernel_size); + if (_method == method::fft_convolution || + _method == method::fft_overlap_add) + { + for (int i = 0; i < n; ++i) + _kernel_buffer[i] = kernel[i]; + + prepare_fft_kernel(); + } +} + + + + +void convolver::prepare_fft_kernel() +{ + for (int i = _kernel_size; i < _fft_size; ++i) + _kernel_buffer[i] = std::complex(); + + fftwf_execute_dft(_fft_fwd, _kernel_buffer, _kernel_buffer); + + // prepare kernel + float norm = float(1.0 / _fft_size); + if (_operation == operation::correlation) + { + for (int i = 0; i < _fft_size; ++i) + _kernel_buffer[i] = conj(_kernel_buffer[i]); + } + else + { + for (int i = 0; i < _fft_size; ++i) + _kernel_buffer[i] *= norm; + } +} + + + +void convolver::alloc_fft_buffers(int fft_size) +{ + fftw_mutex.lock(); + _signal_buffer = reinterpret_cast*>(fftwf_malloc(size_t(_fft_size) * 3 * sizeof(std::complex))); + _kernel_buffer = _signal_buffer + _fft_size; + _output_buffer = _kernel_buffer + _fft_size; + _fft_fwd = fftwf_plan_dft_1d(_fft_size, nullptr, nullptr, FFTW_FORWARD, FFTW_ESTIMATE); + _fft_rev = fftwf_plan_dft_1d(_fft_size, nullptr, nullptr, FFTW_BACKWARD, FFTW_ESTIMATE); + fftw_mutex.unlock(); + + if (!_signal_buffer || !_fft_fwd || !_fft_rev) + exit(-1); + + std::memset(_signal_buffer, 0, size_t(_fft_size) * 3 * sizeof(std::complex)); +} + + + + +void convolver::apply_fft_kernel() +{ + fftwf_execute_dft(_fft_fwd, _signal_buffer, _output_buffer); + + for (int i = 0; i < _fft_size; ++i) + _output_buffer[i] = _output_buffer[i] * _kernel_buffer[i]; + + fftwf_execute_dft(_fft_rev, _output_buffer, _output_buffer); +} + + + + +void convolver::conv_r2c_same(float* signal, std::complex* out) +{ + if (_method == method::fft_convolution) + { + for (int i = 0; i < _signal_size; ++i) _signal_buffer[i] = std::complex(signal[i]); + for (int i = _signal_size; i < _fft_size; ++i) _signal_buffer[i] = std::complex(); + + apply_fft_kernel(); + + auto opb = _output_buffer + _kernel_size / 2; + for (int i = 0; i < _signal_size; ++i) + out[i] = opb[i]; + } + else if (_method == method::fft_overlap_add) + { + for (int i = 0; i < _signal_size; ++i) + out[i] = std::complex(); + + int r_begin = 0; + while (r_begin < _signal_size) + { + int r_count = std::min(r_begin + _segment_size, _signal_size) - r_begin; + + for (int i = 0; i < r_count; ++i) _signal_buffer[i] = std::complex(signal[r_begin + i]); + for (int i = r_count; i < _segment_size; ++i) _signal_buffer[i] = std::complex(); + + apply_fft_kernel(); + + int w_begin = std::max(r_begin - _kernel_size / 2, 0); + int b_offset = std::max(_kernel_size / 2 - r_begin, 0); + int w_count = std::min(_fft_size - b_offset, _signal_size - w_begin - b_offset); + + auto cxbuf = _output_buffer + b_offset; + for (int i = 0; i < w_count; ++i) + out[w_begin + i] += cxbuf[i]; + + r_begin += _segment_size; + } + } +} + + + diff --git a/libraries/timefrequency/methods/helpers/convolver.h b/libraries/timefrequency/methods/helpers/convolver.h new file mode 100644 index 00000000000..70a23225ba5 --- /dev/null +++ b/libraries/timefrequency/methods/helpers/convolver.h @@ -0,0 +1,75 @@ +#pragma once +#include + +namespace TIMEFREQUENCYLIB { + +class convolver +{ +public: + enum class method + { + automatic, + time_domain, + fft_overlap_add, + fft_convolution + }; + + enum class shape + { + same, + full + }; + + enum class operation + { + convolution, + correlation + }; + + +public: + convolver(int signal_size, int kernel_size) + { + initialize(signal_size, kernel_size); + } + + ~convolver() + { + clear(); + } + + void initialize(int signal_size, int kernel_size); + void clear(); + + void conv_r2c_same(float* signal, std::complex* output); + void assign_kernel(std::complex* kernel, int size); + +protected: + void prepare_fft_kernel(); + void alloc_fft_buffers(int fft_size); + void apply_fft_kernel(); + + +protected: + int _signal_size = 0; + int _kernel_size = 0; + int _convol_size = 0; + int _fft_size = 0; + int _segment_size = 0; + int _segment_count = 0; + shape _shape; + method _method; + operation _operation; + +private: + void *_fft_fwd = nullptr; + void *_fft_rev = nullptr; + std::complex *_signal_buffer = nullptr; + std::complex *_output_buffer = nullptr; + std::complex *_kernel_buffer = nullptr; + +private: + static const int default_segment_size = 512; +}; + +} diff --git a/libraries/timefrequency/methods/helpers/morlet.h b/libraries/timefrequency/methods/helpers/morlet.h new file mode 100644 index 00000000000..d465e070db3 --- /dev/null +++ b/libraries/timefrequency/methods/helpers/morlet.h @@ -0,0 +1,72 @@ +#pragma once +#include +#include +#include + +namespace TIMEFREQUENCYLIB { + +static float morlet_SD_factor = 2.5f; +static float morlet_SD_spread = 6; +static float pi_f = 3.14159265359f; + +class morlet +{ +public: + morlet(float center_freq, float cycle_count, float sampling_rate) + { + float SD = (cycle_count / 2) * (1 / center_freq) / morlet_SD_factor; + int wl_size = int(2 * std::floor(std::round(SD * sampling_rate * morlet_SD_spread) / 2) + 1); + int half_size = wl_size / 2; + + _data.resize(wl_size); + float integral; + std::vector gauss(std::move(gausswin(wl_size, morlet_SD_spread / 2, integral))); + + float igsum = 1.f / integral; + float isd = 1.f / sampling_rate; + + for (int i = 0; i < wl_size; ++i) + { + float t = (i - half_size) * isd; + _data[i] = gauss[i] * expj(2 * pi_f * center_freq * t) * igsum; + } + } + + + int size() { return int(_data.size()); } + + std::complex* data() { return _data.data(); } + + +protected: + static std::vector gausswin(int n, float alpha, float& integral) + { + int halfsize = n / 2; + float idiv = alpha / halfsize; + + std::vector result(n); + double acc = 0; + for (int i = 0; i < n; ++i) + { + float t = (i - halfsize) * idiv; + result[i] = std::exp(-(t * t) * 0.5f); + acc += result[i]; + } + + integral = float(acc); + return result; + } + + static std::complex expj(float arg) + { + return std::complex(std::cos(arg), std::sin(arg)); + } + + + + std::vector> _data; + + +}; + +} diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp new file mode 100644 index 00000000000..45a04fa694a --- /dev/null +++ b/libraries/timefrequency/methods/superlets.cpp @@ -0,0 +1,139 @@ +#include "superlets.h" + +#include + +using namespace TIMEFREQUENCYLIB; + +Superlets::Superlets(SuperletSettings& settings) + : m_settings(settings) +{ + +} + +bool Superlets::validateSettings() +{ + +} + +bool Superlets::compute(TimeFrequencyInput input, TimeFrequencyResult output) +{ +// size_t input_size = m_settings.input_size; + +// for (size_t i_freq = 0; i_freq < m_superlets.size(); ++i_freq) +// { +// // initialize the pooling buffer +// std::fill(m_pooling_buffer.begin(), m_pooling_buffer.end(), 1.0); + +// if (m_superlets[i_freq].size() > 1) +// { +// // superresolution +// size_t n_wavelets = size_t(std::floor(m_orders[i_freq])); +// double r_factor = 1.0 / n_wavelets; + +// for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) +// { +// // perform R2C convolution +// m_filters[i_freq][i_wave]->conv_r2c_same(input, m_conv_buffer.data()); + +// // pool with exponent = 1 +// for (size_t i = 0; i < input_size; ++i) +// { +// m_pooling_buffer[i] *= 2.0 * mag_sqr(m_conv_buffer[i]); +// } +// } + +// // determine if fractional superlet should be used +// if (fractional(m_orders[i_freq]) != 0 && // order is fractional +// m_settings.fractional && // we are allowed to use it +// m_superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it +// { +// double exponent = fractional(m_orders[i_freq]); +// r_factor = 1.0 / (n_wavelets + exponent); + +// // perform convolution with the last wavelet +// m_filters[i_freq].back()->conv_r2c_same(input, m_conv_buffer.data()); + +// // pool with fractional exponent +// for (size_t i = 0; i < input_size; ++i) +// { +// m_pooling_buffer[i] *= std::pow(2.0 * mag_sqr(m_conv_buffer[i]), exponent); +// } +// } + +// // perform geometric mean and save to output buffer +// for (size_t i = 0; i < input_size; ++i) +// { +// output[i] += float(std::pow(m_pooling_buffer[i], r_factor)); +// } +// } +// else +// { +// // standard CWT +// m_filters[i_freq].front()->conv_r2c_same(input, m_conv_buffer.data()); + +// for (size_t i = 0; i < input_size; ++i) +// output[i] += float(2.0 * mag_sqr(m_conv_buffer[i])); +// } + +// output += input_size; +// } + + return false; +} + +void Superlets::initFromSettings() +{ + m_filters.resize(m_settings.freq_count); + m_superlets.resize(m_settings.freq_count); + m_conv_buffer.resize(m_settings.input_size); + m_pooling_buffer.resize(m_settings.input_size); + + m_frequencies = linspace(m_settings.freq_low, m_settings.freq_high, m_settings.freq_count); + m_orders = linspace(m_settings.resolution_low, m_settings.resolution_high, m_settings.freq_count); + + if (!m_settings.fractional) + std::transform(m_orders.begin(), m_orders.end(), m_orders.begin(), std::roundf); + + for (size_t i_freq = 0; i_freq < m_settings.freq_count; ++i_freq) + { + float center_freq = m_frequencies[i_freq]; + int n_wavelets = int(std::ceil(m_orders[i_freq])); + + for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) + { + float ncyc = m_settings.multiplicative + ? (i_wave + 1) * m_settings.wavelet_cycles + : m_settings.wavelet_cycles + i_wave; + + m_superlets[i_freq] .emplace_back(center_freq, ncyc, m_settings.sampling_rate); + m_filters[i_freq] .push_back(new convolver(m_settings.input_size, m_superlets[i_freq].back().size())); + m_filters[i_freq] .back()->assign_kernel(m_superlets[i_freq].back().data(), m_superlets[i_freq].back().size()); + } + } +} + +std::vector Superlets::linspace(float from, float to, int n) +{ + if (n <= 0) return { }; + else if (n == 1) return { from }; + else + { + std::vector result(n); + + float dv = (to - from) / (n - 1); + for (size_t i = 0; i < result.size(); ++i) + result[i] = from + i * dv; + + return result; + } +} + +float Superlets::mag_sqr(const std::complex& z) +{ + return z.real() * z.real() + z.imag() * z.imag(); +} + +float Superlets::fractional(float x) +{ + return x - (int)x; +} diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h new file mode 100644 index 00000000000..9e77f71c113 --- /dev/null +++ b/libraries/timefrequency/methods/superlets.h @@ -0,0 +1,56 @@ +#ifndef SUPERLETS_H +#define SUPERLETS_H + +#include "analysismethod.h" + +#include "helpers/analysisIO.h" +#include "helpers/morlet.h" +#include "helpers/convolver.h" + +#include + +namespace TIMEFREQUENCYLIB { + +struct SuperletSettings : public AnalysisSettings{ + int freq_count; + float wavelet_cycles; + float resolution_low; + float resolution_high; + + bool multiplicative; + bool fractional; +}; + +class Superlets : public AnalysisMethod +{ + using filter_bank = std::vector; + using superlet = std::vector; +public: + Superlets() = delete; + Superlets(SuperletSettings& settings); + + virtual bool compute(TimeFrequencyInput input, TimeFrequencyResult output); + virtual bool validateSettings(); + +protected: + + void initFromSettings(); + + std::vector linspace(float from, float to, int n); + + float mag_sqr(const std::complex& z); + + float fractional(float x); + + SuperletSettings& m_settings; + std::vector m_filters; + std::vector m_superlets; + std::vector> m_conv_buffer; + std::vector m_pooling_buffer; + std::vector m_frequencies; + std::vector m_orders; + +}; +} //namespace + +#endif // SUPERLETS_H diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro new file mode 100644 index 00000000000..e9fe36a250a --- /dev/null +++ b/libraries/timefrequency/timefrequency.pro @@ -0,0 +1,82 @@ + +include(../../mne-cpp.pri) + +TEMPLATE = lib + +CONFIG += skip_target_version_ext + +QT += network concurrent +QT -= gui + +DEFINES += TIMEFREQUENCY_LIBRARY + +DESTDIR = $${MNE_LIBRARY_DIR} + +TARGET = TimeFrequency +TARGET = $$join(TARGET,,mnecpp,) +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lmnecppUtilsd \ +} else { + LIBS += -lmnecppUtils \ +} + +SOURCES += \ + methods/helpers/convolver.cpp \ + interface.cpp \ + methods/superlets.cpp \ + timefrequencyanalyzer.cpp \ + wavelet_spectrum_analyzer.cpp + + +HEADERS += \ + methods/helpers/convolver.h \ + methods/analysismethod.h \ + methods/helpers/analysisIO.h \ + methods/helpers/morlet.h \ + methods/superlets.h \ + timefrequencyanalyzer.h \ + wavelet_spectrum_analyzer.h + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} + +header_files.files = $${HEADERS} +header_files.path = $${MNE_INSTALL_INCLUDE_DIR}/events + +INSTALLS += header_files + +contains(MNECPP_CONFIG, withCodeCov) { + QMAKE_CXXFLAGS += --coverage + QMAKE_LFLAGS += --coverage +} + +win32:!contains(MNECPP_CONFIG, static) { + QMAKE_POST_LINK += $$QMAKE_COPY $$shell_path($${MNE_LIBRARY_DIR}/$${TARGET}.dll) $${MNE_BINARY_DIR} +} + +macx { + QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/ +} + +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { +win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -llibfftw3f-3 + +else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -llibfftw3f-3d + +else:unix: LIBS += -L$$PWD/lib/ -llibfftw3f-3 +} + +INCLUDEPATH += $$PWD/include +DEPENDPATH += $$PWD/include diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp new file mode 100644 index 00000000000..6f7d7b256cc --- /dev/null +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -0,0 +1,20 @@ +#include "timefrequencyanalyzer.h" + +using namespace TIMEFREQUENCYLIB; + +TimeFrequencyAnalyzer::TimeFrequencyAnalyzer(AnalysisMethod& method) + : m_method(method) +{ + +} + +TimeFrequencyResult TimeFrequencyAnalyzer::compute(TimeFrequencyInput input) +{ + bool validSettings = m_method.validateSettings(); + + TimeFrequencyResult output; + + if(validSettings){ + m_method.compute(input, output); + } +} diff --git a/libraries/timefrequency/timefrequencyanalyzer.h b/libraries/timefrequency/timefrequencyanalyzer.h new file mode 100644 index 00000000000..f700ab77ab3 --- /dev/null +++ b/libraries/timefrequency/timefrequencyanalyzer.h @@ -0,0 +1,23 @@ +#ifndef TIMEFREQUENCYANALYZER_H +#define TIMEFREQUENCYANALYZER_H + +#include + +#include "methods/analysismethod.h" +#include "methods/helpers/analysisIO.h" + +namespace TIMEFREQUENCYLIB { + +class TimeFrequencyAnalyzer +{ +public: + TimeFrequencyAnalyzer(AnalysisMethod& method); + + TimeFrequencyResult compute(TimeFrequencyInput input); + +private: + AnalysisMethod& m_method; +}; +}//namespace + +#endif // TIMEFREQUENCYANALYZER_H diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.cpp b/libraries/timefrequency/wavelet_spectrum_analyzer.cpp new file mode 100644 index 00000000000..413e25b6f40 --- /dev/null +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.cpp @@ -0,0 +1,152 @@ +//#include "wavelet_spectrum_analyzer.h" +//#include + +//using namespace TIMEFREQUENCYLIB; + +//std::vector linspace(float from, float to, int n) +//{ +// if (n <= 0) return { }; +// else if (n == 1) return { from }; +// else +// { +// std::vector result(n); + +// float dv = (to - from) / (n - 1); +// for (size_t i = 0; i < result.size(); ++i) +// result[i] = from + i * dv; + +// return result; +// } +//} + + +//__forceinline float mag_sqr(const std::complex& z) +//{ +// return z.real() * z.real() + z.imag() * z.imag(); +//} + +//__forceinline float fractional(float x) +//{ +// return x - (int)x; +//} + + + + +//wavelet_spectrum_analyzer::wavelet_spectrum_analyzer(wavelet_analyzer_settings set) +//{ +// _set = set; +// _filters .resize(_set.freq_count); +// _superlets .resize(_set.freq_count); +// _conv_buffer .resize(_set.input_size); +// _pooling_buffer .resize(_set.input_size); +// _frequencies = linspace(_set.freq_low, _set.freq_high, _set.freq_count); +// _orders = linspace(_set.resolution_low, _set.resolution_high, _set.freq_count); + +// if (!_set.fractional) +// std::transform(_orders.begin(), _orders.end(), _orders.begin(), std::roundf); + +// for (size_t i_freq = 0; i_freq < _set.freq_count; ++i_freq) +// { +// float center_freq = _frequencies[i_freq]; +// int n_wavelets = int(std::ceilf(_orders[i_freq])); + +// for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) +// { +// float ncyc = _set.multiplicative +// ? (i_wave + 1) * _set.wavelet_cycles +// : _set.wavelet_cycles + i_wave; + +// _superlets[i_freq] .emplace_back(center_freq, ncyc, _set.sampling_rate); +// _filters[i_freq] .push_back(new convolver(_set.input_size, _superlets[i_freq].back().size())); +// _filters[i_freq] .back()->assign_kernel(_superlets[i_freq].back().data(), _superlets[i_freq].back().size()); +// } +// } +//} + +//wavelet_spectrum_analyzer::~wavelet_spectrum_analyzer() +//{ +// for (auto& fb : _filters) +// { +// for (auto& conv : fb) +// delete conv; +// fb.clear(); +// } + +// _filters .clear(); +// _superlets .clear(); +// _pooling_buffer .clear(); +// _frequencies .clear(); +// _orders .clear(); +// _conv_buffer .clear(); +// _set = wavelet_analyzer_settings(); +//} + + + +//void wavelet_spectrum_analyzer::analyze(float* input, float* output) +//{ +// size_t input_size = _set.input_size; + +// for (size_t i_freq = 0; i_freq < _superlets.size(); ++i_freq) +// { +// // initialize the pooling buffer +// std::fill(_pooling_buffer.begin(), _pooling_buffer.end(), 1.0); + +// if (_superlets[i_freq].size() > 1) +// { +// // superresolution +// size_t n_wavelets = size_t(std::floorf(_orders[i_freq])); +// double r_factor = 1.0 / n_wavelets; + +// for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) +// { +// // perform R2C convolution +// _filters[i_freq][i_wave]->conv_r2c_same(input, _conv_buffer.data()); + +// // pool with exponent = 1 +// for (size_t i = 0; i < input_size; ++i) +// { +// _pooling_buffer[i] *= 2.0 * mag_sqr(_conv_buffer[i]); +// } +// } + +// // determine if fractional superlet should be used +// if (fractional(_orders[i_freq]) != 0 && // order is fractional +// _set.fractional && // we are allowed to use it +// _superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it +// { +// double exponent = fractional(_orders[i_freq]); +// r_factor = 1.0 / (n_wavelets + exponent); + +// // perform convolution with the last wavelet +// _filters[i_freq].back()->conv_r2c_same(input, _conv_buffer.data()); + +// // pool with fractional exponent +// for (size_t i = 0; i < input_size; ++i) +// { +// _pooling_buffer[i] *= std::pow(2.0 * mag_sqr(_conv_buffer[i]), exponent); +// } +// } + +// // perform geometric mean and save to output buffer +// for (size_t i = 0; i < input_size; ++i) +// { +// output[i] += float(std::pow(_pooling_buffer[i], r_factor)); +// } +// } +// else +// { +// // standard CWT +// _filters[i_freq].front()->conv_r2c_same(input, _conv_buffer.data()); + +// for (size_t i = 0; i < input_size; ++i) +// output[i] += float(2.0 * mag_sqr(_conv_buffer[i])); +// } + +// output += input_size; +// } +//} + + + diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.h b/libraries/timefrequency/wavelet_spectrum_analyzer.h new file mode 100644 index 00000000000..f903c2711e1 --- /dev/null +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.h @@ -0,0 +1,46 @@ +#pragma once +//#include "morlet.h" +//#include "convolver.h" + + +//namespace TIMEFREQUENCYLIB { + +//struct wavelet_analyzer_settings +//{ +// float sampling_rate; +// float freq_low; +// float freq_high; +// int freq_count; +// int input_size; +// float wavelet_cycles; +// float resolution_low; +// float resolution_high; +// bool multiplicative; +// bool fractional; +//}; + + +//class wavelet_spectrum_analyzer +//{ +// using filter_bank = std::vector; +// using superlet = std::vector; + +//public: +// wavelet_spectrum_analyzer(wavelet_analyzer_settings set); +// ~wavelet_spectrum_analyzer(); + +// void analyze(float* input, float* output); + +//protected: +// wavelet_analyzer_settings _set; +// std::vector _filters; +// std::vector _superlets; +// std::vector> _conv_buffer; +// std::vector _pooling_buffer; +// std::vector _frequencies; +// std::vector _orders; + +//}; + +//} + diff --git a/libraries/utils/spectrogram.cpp b/libraries/utils/spectrogram.cpp index e9f0bd9e1eb..9a02e1fd102 100644 --- a/libraries/utils/spectrogram.cpp +++ b/libraries/utils/spectrogram.cpp @@ -36,13 +36,13 @@ //============================================================================================================= #include "spectrogram.h" - //============================================================================================================= // EIGEN INCLUDES //============================================================================================================= #include #include +#include //============================================================================================================= // QT INCLUDES @@ -64,12 +64,11 @@ using namespace Eigen; // DEFINE MEMBER METHODS //============================================================================================================= -MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) +MatrixXd Spectrogram::makeSpectrogram(const VectorXd& signal, qint32 windowSize) { //QElapsedTimer timer; //timer.start(); - - signal.array() -= signal.mean(); +// signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount()*2; int iStepsSize = signal.rows()/iThreadSize; @@ -79,7 +78,7 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) dataTemp.vecInputData = signal; dataTemp.window_size = windowSize; if(dataTemp.window_size == 0) { - dataTemp.window_size = signal.rows()/15; + dataTemp.window_size = signal.rows()/5; } for (int i = 0; i < iThreadSize; ++i) { @@ -92,6 +91,8 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) dataTemp.iRangeHigh = iThreadSize*iStepsSize+iResidual; lData.append(dataTemp); +// MatrixXd resultMat = compute(dataTemp); + QFuture resultMat = QtConcurrent::mappedReduced(lData, compute, reduce); @@ -103,6 +104,44 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) //============================================================================================================= +MatrixXcd Spectrogram::makeComplexSpectrogram(const VectorXd& signal, qint32 windowSize) +{ + //QElapsedTimer timer; + //timer.start(); +// signal.array() -= signal.mean(); + QList lData; + int iThreadSize = QThread::idealThreadCount(); + int iStepsSize = signal.rows()/iThreadSize; + int iResidual = signal.rows()%iThreadSize; + + SpectogramInputData dataTemp; + dataTemp.vecInputData = signal; + dataTemp.window_size = windowSize; + if(dataTemp.window_size == 0) { + dataTemp.window_size = signal.rows()/15; + } + + for (int i = 0; i < iThreadSize; ++i) { + dataTemp.iRangeLow = i*iStepsSize; + dataTemp.iRangeHigh = i*iStepsSize+iStepsSize; + lData.append(dataTemp); + } + + dataTemp.iRangeLow = iThreadSize*iStepsSize; + dataTemp.iRangeHigh = iThreadSize*iStepsSize+iResidual; + lData.append(dataTemp); + + QFuture resultMat = QtConcurrent::mappedReduced(lData, + computeComplex, + reduceComplex); + resultMat.waitForFinished(); + + //qDebug() << "Spectrogram::make_spectrogram - timer.elapsed()" << timer.elapsed(); + return resultMat.result(); +} + +//============================================================================================================= + VectorXd Spectrogram::gaussWindow(qint32 sample_count, qreal scale, quint32 translation) { VectorXd gauss = VectorXd::Zero(sample_count); @@ -123,11 +162,42 @@ MatrixXd Spectrogram::compute(const SpectogramInputData& inputData) #ifdef EIGEN_FFTW_DEFAULT fftw_make_planner_thread_safe(); #endif + MatrixXd tf_matrix; +// Eigen::FFT fft; +// MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); +// VectorXd envelope, windowed_sig, real_coeffs; +// VectorXcd fft_win_sig; +// qint32 window_size = inputData.window_size; + +// for(quint32 translate = inputData.iRangeLow; translate < inputData.iRangeHigh; translate++) { +// envelope = gaussWindow(inputData.vecInputData.rows(), window_size, translate); + +// windowed_sig = VectorXd::Zero(inputData.vecInputData.rows()); +// fft_win_sig = VectorXcd::Zero(inputData.vecInputData.rows()); + +// windowed_sig = inputData.vecInputData.array() * envelope.array();\ + +// fft.fwd(fft_win_sig, windowed_sig); + +// real_coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array().abs2(); + +// tf_matrix.col(translate) = real_coeffs; +// } + + return tf_matrix; +} + +//============================================================================================================= +MatrixXcd Spectrogram::computeComplex(const SpectogramInputData& inputData) +{ + #ifdef EIGEN_FFTW_DEFAULT + fftw_make_planner_thread_safe(); + #endif Eigen::FFT fft; - MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); - VectorXd envelope, windowed_sig, real_coeffs; - VectorXcd fft_win_sig; + MatrixXcd tf_matrix = MatrixXcd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); + VectorXd envelope, windowed_sig; + VectorXcd fft_win_sig, coeffs; qint32 window_size = inputData.window_size; for(quint32 translate = inputData.iRangeLow; translate < inputData.iRangeHigh; translate++) { @@ -140,9 +210,9 @@ MatrixXd Spectrogram::compute(const SpectogramInputData& inputData) fft.fwd(fft_win_sig, windowed_sig); - real_coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array().abs2(); + coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array(); - tf_matrix.col(translate) = real_coeffs; + tf_matrix.col(translate) = coeffs; } return tf_matrix; @@ -159,3 +229,15 @@ void Spectrogram::reduce(MatrixXd &resultData, resultData += data; } } + +//============================================================================================================= + +void Spectrogram::reduceComplex(MatrixXcd &resultData, + const MatrixXcd &data) +{ + if(resultData.size() == 0) { + resultData = data; + } else { + resultData += data; + } +} diff --git a/libraries/utils/spectrogram.h b/libraries/utils/spectrogram.h index b7a3276931c..a4c2ae672bb 100644 --- a/libraries/utils/spectrogram.h +++ b/libraries/utils/spectrogram.h @@ -73,9 +73,21 @@ class UTILSSHARED_EXPORT Spectrogram * * @return spectrogram-matrix (tf-representation of the input signal). */ - static Eigen::MatrixXd makeSpectrogram(Eigen::VectorXd signal, + static Eigen::MatrixXd makeSpectrogram(const Eigen::VectorXd& signal, qint32 windowSize); + //========================================================================================================= + /** + * Calculates the spectrogram (tf-representation) of a given signal + * + * @param[in] signal input-signal to calculate spectrogram of + * @param[in] windowSize size of the window which is used (resolution in time an frequency is depending on it) + * + * @return spectrogram-matrix (tf-representation of the input signal) + */ + static Eigen::MatrixXcd makeComplexSpectrogram(const Eigen::VectorXd& signal, + qint32 windowSize); + private: //========================================================================================================= /** @@ -101,6 +113,16 @@ class UTILSSHARED_EXPORT Spectrogram */ static Eigen::MatrixXd compute(const SpectogramInputData& data); + //========================================================================================================= + /** + * Calculates the spectogram matrix for a given input data matrix. + * + * @param[in] data The input data. + * + * @return The spectogram matrix. + */ + static Eigen::MatrixXcd computeComplex(const SpectogramInputData& data); + //========================================================================================================= /** * Sums up (reduces) the in parallel processed spectogram matrix. @@ -110,6 +132,16 @@ class UTILSSHARED_EXPORT Spectrogram */ static void reduce(Eigen::MatrixXd &resultData, const Eigen::MatrixXd &data); + + //========================================================================================================= + /** + * Sums up (reduces) the in parallel processed spectogram matrix. + * + * @param[out] resultData The result data. + * @param[in] data The incoming, temporary result data. + */ + static void reduceComplex(Eigen::MatrixXcd &resultData, + const Eigen::MatrixXcd &data); }; }//namespace diff --git a/libraries/utils/tracer.cpp b/libraries/utils/tracer.cpp new file mode 100644 index 00000000000..1e83a29302b --- /dev/null +++ b/libraries/utils/tracer.cpp @@ -0,0 +1,223 @@ +#include "tracer.h" + +using namespace UTILSLIB; + +int Tracer::numTracers = 0; +bool Tracer::isEnabled = false; +std::ofstream Tracer::outputFileStream; +bool Tracer::isFirstEvent = true; +bool Tracer::outFileMutex = false; +long long Tracer::zeroTime = 0; + +Tracer::Tracer(const std::string &function, const std::string &file, const int num) +: printToTerminal(false) +, fileName(file) +, threadId("0") +, beginTime(0) +, endTime(0) +, durationMicros(0) +, durationMilis(0.0) +{ + if (isEnabled) + { + initialize(function, file, num); + writeBeginEvent(); + } +} + +Tracer::~Tracer() +{ + if (isEnabled) + { + registerFinalTime(); + writeEndEvent(); + if (printToTerminal) + { + calculateDuration(); + printDurationMiliSec(); + } + } +} + +void Tracer::enable(const std::string &jsonFileName) +{ + outputFileStream.open(jsonFileName); + outFileMutex = false; + writeHeader(); + setZeroTime(); + isEnabled = true; +} + +void Tracer::enable() +{ + enable("default_tracer_file.json"); +} + +void Tracer::disable() +{ + if (Tracer::isEnabled) + { + writeFooter(); + outputFileStream.close(); + outFileMutex = false; + isEnabled = false; + } +} + +void Tracer::start(const std::string &jsonFileName) +{ + enable(jsonFileName); +} + +void Tracer::start() +{ + enable(); +} + +void Tracer::stop() +{ + disable(); +} + +void Tracer::traceQuantity(std::string &name, long val) +{ + long long timeNow = getTimeNow() - zeroTime; + std::string s; + s.append("{\"name\":\"").append(name).append("\",\"ph\":\"C\",\"ts\":"); + s.append(std::to_string(timeNow)).append(",\"pid\":1,\"tid\":1"); + s.append(",\"args\":{\"").append(name).append("\":").append(std::to_string(val)).append("}}\n"); + writeToFile(s); +} + +void Tracer::initialize(const std::string &function, const std::string &file, const int num) +{ + numTracers++; + + initializeFunctionName(function); + initializeFile(file); + lineNumber = num; + + registerThreadId(); + registerInitialTime(); +} + +void Tracer::setZeroTime() +{ + zeroTime = getTimeNow(); +} + +void Tracer::registerInitialTime() +{ + beginTime = getTimeNow() - zeroTime; +} + +void Tracer::registerFinalTime() +{ + endTime = getTimeNow() - zeroTime; +} + +long long Tracer::getTimeNow() +{ + auto timeNow = std::chrono::high_resolution_clock::now(); + return std::chrono::time_point_cast(timeNow).time_since_epoch().count(); +} + +void Tracer::registerThreadId() +{ + auto longId = std::hash{}(std::this_thread::get_id()); + threadId = std::to_string(longId).substr(0, 5); +} + +void Tracer::initializeFunctionName(const std::string &function) +{ + functionName = function; + std::string pattern(" __cdecl"); + size_t pos = functionName.find("__cdecl"); + if (pos != std::string::npos) + functionName.replace(pos, pattern.length(), ""); +} + +void Tracer::initializeFile(std::string file) +{ + std::string patternIn("\\"); + std::string patternOut("\\\\"); + size_t start_pos = 0; + while ((start_pos = file.find(patternIn, start_pos)) != std::string::npos) + { + file.replace(start_pos, 1, patternOut); + start_pos += patternOut.length(); + } + + fileName = file; +} + +void Tracer::calculateDuration() +{ + durationMicros = endTime - beginTime; + durationMilis = durationMicros * 0.001; +} + +void Tracer::printDurationMiliSec() +{ + std::cout << "Scope: " << fileName << " - " << functionName << " DurationMs: " << durationMilis << "ms.\n"; +} + +void Tracer::writeHeader() +{ + writeToFile("{\"displayTimeUnit\": \"ms\",\"traceEvents\":[\n"); +} + +void Tracer::writeFooter() +{ + writeToFile("]}"); +} + +void Tracer::writeToFile(const std::string &str) +{ + if (outFileMutex) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + writeToFile(str); + } + else + { + outFileMutex = true; + outputFileStream << str; + outputFileStream.flush(); + outFileMutex = false; + } +} + +void Tracer::writeBeginEvent() +{ + std::string s; + if (!isFirstEvent) + s.append(","); + + s.append("{\"name\":\"").append(functionName).append("\",\"cat\":\"bst\","); + s.append("\"ph\":\"B\",\"ts\":").append(std::to_string(beginTime)).append(",\"pid\":1,\"tid\":"); + s.append(threadId).append(",\"args\":{\"file path\":\"").append(fileName).append("\",\"line number\":"); + s.append(std::to_string(lineNumber)).append("}}\n"); + writeToFile(s); + isFirstEvent = false; +} + +void Tracer::writeEndEvent() +{ + std::string s; + s.append(",{\"name\":\"").append(functionName).append("\",\"cat\":\"bst\","); + s.append("\"ph\":\"E\",\"ts\":").append(std::to_string(endTime)).append(",\"pid\":1,\"tid\":"); + s.append(threadId).append(",\"args\":{\"file path\":\"").append(fileName).append("\",\"line number\":"); + s.append(std::to_string(lineNumber)).append("}}\n"); + writeToFile(s); +} + +bool Tracer::printToTerminalIsSet() +{ + return printToTerminal; +} + +void Tracer::setPrintToTerminal(bool s) +{ + printToTerminal = s; +} diff --git a/libraries/utils/tracer.h b/libraries/utils/tracer.h new file mode 100644 index 00000000000..1a1e458ff22 --- /dev/null +++ b/libraries/utils/tracer.h @@ -0,0 +1,129 @@ +#ifndef TRACER_H +#define TRACER_H + +#include "utils_global.h" + +#include +#include +#include +#include +#include + +#define __PRETTY_FUNCTION__ __FUNCSIG__ + +#ifdef TRACE +#define __TRACE_FUNC() UTILSLIB::Tracer _t__LINE__(__PRETTY_FUNCTION__, __FILE__, __LINE__); +#define __TRACER_ENABLE UTILSLIB::Tracer::enable("chrome_tracer.json"); +#define __TRACER_DISABLE UTILSLIB::Tracer::disable(); +#define __TRACE_VALUE(NAME, VALUE) UTILSLIB::Tracer::traceQuantity(NAME, VALUE); +#else +#define __TRACE_FUNC() PEPE +#define __TRACER_ENABLE PEPE +#define __TRACER_DISABLE PEPE +#define __TRACE_VALUE() PEPE +#endif + +#ifdef TRACE_MEMORY +#define __TRACE_MEMORY_REPORT \ + std::cout << "Total Memory Allocated : " << 0.000001 * __totalMemAllocated << " MB\n";\ + std::cout << "Total Memory Deleted : " << 0.000001 * __totalMemDeleted << " MB\n";\ + std::cout << "Total Memory Diff : " << 0.000001 * (__totalMemAllocated - __totalMemDeleted) << " MB\n";\ + +size_t __totalMemAllocated(0); +size_t __totalMemDeleted(0); +void *operator new(size_t size) +{ + // std::cout << "Allocating " << size << " Bytes.\n"; + __totalMemAllocated += size; + return malloc(size); +} + +void operator delete(void *memory, size_t size) +{ + // std::cout << "Deleting " << size << " Bytes.\n"; + __totalMemDeleted += size; + free(memory); +} +#else +#define __TRACE_MEMORY_REPORT +#endif + +namespace UTILSLIB +{ + + class UTILSSHARED_EXPORT Tracer + { + public: + Tracer(const std::string &function, const std::string &file, const int num); + + ~Tracer(); + + static void enable(const std::string &jsonFileName); + + static void enable(); + + static void disable(); + + static void start(const std::string &jsonFileName); + + static void start(); + + static void stop(); + + static void traceQuantity(std::string &name, long val); + + bool printToTerminalIsSet(); + + void setPrintToTerminal(bool s); + + private: + static void writeHeader(); + + static void writeFooter(); + + static void writeToFile(const std::string &str); + + static void setZeroTime(); + + static long long getTimeNow(); + + void initialize(const std::string &function, const std::string &file, const int num); + + void initializeFunctionName(const std::string &function); + + void initializeFile(std::string file); + + void registerInitialTime(); + + void registerFinalTime(); + + void registerThreadId(); + + void calculateDuration(); + + void printDurationMiliSec(); + + void writeBeginEvent(); + + void writeEndEvent(); + + static int numTracers; + static bool isEnabled; + static std::ofstream outputFileStream; + static bool isFirstEvent; + static bool outFileMutex; + static long long zeroTime; + + bool printToTerminal; + std::string functionName; + std::string fileName; + int lineNumber; + std::string threadId; + long long beginTime; + long long endTime; + long long durationMicros; + double durationMilis; + }; + +} // namespace ChromeTracer +#endif // TRACER_H diff --git a/libraries/utils/utils.pro b/libraries/utils/utils.pro index 96110f033cc..6f00878640e 100644 --- a/libraries/utils/utils.pro +++ b/libraries/utils/utils.pro @@ -45,6 +45,7 @@ QT -= gui QT += concurrent DEFINES += UTILS_LIBRARY +DEFINES += TRACE DESTDIR = $${MNE_LIBRARY_DIR}