Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[ENH] Time frequency plugin #918

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/applications/mne_scan/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_subdirectory(fiffsimulator)
add_subdirectory(ftbuffer)
add_subdirectory(babymeg)
add_subdirectory(natus)
add_subdirectory(randomdata)

# Algorithm Plugin
add_subdirectory(rtcmne)
Expand All @@ -27,6 +28,7 @@ add_subdirectory(neuronalconnectivity)
add_subdirectory(writetofile)
add_subdirectory(hpi)
add_subdirectory(rtfwd)
add_subdirectory(timefrequency)

option(WITH_BRAINFLOW "Build brainflow plugin" OFF)
option(WITH_LSL "Build LSL plugin" OFF)
Expand Down
73 changes: 73 additions & 0 deletions src/applications/mne_scan/plugins/randomdata/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
cmake_minimum_required(VERSION 3.14)
project(scan_randomdata LANGUAGES CXX)

#Handle qt uic, moc, rrc automatically
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Widgets Network Concurrent)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Network Concurrent)

set(SOURCES
randomdata.cpp
randomdata_global.cpp
)

set(HEADERS
randomdata.h
randomdata_global.h
)

set(FILE_TO_UPDATE randomdata_global.cpp)

set(SOURCE_PATHS ${SOURCES})
list(TRANSFORM SOURCE_PATHS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
set_source_files_properties(${FILE_TO_UPDATE} PROPERTIES OBJECT_DEPENDS "${SOURCE_PATHS}")

add_library(${PROJECT_NAME} ${SOURCES} ${HEADERS})

set(FFTW_LIBS "")

if(USE_FFTW)
if (WIN32)
set(FFTW_LIBS
${FFTW_DIR_LIBS}/libfftw3-3.dll
${FFTW_DIR_LIBS}/libfftw3f-3.dll
${FFTW_DIR_LIBS}/libfftwf3l-3.dll
)
target_include_directories(${PROJECT_NAME} PRIVATE ${FFTW_DIR_INCLUDE})
elseif(UNIX AND NOT APPLE)
set(FFTW_LIBS ${FFTW_DIR_LIBS}/lib/libfftw3.so)
target_include_directories(${PROJECT_NAME} PRIVATE ${FFTW_DIR_INCLUDE}/api)
endif()
endif()

target_include_directories(${PROJECT_NAME} PUBLIC ../)

target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Concurrent
eigen
mne_disp
mne_utils
mne_fiff
# mne_fs
# mne_mne
# mne_fwd
# mne_inverse
# mne_rtprocessing
# mne_connectivity
# mne_events
scDisp
scShared
scMeas
${FFTW_LIBS})

target_compile_definitions(${PROJECT_NAME} PRIVATE SCAN_RANDOMDATA_PLUGIN MNE_GIT_HASH_SHORT="${MNE_GIT_HASH_SHORT}" MNE_GIT_HASH_LONG="${MNE_GIT_HASH_LONG}")

if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(${PROJECT_NAME} PRIVATE STATICBUILD QT_STATICPLUGIN)
endif()
304 changes: 304 additions & 0 deletions src/applications/mne_scan/plugins/randomdata/randomdata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
//=============================================================================================================
/**
* @file randomdata.cpp
* @author Juan GarciaPrieto <jgarciaprieto@mgh.harvard.edu>;
* Gabriel B Motta <gbmotta@mgh.harvard.edu>;
* @since 0.1.0
* @date February, 2023
*
* @section LICENSE
*
* Copyright (C) 2023, Juan G Prieto, Gabriel B 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 RandomData class.
*
*/

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <utility>

#include "randomdata/randomdata.h"

#include <fiff/fiff_info.h>
#include <scMeas/realtimemultisamplearray.h>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QSettings>
#include <QDebug>
#include <QLabel>
#include <numeric>
#include <vector>

//=============================================================================================================
// EIGEN INCLUDES
//=============================================================================================================


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

