Skip to content

WIP [ENH] Time Frequency Plugins for MNE Scan and MNE Analyze #785

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 57 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e35b5a5
ENH: add tf view and model classes
gabrielbmotta Apr 6, 2021
bc55890
ENH: skeleton for timefrequency plugin in mneanalyze
gabrielbmotta Apr 6, 2021
d9c0c79
ENH: scene and items for layout view
gabrielbmotta Apr 6, 2021
7642ad6
ENH: subclassing abstractview
gabrielbmotta Apr 7, 2021
dd01477
ENH: setting up plugin
gabrielbmotta Apr 7, 2021
48e4a2a
ENH: setting up views
gabrielbmotta Apr 7, 2021
fff0e7f
ENH: init layout view, tabs in plugin
gabrielbmotta Apr 8, 2021
af26eb5
ENh: timefrequency in lib layer, raw data and events to plugin
gabrielbmotta Apr 9, 2021
42e7eee
ENH: trying qml for view
gabrielbmotta Apr 9, 2021
b8aa1d1
ENH: embedding qml
gabrielbmotta Apr 9, 2021
d9b38b0
ENH: functions for redrawing layout. catching avg model in analyze
gabrielbmotta Apr 12, 2021
8f3645d
ENH: graphics layout formatting and plotting
gabrielbmotta Apr 12, 2021
a35d842
ENH: passing channel select data to plot layout
gabrielbmotta Apr 13, 2021
0bcacfa
MAINT: testing drawing by had with paintEvent function
gabrielbmotta Apr 13, 2021
e0415cd
ENH: drawing tf chart
gabrielbmotta Apr 14, 2021
46a6273
MAINT: separate draw functionality
gabrielbmotta Apr 15, 2021
e3f1d52
ENH: class for creating color gradient
gabrielbmotta Apr 15, 2021
b3c1572
ENH: color library
gabrielbmotta Apr 15, 2021
d311df7
MAINT: remove qml files
gabrielbmotta Apr 16, 2021
f3794d5
MAINT: add button and start sending data to function
gabrielbmotta Apr 19, 2021
5080cfa
FIX: fix namspace to avoid runtime error
gabrielbmotta Apr 19, 2021
e17887c
ENH:testing tfplot with one channel and plotting
gabrielbmotta Apr 20, 2021
c5c49bb
ENH: calculation on all channels in the pased data
gabrielbmotta Apr 20, 2021
d44fe86
ENH: return data from timefrequencymodel
gabrielbmotta Apr 21, 2021
7eb2d32
Creating and setting model, passing data matrix to plot
gabrielbmotta Apr 21, 2021
e79daf9
ENH: getting tfplot into lyout view (or trying to)
gabrielbmotta Apr 21, 2021
27758fd
ENH: single view based of tfplot
gabrielbmotta Apr 22, 2021
3de6ae7
ENH: control view. testing qgraphicsobject vs qwidget for layout vciew
gabrielbmotta Apr 22, 2021
76d6f4e
ENH: starting mne scan pluign for time frequency
gabrielbmotta Apr 22, 2021
f68db82
ENH: function to return spectrogram as complex
gabrielbmotta Apr 23, 2021
99c9d6f
ENH: leaving matrix as complex
gabrielbmotta Apr 26, 2021
1cc513f
MAINT: gettign channel selection to diplay average
gabrielbmotta Apr 26, 2021
46080f4
DEBUG: add guard for having data and channel select info to aprevent …
gabrielbmotta Apr 26, 2021
d1950c9
ENH: averaging tf in real time and updating display
gabrielbmotta Apr 27, 2021
641ce1c
DEBUG: taking real values after computing absolute values
gabrielbmotta Apr 27, 2021
c76ea91
ENH: measurment and measurement widget
gabrielbmotta Apr 27, 2021
6facf99
ENH: rttfwidget and measurement for real time tfview
gabrielbmotta Apr 28, 2021
bd29616
ENH: rolling queue of data comined into single matrix for processing
gabrielbmotta Apr 29, 2021
aea5354
ENH: change storage of data in mne scan plugin
gabrielbmotta Apr 30, 2021
0d41f0c
MAINT: function to compute epoch tf properly
gabrielbmotta May 5, 2021
a13a3b0
ENH: getting tf data from each epoch
gabrielbmotta May 7, 2021
9929922
MAINT: get matrix size, init to zeroes
gabrielbmotta May 7, 2021
ca15558
ENH: view now uses painter instread of qgraphicsscene
gabrielbmotta May 7, 2021
dfb76b2
ENH: draw gradient bar
gabrielbmotta May 10, 2021
e58927c
Add disp params, remove scan plugin from loading, add libs to static …
gabrielbmotta May 10, 2021
0e08945
Changes to resolution and compute structure
gabrielbmotta May 11, 2021
66ae6a1
tracer working
juangpc May 12, 2021
786479a
new superlet toolbox
juangpc May 13, 2021
7872822
ENH: time freuqency analyzer class
gabrielbmotta May 17, 2021
4e36ea8
ENH: methods as separate classes which analyser calls
gabrielbmotta May 17, 2021
0de01ce
ENH: samll changes and examples
gabrielbmotta May 17, 2021
95c5b94
ENH: moving functionality to Superlets class
gabrielbmotta May 18, 2021
008d8a4
ENG: load data in example
gabrielbmotta May 18, 2021
8f37dfd
ENH: more superlet work
gabrielbmotta May 18, 2021
242b5c7
moving functions to superlets class
gabrielbmotta May 20, 2021
dca3670
change input
gabrielbmotta May 24, 2021
ac8d2d8
remove tracer and unused sections of supelets to get project to build.
gabrielbmotta May 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion applications/mne_analyze/mne_analyze/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -109,5 +110,7 @@ int main(int argc, char *argv[])
QScopedPointer<AnalyzeCore> pAnalyzeCore (new AnalyzeCore);
pAnalyzeCore->showMainWindow();