namespace RANDOMDATAPLUGIN {

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

// QSharedPointer<FIFFLIB::FiffInfo> createFiffInfo(int numChassis,
// int numChannels) {
// QSharedPointer<FIFFLIB::FiffInfo> pFiffInfo;
// pFiffInfo->sfreq = 1000.0f;
// pFiffInfo->nchan = numChassis * numChannels;
// pFiffInfo->chs.clear();
//
// for (int chan_i = 0; chan_i < pFiffInfo->nchan; ++chan_i) {
// FIFFLIB::FiffChInfo channel;
// channel.ch_name = QString("%1:%2").arg(numChannels, 2).arg(chan_i, 2);
// channel.kind = FIFFV_MEG_CH;
// channel.unit = FIFF_UNIT_T;
// channel.unit_mul = FIFF_UNITM_NONE;
// channel.chpos.coil_type = FIFFV_COIL_NONE;
// pFiffInfo->chs.append(channel);
// pFiffInfo->ch_names.append(channel.ch_name);
// }
// }

// QSharedPointer<FIFFLIB::FiffInfo>
// createFiffInfo(std::vector<std::vector<int>> fl_chassis, float sfreq = 1000.f) {
// QSharedPointer<FIFFLIB::FiffInfo> pFiffInfo;
// pFiffInfo->sfreq = sfreq;
// pFiffInfo->chs.clear();
//
// int total_channels = 0;
// int chassis_num = 0;
// for (auto &chassis : fl_chassis) {
// for (auto &sensor : chassis) {
// FIFFLIB::FiffChInfo channel;
// channel.ch_name = QString("%1:%2").arg(chassis_num, 2).arg(sensor, 2);
// channel.kind = FIFFV_MEG_CH;
// channel.unit = FIFF_UNIT_T;
// channel.unit_mul = FIFF_UNITM_NONE;
// channel.chpos.coil_type = FIFFV_COIL_NONE;
// pFiffInfo->chs.append(channel);
// pFiffInfo->ch_names.append(channel.ch_name);
// ++total_channels;
// }
// }
// pFiffInfo->nchan = total_channels;
//
// return pFiffInfo;
// }
//
// QSharedPointer<FIFFLIB::FiffInfo>
// createFiffInfo(int numChassis, int numChannels, float sfreq = 1000.f) {
// std::vector<std::vector<int>> fl;
// for (int i = 0; i < numChassis; ++i) {
// std::vector<int> ch(numChannels);
// std::iota(ch.begin(), ch.end(), 1);
// fl.push_back(std::move(ch));
// }
// return createFiffInfo(fl, sfreq);
// }

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

RandomData::RandomData()
: m_pFiffInfo(QSharedPointer<FIFFLIB::FiffInfo>(new FIFFLIB::FiffInfo()))
{
m_pRTMSA_RandomData = SCSHAREDLIB::PluginOutputData<
SCMEASLIB::RealTimeMultiSampleArray>::create(this, "RandomData Out",
"RandomDataPlguin output");
m_pRTMSA_RandomData->measurementData()->setName(this->getName());
m_outputConnectors.append(m_pRTMSA_RandomData);
}

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

RandomData::~RandomData()
{
if(this->isRunning()) {
RandomData::stop();
}
}

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

QSharedPointer<SCSHAREDLIB::AbstractPlugin> RandomData::clone() const
{
QSharedPointer<SCSHAREDLIB::AbstractPlugin> pRandomDataClone(new RandomData());
return pRandomDataClone;
}

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

void RandomData::init()
{
m_pFiffInfo->sfreq = 1000.0f;
m_pFiffInfo->nchan = 32;
m_pFiffInfo->chs.clear();

for (int chan_i = 0; chan_i < m_pFiffInfo->nchan; ++chan_i) {
FIFFLIB::FiffChInfo channel;
channel.ch_name = "Ch. " + QString::number(chan_i);
channel.kind = FIFFV_MEG_CH;
channel.unit = FIFF_UNIT_T;
channel.unit_mul = FIFF_UNITM_NONE;
channel.chpos.coil_type = FIFFV_COIL_NONE;
m_pFiffInfo->chs.append(channel);
m_pFiffInfo->ch_names.append(channel.ch_name);
}

m_pRTMSA_RandomData->measurementData()->initFromFiffInfo(
m_pFiffInfo); // if(m_pCircularBuffer->pop(matData)) {
m_pRTMSA_RandomData->measurementData()->setMultiArraySize(1);
m_pRTMSA_RandomData->measurementData()->setVisibility(true);

matData.resize(m_pFiffInfo->nchan, 200);

qDebug() << " ^^^^^^^^^^^^^^^^^^^^ Init Random Data (....again)";
}

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

void RandomData::unload()
{
}

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

bool RandomData::start()
{
// Init circular buffer to transmit data from the producer to this thread
// if(!m_pCircularBuffer) {
// m_pCircularBuffer = QSharedPointer<CircularBuffer_Matrix_double>(new
// CircularBuffer_Matrix_double(10));
// }
//
// //Setup fiff info before setting up the RMTSA because we need it to init
// the RTMSA setUpFiffInfo();
//
// //Set the channel size of the RMTSA - this needs to be done here and NOT in
// the init() function because the user can change the number of channels
// during runtime
// m_pRMTSA_Natus->measurementData()->initFromFiffInfo(m_pFiffInfo);
// m_pRMTSA_Natus->measurementData()->setMultiArraySize(1);
//
QThread::start();
//
// // Start the producer
// m_pNatusProducer =
// QSharedPointer<NatusProducer>::create(m_iSamplesPerBlock,
// m_iNumberChannels); m_pNatusProducer->moveToThread(&m_pProducerThread);
// connect(m_pNatusProducer.data(), &NatusProducer::newDataAvailable,
// this, &RandomData::onNewDataAvailable, Qt::DirectConnection);
// m_pProducerThread.start();

return true;
}

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

bool RandomData::stop()
{
requestInterruption();
wait(500);
m_pRTMSA_RandomData->measurementData()->clear();

return true;
}

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

SCSHAREDLIB::AbstractPlugin::PluginType RandomData::getType() const
{
return SCSHAREDLIB::AbstractPlugin::PluginType::_ISensor;
}

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

QString RandomData::getName() const
{
return "Random Data";
}

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

QWidget* RandomData::setupWidget()
{

// guiWidget = std::make_unique<RandomDataPluginGUI>();

// NatusSetup* widget = new NatusSetup(this);//widget is later destroyed by
// CentralWidget - so it has to be created everytime new

// init properties dialog
// widget->initGui();

// auto *frame = new QWidget();
// frame->setLayout(new QHBoxLayout());
//
// auto *flWidget = new DISPLIB::RandomDataView(2, 16);
//
// frame->layout()->addWidget(flWidget);
// flWidget->setBlinkState(0, 2, true);
// flWidget->setBlinkState(1, 5, true);

return new QLabel("Random data Baby!");
}

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

void RandomData::run() {

for (;;) {
// gather the data

matData = Eigen::MatrixXd::Random(m_pFiffInfo->nchan, 200);
matData *= 4e-12;

msleep(200);

if (isInterruptionRequested())
break;
m_pRTMSA_RandomData->measurementData()->setValue(matData);
}
}

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

QString RandomData::getBuildInfo() {
return QString(buildDateTime()) + QString(" - ") + QString(buildHash());
}

} // namespace RANDOMDATAPLUGIN

Loading