return app.exec();
int main_return_value(app.exec());

return main_return_value;
}
3 changes: 2 additions & 1 deletion applications/mne_analyze/mne_analyze/mne_analyze.pro
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#==============================================================================================================

include(../../../mne-cpp.pri)

DEFINES += TRACE
TEMPLATE = app

QT += gui widgets network opengl svg concurrent charts
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 0 additions & 6 deletions applications/mne_analyze/plugins/dataloader/dataloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,6 @@ namespace DISPLIB {
namespace DATALOADERPLUGIN
{

//=============================================================================================================
// DATALOADERPLUGIN FORWARD DECLARATIONS
//=============================================================================================================

class DataLoaderControl;

//=============================================================================================================
/**
* DataLoader Plugin
Expand Down
1 change: 1 addition & 0 deletions applications/mne_analyze/plugins/plugins.pro
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
306 changes: 306 additions & 0 deletions applications/mne_analyze/plugins/timefrequency/timefrequency.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
//=============================================================================================================
/**
* @file timefrequency.cpp
* @author Gabriel Motta <[email protected]>
* @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 <anShared/Management/communicator.h>
#include <anShared/Management/analyzedata.h>
#include <anShared/Model/averagingdatamodel.h>
#include <anShared/Model/eventmodel.h>

#include <disp/viewers/progressview.h>
#include <disp/viewers/timefrequencyview.h>
#include <disp/viewers/timefrequencylayoutview.h>
#include <disp/viewers/timefrequencysettingsview.h>
#include <disp/viewers/helpers/timefrequencymodel.h>
#include <disp/viewers/helpers/selectionsceneitem.h>
#include <disp/viewers/helpers/evokedsetmodel.h>
#include <disp/plots/tfplot.h>

#include <fiff/fiff_evoked_set.h>
#include <fiff/fiff_evoked.h>

#include <rtprocessing/timefrequency.h>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace TIMEFREQUENCYPLUGIN;
using namespace ANSHAREDLIB;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

TimeFrequency::TimeFrequency()
: m_sSettingsPath("MNEANALYZE/TimeFrequency")
, m_pAvgModel(Q_NULLPTR)
{
m_pEvokedModel = QSharedPointer<DISPLIB::EvokedSetModel>(new DISPLIB::EvokedSetModel());
loadSettings();
}

//=============================================================================================================

TimeFrequency::~TimeFrequency()
{

}

//=============================================================================================================

QSharedPointer<AbstractPlugin> TimeFrequency::clone() const
{
QSharedPointer<TimeFrequency> pTimeFrequencyClone(new TimeFrequency);
return pTimeFrequencyClone;
}

//=============================================================================================================

void TimeFrequency::init()
{
m_pCommu = new Communicator(this);

m_pTFModel = QSharedPointer<DISPLIB::TimeFrequencyModel>(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<Event> e)
{
switch (e->getType()) {
case EVENT_TYPE::SELECTED_MODEL_CHANGED:{
onModelChanged(e->getData().value<QSharedPointer<ANSHAREDLIB::AbstractModel> >());
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<EVENT_TYPE> TimeFrequency::getEventSubscriptions(void) const
{
QVector<EVENT_TYPE> 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<ANSHAREDLIB::AbstractModel> pNewModel)
{
if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_AVERAGING_MODEL) {
m_pAvgModel = qSharedPointerCast<AveragingDataModel>(pNewModel);
m_pEvokedModel->setEvokedSet(m_pAvgModel->data(QModelIndex()).value<QSharedPointer<FIFFLIB::FiffEvokedSet>>());
m_pTimeFreqView->setEvokedSetModel(m_pEvokedModel);
}
if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_FIFFRAW_MODEL) {
m_pFiffRawModel = qSharedPointerCast<FiffRawViewModel>(pNewModel);
}
}

//=============================================================================================================

void TimeFrequency::setChannelSelection(const QVariant &data)
{
if(data.value<DISPLIB::SelectionItem*>()->m_sViewsToApply.contains("layoutview")){
if(m_pTimeFreqLayoutView){
m_pTimeFreqLayoutView->channelSelectionChanged(data);
}
}
if(data.value<DISPLIB::SelectionItem*>()->m_sViewsToApply.contains("butterflyview")){
// if(data.value<DISPLIB::SelectionItem*>()->m_bShowAll){
// emit showAllChannels();
// } else {
// emit showSelectedChannels(data.value<DISPLIB::SelectionItem*>()->m_iChannelNumber);
// }

}

if(m_pTFModel){
if(data.value<DISPLIB::SelectionItem*>()->m_sViewsToApply.contains("butterflyview")){
m_pTFModel->setChannelSelection(data.value<DISPLIB::SelectionItem*>()->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);
}
Loading