diff --git a/applications/mne_analyze/libs/anShared/Management/analyzedata.h b/applications/mne_analyze/libs/anShared/Management/analyzedata.h index ca82958f703..7273e8e4806 100644 --- a/applications/mne_analyze/libs/anShared/Management/analyzedata.h +++ b/applications/mne_analyze/libs/anShared/Management/analyzedata.h @@ -290,6 +290,20 @@ class ANSHAREDSHARED_EXPORT AnalyzeData : public QObject BIDS_DIPOLE); break; } + case ANSHAREDLIB_FORWARDSOLUTION_MODEL:{ + pItem->setData(data); + m_pData->addToData(pItem, + m_SelectedFunctionalData, + BIDS_UNKNOWN); + break; + } + case ANSHAREDLIB_SOURCEESTIMATE_MODEL:{ + pItem->setData(data); + m_pData->addToData(pItem, + m_SelectedFunctionalData, + BIDS_UNKNOWN); + break; + } case ANSHAREDLIB_FIFFRAW_MODEL: { pItem->setData(data); QModelIndex index = m_SelectedItem; @@ -299,7 +313,7 @@ class ANSHAREDSHARED_EXPORT AnalyzeData : public QObject break; } default:{ - qWarning() << "[AnalyzeData::addModel] Model type not supported"; + qWarning() << "[AnalyzeData::addModel] Model type not recognized."; break; } } diff --git a/applications/mne_analyze/libs/anShared/Model/forwardsolutionmodel.cpp b/applications/mne_analyze/libs/anShared/Model/forwardsolutionmodel.cpp new file mode 100644 index 00000000000..e31d188c42e --- /dev/null +++ b/applications/mne_analyze/libs/anShared/Model/forwardsolutionmodel.cpp @@ -0,0 +1,119 @@ +//============================================================================================================= +/** + * @file forwardsolutionmodel.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date October, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, 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 ForwardSolutionModel Class. + * + */ + + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "forwardsolutionmodel.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// Eigen INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace ANSHAREDLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +ForwardSolutionModel::ForwardSolutionModel(QObject* parent) +:AbstractModel(parent) +{ +} + +//============================================================================================================= + +ForwardSolutionModel::ForwardSolutionModel(QSharedPointer pFwdSolution, + QObject* parent) +: AbstractModel( parent) +, m_pFwdSolution(pFwdSolution) +{ +} + +//============================================================================================================= + +int ForwardSolutionModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return 1; +} + +//============================================================================================================= + +int ForwardSolutionModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return 1; +} + +//============================================================================================================= + +QVariant ForwardSolutionModel::data(const QModelIndex &index, + int role) const +{ + Q_UNUSED(index); + Q_UNUSED(role); + + return QVariant::fromValue(m_pFwdSolution); +} + +//============================================================================================================= + +Qt::ItemFlags ForwardSolutionModel::flags(const QModelIndex &index) const +{ + return QAbstractItemModel::flags(index); +} + +//============================================================================================================= + +QSharedPointer ForwardSolutionModel::getFwdSolution() +{ + return m_pFwdSolution; +} diff --git a/applications/mne_analyze/libs/anShared/Model/forwardsolutionmodel.h b/applications/mne_analyze/libs/anShared/Model/forwardsolutionmodel.h new file mode 100644 index 00000000000..c44192a9f08 --- /dev/null +++ b/applications/mne_analyze/libs/anShared/Model/forwardsolutionmodel.h @@ -0,0 +1,174 @@ +//============================================================================================================= +/** + * @file forwardsolutionmodel.h + * @author Gabriel Motta + * @since 0.1.9 + * @date October, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, 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 ForwardSolutionModel Class. + * + */ + +#ifndef FORWARDSOLUTIONMODEL_H +#define FORWARDSOLUTIONMODEL_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../anshared_global.h" +#include "../Utils/types.h" +#include "abstractmodel.h" + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace MNELIB { + class MNEForwardSolution; +} + +//============================================================================================================= +// DEFINE NAMESPACE ANSHAREDLIB +//============================================================================================================= + +namespace ANSHAREDLIB { + +//============================================================================================================= +class ANSHAREDSHARED_EXPORT ForwardSolutionModel : public AbstractModel +{ + Q_OBJECT +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for ForwardSolutionModel. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for ForwardSolutionModel. */ + +public: + //========================================================================================================= + ForwardSolutionModel(QObject* parent = Q_NULLPTR); + + //========================================================================================================= + ForwardSolutionModel(QSharedPointer pFwdSolution, + QObject* parent = Q_NULLPTR); + + //========================================================================================================= + /** + * Returns the number of rows in the model + * + * @param[in] parent The parent index. + */ + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + //========================================================================================================= + /** + * Returns the number of columns in the model + * + * @param[in] parent The parent index. + */ + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + //========================================================================================================= + /** + * Returns the data stored under the given role for the index. + * + * @param[in] index The index that referres to the requested item. + * @param[in] role The requested role. + */ + virtual QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const override; + + //========================================================================================================= + /** + * Returns the item flags for the given index. + * + * @param[in] index The index that referres to the requested item. + */ + Qt::ItemFlags flags(const QModelIndex & index) const override; + + //========================================================================================================= + /** + * The type of this model (CovarianceModel) + * + * @return The type of this model (CovarianceModel). + */ + inline MODEL_TYPE getType() const override; + + //========================================================================================================= + /** + * Returns the index for the item in the model specified by the given row, column and parent index. + * Currently only Qt::DisplayRole is supported. + * Index rows reflect channels, first column is channel names, second is raw data. + * + * @param[in] row The specified row. + * @param[in] column The specified column. + * @param[in] parent The parent index. + */ + inline QModelIndex index(int row, + int column, + const QModelIndex &parent = QModelIndex()) const override; + + //========================================================================================================= + /** + * Returns the parent index of the given index. + * In this Model the parent index in always QModelIndex(). + * + * @param[in] index The index that referres to the child. + */ + inline QModelIndex parent(const QModelIndex &index) const override; + + QSharedPointer getFwdSolution(); + +private: + QSharedPointer m_pFwdSolution; +}; + +//============================================================================================================= +// INLINE DEFINITIONS +//============================================================================================================= + +inline MODEL_TYPE ForwardSolutionModel::getType() const +{ + return MODEL_TYPE::ANSHAREDLIB_FORWARDSOLUTION_MODEL; +} + +//============================================================================================================= + +QModelIndex ForwardSolutionModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index); + return QModelIndex(); +} + +//============================================================================================================= + +QModelIndex ForwardSolutionModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return createIndex(row, column); +} + +}//namespace + +#endif // FORWARDSOLUTIONMODEL_H diff --git a/applications/mne_analyze/libs/anShared/Model/sourceestimatemodel.cpp b/applications/mne_analyze/libs/anShared/Model/sourceestimatemodel.cpp new file mode 100644 index 00000000000..48b12db55ef --- /dev/null +++ b/applications/mne_analyze/libs/anShared/Model/sourceestimatemodel.cpp @@ -0,0 +1,192 @@ +//============================================================================================================= +/** + * @file sourceestimatemodel.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date October, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, 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 SourceEstimateModel Class. + * + */ + + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + + +#include "sourceestimatemodel.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// Eigen INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace ANSHAREDLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +SourceEstimateModel::SourceEstimateModel(QObject* parent) +:AbstractModel(parent) +{ +} + +//============================================================================================================= + +SourceEstimateModel::SourceEstimateModel(QSharedPointer pSourceEstimate, + QSharedPointer pFwdSolution, + QSharedPointer pCoord, + QSharedPointer pAnnotationSet, + QSharedPointer pSurfaceSet, + QObject* parent ) +: AbstractModel( parent) +, m_pSourceEstimate(pSourceEstimate) +, m_pFwdSolution(pFwdSolution) +, m_pCoord(pCoord) +, m_pAnnotationSet(pAnnotationSet) +, m_pSurfaceSet(pSurfaceSet) +{ +} + +//============================================================================================================= + +int SourceEstimateModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return 1; +} + +//============================================================================================================= + +int SourceEstimateModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return 1; +} + +//============================================================================================================= + +QVariant SourceEstimateModel::data(const QModelIndex &index, + int role) const +{ + Q_UNUSED(index); + Q_UNUSED(role); + + return QVariant::fromValue(m_pFwdSolution); +} + +//============================================================================================================= + +Qt::ItemFlags SourceEstimateModel::flags(const QModelIndex &index) const +{ + return QAbstractItemModel::flags(index); +} + +//============================================================================================================= + +QSharedPointer SourceEstimateModel::getSourceEstimate() const +{ + return m_pSourceEstimate; +} + +//============================================================================================================= + +QSharedPointer SourceEstimateModel::getFwdSolution() const +{ + return m_pFwdSolution; +} + +//============================================================================================================= + +QSharedPointer SourceEstimateModel::getMRIHeadTrans() const +{ + return m_pCoord; +} + +//============================================================================================================= + +QSharedPointer SourceEstimateModel::getAnnotationSet() const +{ + return m_pAnnotationSet; +} + +//============================================================================================================= + +QSharedPointer SourceEstimateModel::getSurfSet() const +{ + return m_pSurfaceSet; +} + +//============================================================================================================= + +void SourceEstimateModel::setSourceEstimate(QSharedPointer pSourceEstimate) +{ + m_pSourceEstimate = pSourceEstimate; +} + +//============================================================================================================= + +void SourceEstimateModel::setFwdSolution(QSharedPointer pFwdSol) +{ + m_pFwdSolution = pFwdSol; +} + +//============================================================================================================= + +void SourceEstimateModel::setMRIHeadTrans( QSharedPointer pCoord) +{ + m_pCoord = pCoord; +} + +//============================================================================================================= + +void SourceEstimateModel::setAnnotationSet(QSharedPointer pAnnot) +{ + m_pAnnotationSet = pAnnot; +} + +//============================================================================================================= + +void SourceEstimateModel::setSurfSet(QSharedPointer pSurfSet) +{ + m_pSurfaceSet = pSurfSet; +} diff --git a/applications/mne_analyze/libs/anShared/Model/sourceestimatemodel.h b/applications/mne_analyze/libs/anShared/Model/sourceestimatemodel.h new file mode 100644 index 00000000000..06f58130be5 --- /dev/null +++ b/applications/mne_analyze/libs/anShared/Model/sourceestimatemodel.h @@ -0,0 +1,202 @@ +//============================================================================================================= +/** + * @file sourceestimatemodel.h + * @author Gabriel Motta + * @since 0.1.9 + * @date October, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, 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 SourceEstimateModel Class. + * + */ + +#ifndef SOURCEESTIMATEMODEL_H +#define SOURCEESTIMATEMODEL_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../anshared_global.h" +#include "../Utils/types.h" +#include "abstractmodel.h" + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace FIFFLIB{ + class FiffCoordTrans; +} + +namespace FSLIB{ + class AnnotationSet; + class SurfaceSet; +} + +namespace MNELIB { + class MNEForwardSolution; + class MNESourceEstimate; +} + +//============================================================================================================= +// DEFINE NAMESPACE ANSHAREDLIB +//============================================================================================================= + +namespace ANSHAREDLIB { + +//============================================================================================================= +class ANSHAREDSHARED_EXPORT SourceEstimateModel : public AbstractModel +{ + Q_OBJECT +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for SourceEstimateModel. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for SourceEstimateModel. */ + +public: + //========================================================================================================= + SourceEstimateModel(QObject* parent = Q_NULLPTR); + + //========================================================================================================= + SourceEstimateModel(QSharedPointer pSourceEstimate = Q_NULLPTR, + QSharedPointer pFwdSolution = Q_NULLPTR, + QSharedPointer pCoord = Q_NULLPTR, + QSharedPointer pAnnotationSet = Q_NULLPTR, + QSharedPointer pSurfaceSet = Q_NULLPTR, + QObject* parent = Q_NULLPTR); + + //========================================================================================================= + /** + * Returns the number of rows in the model + * + * @param[in] parent The parent index. + */ + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + //========================================================================================================= + /** + * Returns the number of columns in the model + * + * @param[in] parent The parent index. + */ + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + //========================================================================================================= + /** + * Returns the data stored under the given role for the index. + * + * @param[in] index The index that referres to the requested item. + * @param[in] role The requested role. + */ + virtual QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const override; + + //========================================================================================================= + /** + * Returns the item flags for the given index. + * + * @param[in] index The index that referres to the requested item. + */ + Qt::ItemFlags flags(const QModelIndex & index) const override; + + //========================================================================================================= + /** + * The type of this model (CovarianceModel) + * + * @return The type of this model (CovarianceModel). + */ + inline MODEL_TYPE getType() const override; + + //========================================================================================================= + /** + * Returns the index for the item in the model specified by the given row, column and parent index. + * Currently only Qt::DisplayRole is supported. + * Index rows reflect channels, first column is channel names, second is raw data. + * + * @param[in] row The specified row. + * @param[in] column The specified column. + * @param[in] parent The parent index. + */ + inline QModelIndex index(int row, + int column, + const QModelIndex &parent = QModelIndex()) const override; + + //========================================================================================================= + /** + * Returns the parent index of the given index. + * In this Model the parent index in always QModelIndex(). + * + * @param[in] index The index that referres to the child. + */ + inline QModelIndex parent(const QModelIndex &index) const override; + + QSharedPointer getSourceEstimate() const; + QSharedPointer getFwdSolution() const; + QSharedPointer getMRIHeadTrans() const; + QSharedPointer getAnnotationSet() const; + QSharedPointer getSurfSet() const; + + void setSourceEstimate(QSharedPointer pSourceEstimate); + void setFwdSolution(QSharedPointer pFwdSol); + void setMRIHeadTrans( QSharedPointer pCoord); + void setAnnotationSet(QSharedPointer pAnnot); + void setSurfSet(QSharedPointer pSurfSet); + +private: + QSharedPointer m_pSourceEstimate; + QSharedPointer m_pFwdSolution; + QSharedPointer m_pCoord; + QSharedPointer m_pAnnotationSet; + QSharedPointer m_pSurfaceSet; +}; + +//============================================================================================================= +// INLINE DEFINITIONS +//============================================================================================================= + +inline MODEL_TYPE SourceEstimateModel::getType() const +{ + return MODEL_TYPE::ANSHAREDLIB_SOURCEESTIMATE_MODEL; +} + +//============================================================================================================= + +QModelIndex SourceEstimateModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index); + return QModelIndex(); +} + +//============================================================================================================= + +QModelIndex SourceEstimateModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return createIndex(row, column); +} + +}//namespace + +#endif // SOURCEESTIMATEMODEL_H diff --git a/applications/mne_analyze/libs/anShared/Utils/types.h b/applications/mne_analyze/libs/anShared/Utils/types.h index 25623172680..611501e3249 100644 --- a/applications/mne_analyze/libs/anShared/Utils/types.h +++ b/applications/mne_analyze/libs/anShared/Utils/types.h @@ -87,7 +87,9 @@ namespace ANSHAREDLIB ANSHAREDLIB_BEMDATA_MODEL, ANSHAREDLIB_NOISE_MODEL, ANSHAREDLIB_MRICOORD_MODEL, - ANSHAREDLIB_DIPOLEFIT_MODEL + ANSHAREDLIB_DIPOLEFIT_MODEL, + ANSHAREDLIB_FORWARDSOLUTION_MODEL, + ANSHAREDLIB_SOURCEESTIMATE_MODEL }; //========================================================================================================= @@ -100,7 +102,7 @@ namespace ANSHAREDLIB PLUGIN_INIT_FINISHED, ///< [NO DATA] Send when all plugins finished initializing STATUS_BAR_MSG, ///< [QString] Send a message to the status bar (part of gui) SELECTED_MODEL_CHANGED, ///< [QSharedPointer>] Send whenever the selection changes in the datamanager plugin - NEW_EVENT_ADDED, ///< [int] event send whenever the user adds a new event in the rawdataviewer plugin + ADD_NEW_EVENT, ///< [int] event send whenever the user adds a new event in the rawdataviewer plugin EVENTS_UPDATED, ///< [NO DATA] send when events or events-groups have changed TRIGGER_REDRAW, ///< [NO DATA] send when viewer needs to be updated TRIGGER_ACTIVE_CHANGED, ///< [int] send when the trigger active state was toggled @@ -122,7 +124,8 @@ namespace ANSHAREDLIB FIDUCIAL_CHANGED, ///< [int] event send when fiducial was changed SET_DATA3D_TREE_MODEL, ///< [QSharedPointer] send when a new 3D Model is set VIEW3D_SETTINGS_CHANGED, ///< [ANSHAREDLIB::View3DParameters] send to trigger view 3D settings update - MODEL_REMOVED ///< [QSharedPointer>] send to alert plugins when model is being removed + MODEL_REMOVED, ///< [QSharedPointer>] send to alert plugins when model is being removed + SAMPLE_SELECTED }; //========================================================================================================= diff --git a/applications/mne_analyze/libs/anShared/anShared.pro b/applications/mne_analyze/libs/anShared/anShared.pro index 479ff52febf..b69bd63a7b8 100644 --- a/applications/mne_analyze/libs/anShared/anShared.pro +++ b/applications/mne_analyze/libs/anShared/anShared.pro @@ -96,14 +96,18 @@ SOURCES += \ Model/fiffrawviewmodel.cpp \ Model/eventmodel.cpp \ Model/averagingdatamodel.cpp \ + Model/forwardsolutionmodel.cpp \ Model/mricoordmodel.cpp \ Model/covariancemodel.cpp \ + Model/sourceestimatemodel.cpp \ Plugins/abstractplugin.cpp HEADERS += \ Model/dipolefitmodel.h \ + Model/forwardsolutionmodel.h \ Model/mricoordmodel.h \ Model/covariancemodel.h \ + Model/sourceestimatemodel.h \ Plugins/abstractplugin.h \ anshared_global.h \ Model/abstractmodel.h \ diff --git a/applications/mne_analyze/plugins/events/events.cpp b/applications/mne_analyze/plugins/events/events.cpp index 4230ec93997..6ee0ba456ac 100644 --- a/applications/mne_analyze/plugins/events/events.cpp +++ b/applications/mne_analyze/plugins/events/events.cpp @@ -172,7 +172,7 @@ QWidget *Events::getView() void Events::handleEvent(QSharedPointer e) { switch (e->getType()) { - case EVENT_TYPE::NEW_EVENT_ADDED: + case EVENT_TYPE::ADD_NEW_EVENT: emit newEventAvailable(e->getData().toInt()); onTriggerRedraw(); break; @@ -192,7 +192,7 @@ void Events::handleEvent(QSharedPointer e) QVector Events::getEventSubscriptions(void) const { QVector temp; - temp.push_back(NEW_EVENT_ADDED); + temp.push_back(ADD_NEW_EVENT); temp.push_back(SELECTED_MODEL_CHANGED); temp.push_back(MODEL_REMOVED); diff --git a/applications/mne_analyze/plugins/forwardsolution/forwardsolution.cpp b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.cpp new file mode 100644 index 00000000000..13cd986d0c8 --- /dev/null +++ b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.cpp @@ -0,0 +1,392 @@ +//============================================================================================================= +/** + * @file forwardsolution.cpp + * @author Gabriel Motta ; + * Juan G Prieto + * @since 0.1.9 + * @date June, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, Gabriel B Motta, Juan G Prieto. 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 ForwardSolution class defintion. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "forwardsolution.h" + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace FORWARDSOLUTIONPLUGIN; +using namespace ANSHAREDLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +ForwardSolution::ForwardSolution() +: m_pCommu(Q_NULLPTR) +, m_pFwdSettings(new FWDLIB::ComputeFwdSettings) +, m_bBusy(false) +, m_bDoRecomputation(false) +, m_bDoClustering(true) +, m_bDoFwdComputation(false) +{ + // set init values + m_pFwdSettings->solname = QCoreApplication::applicationDirPath() + "/MNE-sample-data/your-solution-fwd.fif"; + m_pFwdSettings->mriname = QCoreApplication::applicationDirPath() + "/MNE-sample-data/MEG/sample/all-trans.fif"; + m_pFwdSettings->bemname = QCoreApplication::applicationDirPath() + "/MNE-sample-data/subjects/sample/bem/sample-5120-5120-5120-bem.fif"; + m_pFwdSettings->srcname = QCoreApplication::applicationDirPath() + "/MNE-sample-data/subjects/sample/bem/sample-oct-6-src.fif"; + m_pFwdSettings->measname = QCoreApplication::applicationDirPath() + "/MNE-sample-data/MEG/sample/sample_audvis_raw.fif"; + m_pFwdSettings->transname.clear(); + m_pFwdSettings->eeg_model_name = "Default"; + m_pFwdSettings->include_meg = true; + m_pFwdSettings->include_eeg = true; + m_pFwdSettings->accurate = true; + m_pFwdSettings->mindist = 5.0f/1000.0f; + + m_sAtlasDir = QCoreApplication::applicationDirPath() + "/MNE-sample-data/subjects/sample/label"; + + m_pAnnotationSet = FSLIB::AnnotationSet::SPtr(new FSLIB::AnnotationSet(m_sAtlasDir+"/lh.aparc.a2009s.annot", m_sAtlasDir+"/rh.aparc.a2009s.annot")); +} + +//============================================================================================================= + +ForwardSolution::~ForwardSolution() +{ +} + +//============================================================================================================= + +QSharedPointer ForwardSolution::clone() const +{ + QSharedPointer pForwardSolutionClone(new ForwardSolution); + return pForwardSolutionClone; +} + +//============================================================================================================= + +void ForwardSolution::init() +{ + m_pCommu = new Communicator(this); +} + +//============================================================================================================= + +void ForwardSolution::unload() +{ + +} + +//============================================================================================================= + +QString ForwardSolution::getName() const +{ + return "Forward Solution"; +} + +//============================================================================================================= + +QMenu *ForwardSolution::getMenu() +{ + return Q_NULLPTR; +} + +//============================================================================================================= + +QWidget *ForwardSolution::getView() +{ + return Q_NULLPTR; +} + +//============================================================================================================= + +QDockWidget* ForwardSolution::getControl() +{ + m_pFwdSettingsView = new DISPLIB::FwdSettingsView(); + m_pFwdSettingsView->setSettings(m_pFwdSettings); + + QVBoxLayout* pControlLayout = new QVBoxLayout(); + pControlLayout->addWidget(m_pFwdSettingsView); + + QWidget* containerWidget = new QWidget(); + containerWidget->setLayout(pControlLayout); + + QScrollArea* pControlScrollArea = new QScrollArea(); + pControlScrollArea->setWidget(containerWidget); + + QDockWidget* pControlDock = new QDockWidget(this->getName()); + pControlDock->setWidget(pControlScrollArea); + + // connect incoming signals + connect(m_pFwdSettingsView, &DISPLIB::FwdSettingsView::recompStatusChanged, + this, &ForwardSolution::onRecompStatusChanged, Qt::UniqueConnection); + connect(m_pFwdSettingsView, &DISPLIB::FwdSettingsView::clusteringStatusChanged, + this, &ForwardSolution::onClusteringStatusChanged, Qt::UniqueConnection); + connect(m_pFwdSettingsView, &DISPLIB::FwdSettingsView::atlasDirChanged, + this, &ForwardSolution::onAtlasDirChanged, Qt::UniqueConnection); + connect(m_pFwdSettingsView, &DISPLIB::FwdSettingsView::doForwardComputation, + this, &ForwardSolution::onDoForwardComputation, Qt::UniqueConnection); + + // connect outgoing signals + connect(this, &ForwardSolution::statusInformationChanged, + m_pFwdSettingsView, &DISPLIB::FwdSettingsView::setRecomputationStatus, Qt::UniqueConnection); + connect(this, &ForwardSolution::fwdSolutionAvailable, + m_pFwdSettingsView, &DISPLIB::FwdSettingsView::setSolutionInformation, Qt::UniqueConnection); + connect(this, &ForwardSolution::clusteringAvailable, + m_pFwdSettingsView, &DISPLIB::FwdSettingsView::setClusteredInformation, Qt::UniqueConnection); + + return pControlDock; +} + +//============================================================================================================= + +void ForwardSolution::handleEvent(QSharedPointer e) +{ + switch (e->getType()) { + case EVENT_TYPE::SELECTED_MODEL_CHANGED: + onModelChanged(e->getData().value >()); + break; + default: + qWarning() << "[ForwardSolution::handleEvent] Received an Event that is not handled by switch cases."; + } +} + +//============================================================================================================= + +QVector ForwardSolution::getEventSubscriptions(void) const +{ + QVector temp; + temp.push_back(SELECTED_MODEL_CHANGED); + + return temp; +} + +//============================================================================================================= + +QString ForwardSolution::getBuildInfo() +{ + return QString(FORWARDSOLUTIONPLUGIN::buildDateTime()) + QString(" - ") + QString(FORWARDSOLUTIONPLUGIN::buildHash()); +} + +//============================================================================================================= + +void ForwardSolution::onDoForwardComputation() +{ + + if(!m_pFiffInfo){ + qInfo() << "No FiffInfo source available for forward solution computation."; + return; + } + + qInfo() << "Performing forward solution computation."; + + QFile t_fBem(m_pFwdSettings->bemname); + FIFFLIB::FiffStream::SPtr stream(new FIFFLIB::FiffStream(&t_fBem)); + if(!stream->open()) { + QMessageBox msgBox; + msgBox.setText("The bem model cannot be opend. Chosse another file."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setWindowFlags(Qt::WindowStaysOnTopHint); + msgBox.exec(); + stream->close(); + return; + } + stream->close(); + + // Read source space + QFile t_fSource(m_pFwdSettings->srcname); + stream = FIFFLIB::FiffStream::SPtr(new FIFFLIB::FiffStream(&t_fSource)); + if(!stream->open()) { + QMessageBox msgBox; + msgBox.setText("The source space cannot be opend. Chosse another file."); + msgBox.setText(m_pFwdSettings->srcname); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setWindowFlags(Qt::WindowStaysOnTopHint); + msgBox.exec(); + stream->close(); + return; + } + stream->close(); + + // Read MRI transformation + QFile t_fMri(m_pFwdSettings->mriname); + stream = FIFFLIB::FiffStream::SPtr(new FIFFLIB::FiffStream(&t_fMri)); + if(!stream->open()) { + QMessageBox msgBox; + msgBox.setText("The mri - head transformation cannot be opend. Chosse another file."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setWindowFlags(Qt::WindowStaysOnTopHint); + msgBox.exec(); + stream->close(); + return; + } + stream->close(); + + // Read measurement + QFile t_fMeas(m_pFwdSettings->measname); + stream = FIFFLIB::FiffStream::SPtr(new FIFFLIB::FiffStream(&t_fMri)); + if(!stream->open()) { + QMessageBox msgBox; + msgBox.setText("The meaurement file cannot be opend. Chosse another file."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setWindowFlags(Qt::WindowStaysOnTopHint); + msgBox.exec(); + stream->close(); + return; + } + stream->close(); + + qInfo() << "Verified source files for forward solution computation."; + + m_bDoFwdComputation = true; + + m_pFwdSettings->pFiffInfo = m_pFiffInfo; + + emit statusInformationChanged(0); // initializing + FWDLIB::ComputeFwd::SPtr pComputeFwd = FWDLIB::ComputeFwd::SPtr(new FWDLIB::ComputeFwd(m_pFwdSettings)); + + QFile t_fSolution(m_pFwdSettings->solname); + MNELIB::MNEForwardSolution::SPtr pFwdSolution; + MNELIB::MNEForwardSolution::SPtr pClusteredFwd; + + emit statusInformationChanged(4); // not computed + + emit statusInformationChanged(1); // computing + m_bBusy = true; + + // compute and store + pComputeFwd->calculateFwd(); + pComputeFwd->storeFwd(); + + // get Mne Forward Solution (in future this is not necessary, ComputeForward will have this as member) + pFwdSolution = MNELIB::MNEForwardSolution::SPtr(new MNELIB::MNEForwardSolution(t_fSolution, false, true)); + + // emit results to control widget + emit fwdSolutionAvailable(pFwdSolution->source_ori, + pFwdSolution->coord_frame, + pFwdSolution->nsource, + pFwdSolution->nchan, + pFwdSolution->src.size()); + + if(m_bDoClustering) { + emit statusInformationChanged(3); // clustering + pClusteredFwd = MNELIB::MNEForwardSolution::SPtr(new MNELIB::MNEForwardSolution(pFwdSolution->cluster_forward_solution(*m_pAnnotationSet.data(), 200))); + emit clusteringAvailable(pClusteredFwd->nsource); + emit statusInformationChanged(5); //finished + m_pFwdSolution = pClusteredFwd; + } else { + emit statusInformationChanged(5); + m_pFwdSolution = pFwdSolution; + } + + QSharedPointer pFwdSolModel = QSharedPointer(new ANSHAREDLIB::ForwardSolutionModel(m_pFwdSolution)); + + m_pAnalyzeData->addModel(pFwdSolModel, + "Fwd. Sol. - " + QDateTime::currentDateTime().toString()); + + qInfo() << "New soultion available"; +} + +//============================================================================================================= + +void ForwardSolution::onRecompStatusChanged(bool bDoRecomputation) +{ + m_bDoRecomputation = bDoRecomputation; +} + +//============================================================================================================= + +void ForwardSolution::onClusteringStatusChanged(bool bDoClustering) +{ + if(m_pAnnotationSet->isEmpty()) { + QMessageBox msgBox; + msgBox.setText("Please load an annotation set befor clustering."); + msgBox.exec(); + return; + } + m_bDoClustering = bDoClustering; +} + +//============================================================================================================= + +void ForwardSolution::onAtlasDirChanged(const QString& sDirPath, const FSLIB::AnnotationSet::SPtr pAnnotationSet) +{ + m_sAtlasDir = sDirPath; + m_pAnnotationSet = pAnnotationSet; +} + +//============================================================================================================= + +void ForwardSolution::onModelChanged(QSharedPointer pNewModel) +{ + switch(pNewModel->getType()){ + case ANSHAREDLIB::ANSHAREDLIB_FIFFRAW_MODEL:{ + auto pRawDataModel = qSharedPointerCast(pNewModel); + if(pRawDataModel){ + m_pFiffInfo = pRawDataModel->getFiffInfo(); + } + break; + } + case ANSHAREDLIB::ANSHAREDLIB_AVERAGING_MODEL:{ + auto pAverageDataModel = qSharedPointerCast(pNewModel); + if(pAverageDataModel){ + m_pFiffInfo = pAverageDataModel->getFiffInfo(); + } + break; + } + default: + break; + } +} diff --git a/applications/mne_analyze/plugins/forwardsolution/forwardsolution.h b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.h new file mode 100644 index 00000000000..256199f4f90 --- /dev/null +++ b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.h @@ -0,0 +1,231 @@ +//============================================================================================================= +/** + * @file forwardsolution.h + * @author Gabriel Motta + * Juan G Prieto + * @since 0.1.9 + * @date June, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, Gabriel B Motta, Juan G Prieto. 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 ForwardSolution class declaration. + * + */ + +#ifndef MNEANALYZE_FORWARDSOLUTION_H +#define MNEANALYZE_FORWARDSOLUTION_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "forwardsolution_global.h" + +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace ANSHAREDLIB { + class Communicator; + class AbstractModel; +} + +namespace DISPLIB { + class FwdSettingsView; +} + +namespace FSLIB{ + class AnnotationSet; +} + +namespace FWDLIB { + class ComputeFwdSettings; + class ComputeFwd; +} + +namespace MNELIB { + class MNEForwardSolution; +} + +//============================================================================================================= +// DEFINE NAMESPACE FORWARDSOLUTIONPLUGIN +//============================================================================================================= + +namespace FORWARDSOLUTIONPLUGIN +{ + +//============================================================================================================= +// FORWARDSOLUTIONPLUGIN FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * ForwardSolution Plugin + * + * @brief The forwardsolution class provides a plugin for computing averages. + */ +class FORWARDSOLUTIONSHARED_EXPORT ForwardSolution : public ANSHAREDLIB::AbstractPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "ansharedlib/1.0" FILE "forwardsolution.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 an ForwardSolution object. + */ + ForwardSolution(); + + //========================================================================================================= + /** + * Destroys the ForwardSolution object. + */ + ~ForwardSolution() 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 QString getBuildInfo() override; + + virtual void handleEvent(QSharedPointer e) override; + virtual QVector getEventSubscriptions() const override; + +private slots: + //========================================================================================================= + /** + * Call this funciton whenever a forward computation was requested. + */ + void onDoForwardComputation(); + + //========================================================================================================= + /** + * Call this function whenever the recompution status changed. + * + * @param[in] bDoRecomputation If recomputation is activated. + */ + void onRecompStatusChanged(bool bDoRecomputation); + + //========================================================================================================= + /** + * Call this function whenever the clustering status changed. + * + * @param[in] bDoClustering If clustering is activated. + */ + void onClusteringStatusChanged(bool bDoRecomputation); + + //========================================================================================================= + /** + * Call this function whenever the atlas directory is set. + * + * @param[in] sDirPath The path to the atlas directory. + * @param[in] pAnnotationSet The Annotation set. + */ + void onAtlasDirChanged(const QString& sDirPath, + const QSharedPointer pAnnotationSet); + +signals: + //========================================================================================================= + /** + * Emitted when forward solution is available + */ + void fwdSolutionAvailable(FIFFLIB::fiff_int_t iSourceOri, + FIFFLIB::fiff_int_t iCoordFrame, + int iNSource, + int iNChan, + int iNSpaces); + + //========================================================================================================= + /** + * Emitted whenever clustered forward solution is available + */ + void clusteringAvailable(int iNSource); + + //========================================================================================================= + /** + * Emit this signal whenever the clustering status changed + * (0 Initializing, 1 Computing, 2 Recomputing, 3 Clustering, 4 Not Computed, 5 Finished). + * + * @param[in] iStatus status of recomputation. + */ + void statusInformationChanged(int iStatus); + +private: + + //========================================================================================================= + /** + * Loads new Fiff model whan current loaded model is changed + * + * @param[in, out] pNewModel pointer to currently loaded FiffRawView Model. + */ + void onModelChanged(QSharedPointer pNewModel); + + + QPointer m_pCommu; /**< To broadcst signals. */ + + DISPLIB::FwdSettingsView* m_pFwdSettingsView; + + QSharedPointer m_pFwdSettings; /**< Forward Solution Settings. */ + + QSharedPointer m_pFwdSolution; + + QSharedPointer m_pFiffInfo; /**< Fiff measurement info.*/ + FIFFLIB::FiffCoordTrans m_transDevHead; /**< Updated meg->head transformation. */ + QSharedPointer m_pAnnotationSet; /**< Annotation set. */ + + QMutex m_mutex; /**< The threads mutex.*/ + + float m_fThreshRot; /**< The allowed rotation in degree.**/ + float m_fThreshMove; /**< The Allowed movement in mm.**/ + bool m_bBusy; /**< Indicates if we have to update headposition.**/ + bool m_bDoRecomputation; /**< If recomputation is activated.**/ + bool m_bDoClustering; /**< If clustering is activated.**/ + bool m_bDoFwdComputation; /**< Do a forward computation. **/ + + QString m_sAtlasDir; /**< File to Atlas. */ + + QString m_sFiffInfoSource; +}; + +} // NAMESPACE + +#endif // MNEANALYZE_FORWARDSOLUTION_H diff --git a/applications/mne_analyze/plugins/forwardsolution/forwardsolution.json b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/applications/mne_analyze/plugins/forwardsolution/forwardsolution.pro b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.pro new file mode 100644 index 00000000000..d2a49e4b9b0 --- /dev/null +++ b/applications/mne_analyze/plugins/forwardsolution/forwardsolution.pro @@ -0,0 +1,165 @@ +#============================================================================================================== +# +# @file forwardsolution.pro +# @author Gabriel Motta +# Juan G Prieto +# @since 0.1.9 +# @date June, 2022 +# +# @section LICENSE +# +# Copyright (C) 2022, Gabriel B Motta, Juan G Prieto. 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 forwardsolution plugin. +# +#============================================================================================================== + +include(../../../../mne-cpp.pri) + +TEMPLATE = lib + +QT += gui widgets + +CONFIG += skip_target_version_ext plugin + +DEFINES += FORWARDSOLUTION_PLUGIN + +DESTDIR = $${MNE_BINARY_DIR}/mne_analyze_plugins + +contains(MNECPP_CONFIG, wasm) { + DEFINES += WASMBUILD +} + +TARGET = forwardsolution +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 += \ + forwardsolution.cpp \ + forwardsolution_global.cpp \ + +HEADERS += \ + forwardsolution_global.h \ + forwardsolution.h \ + +OTHER_FILES += forwardsolution.json + +clang { + QMAKE_CXXFLAGS += -isystem $${EIGEN_INCLUDE_DIR} +} else { + 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 \ + } +} + +################################################## BUILD TIMESTAMP/HASH UPDATER ############################################ + +FILE_TO_UPDATE = forwardsolution_global.cpp +win32 { + CONFIG(debug, debug|release) { + OBJ_TARJET = debug\forwardsolution_global.obj + } else { + OBJ_TARJET = release\forwardsolution_global.obj + } +} + +ALL_FILES += $$HEADERS +ALL_FILES += $$SOURCES +ALL_FILES -= $$FILE_TO_UPDATE + +FileUpdater.target = phonyFileUpdater +for (I_FILE, ALL_FILES) { + FileUpdater.depends += $${PWD}/$${I_FILE} +} + +unix|macx { + FileUpdater.commands = touch $${PWD}/$${FILE_TO_UPDATE} ; echo PASTA > phonyFileUpdater +} + +win32 { + FileUpdater.commands = copy /y $$shell_path($${PWD})\\$${FILE_TO_UPDATE} +,, $$shell_path($${PWD})\\$${FILE_TO_UPDATE} & echo PASTA > phonyFileUpdater + OrderForcerTarget.target = $${OBJ_TARJET} + OrderForcerTarget.depends += phonyFileUpdater + QMAKE_EXTRA_TARGETS += OrderForcerTarget +} + +PRE_TARGETDEPS += phonyFileUpdater +QMAKE_EXTRA_TARGETS += FileUpdater diff --git a/applications/mne_analyze/plugins/forwardsolution/forwardsolution_global.cpp b/applications/mne_analyze/plugins/forwardsolution/forwardsolution_global.cpp new file mode 100644 index 00000000000..19cc687db8b --- /dev/null +++ b/applications/mne_analyze/plugins/forwardsolution/forwardsolution_global.cpp @@ -0,0 +1,54 @@ +//============================================================================================================= +/** + * @file forwardsolution_global.cpp + * @author Gabriel B Motta ; + * Juan G Prieto + * @since 0.1.9 + * @date June, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, Gabriel B Motta, Juan G Prieto. 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 forwardsolution plugin global definitions. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "forwardsolution_global.h" + +//============================================================================================================= +// DEFINE METHODS +//============================================================================================================= + +const char* FORWARDSOLUTIONPLUGIN::buildDateTime(){ return UTILSLIB::dateTimeNow();}; + +//============================================================================================================= + +const char* FORWARDSOLUTIONPLUGIN::buildHash(){ return UTILSLIB::gitHash();}; + +//============================================================================================================= + +const char* FORWARDSOLUTIONPLUGIN::buildHashLong(){ return UTILSLIB::gitHashLong();}; diff --git a/applications/mne_analyze/plugins/forwardsolution/forwardsolution_global.h b/applications/mne_analyze/plugins/forwardsolution/forwardsolution_global.h new file mode 100644 index 00000000000..faa0d382e5a --- /dev/null +++ b/applications/mne_analyze/plugins/forwardsolution/forwardsolution_global.h @@ -0,0 +1,82 @@ +//============================================================================================================= +/** + * @file forwardsolution_global.h + * @author Gabriel Motta ; + * Juan G Prieto + * @since 0.1.9 + * @date June, 2022 + * + * @section LICENSE + * + * Copyright (C) 2022, Gabriel B Motta, Juan G Prieto. 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 MNE Analyze Source Localization Plugin + * + */ + +#ifndef MNEANALYZE_FORWARDSOLUTION_GLOBAL_H +#define MNEANALYZE_FORWARDSOLUTION_GLOBAL_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// PREPROCESSOR DEFINES +//============================================================================================================= + +#if defined(FORWARDSOLUTION_PLUGIN) +# define FORWARDSOLUTIONSHARED_EXPORT Q_DECL_EXPORT /**< Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library. */ +#else +# define FORWARDSOLUTIONSHARED_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 + +namespace FORWARDSOLUTIONPLUGIN{ + +//============================================================================================================= +/** + * Returns build date and time. + */ +FORWARDSOLUTIONSHARED_EXPORT const char* buildDateTime(); + +//============================================================================================================= +/** + * Returns abbreviated build git hash. + */ +FORWARDSOLUTIONSHARED_EXPORT const char* buildHash(); + +//============================================================================================================= +/** + * Returns full build git hash. + */ +FORWARDSOLUTIONSHARED_EXPORT const char* buildHashLong(); +} + +#endif // MNEANALYZE_FORWARDSOLUTION_GLOBAL_H diff --git a/applications/mne_analyze/plugins/plugins.pro b/applications/mne_analyze/plugins/plugins.pro index 0d151f6d920..6eb56ded59a 100644 --- a/applications/mne_analyze/plugins/plugins.pro +++ b/applications/mne_analyze/plugins/plugins.pro @@ -49,6 +49,7 @@ SUBDIRS += \ controlmanager \ coregistration \ dipolefit \ + forwardsolution \ # 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/rawdataviewer/fiffrawview.cpp b/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.cpp index 7c21500ee15..b62dbb2a727 100644 --- a/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.cpp +++ b/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.cpp @@ -478,11 +478,12 @@ bool FiffRawView::eventFilter(QObject *object, QEvent *event) switch(mouseEvent->button()){ case Qt::LeftButton:{ if(m_pModel && object == m_pTableView->viewport()){ - QPoint pos = mouseEvent->pos(); - m_pModel->setScrollerSample(static_cast(floor((float)m_pModel->absoluteFirstSample() + //accounting for first sample offset - (m_pTableView->horizontalScrollBar()->value() / m_pModel->pixelDifference()) + //accounting for scroll offset - ((float)pos.x() / m_pModel->pixelDifference())))); //accounting for mouse position offset - m_pTableView->viewport()->repaint(); + QPoint pos = mouseEvent->pos(); + m_pModel->setScrollerSample(static_cast(floor((float)m_pModel->absoluteFirstSample() + //accounting for first sample offset + (m_pTableView->horizontalScrollBar()->value() / m_pModel->pixelDifference()) + //accounting for scroll offset + ((float)pos.x() / m_pModel->pixelDifference())))); //accounting for mouse position offset + m_pTableView->viewport()->repaint(); + emit sendLastClickPos(m_pModel->getScrollerPosition()); } } } diff --git a/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.h b/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.h index 19a13ecc801..2538d04b331 100644 --- a/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.h +++ b/applications/mne_analyze/plugins/rawdataviewer/fiffrawview.h @@ -314,6 +314,14 @@ class RAWDATAVIEWERSHARED_EXPORT FiffRawView : public DISPLIB::AbstractView */ void sendSamplePos(int iSample); + //========================================================================================================= + /** + * Emits sample number where last clicked + * + * @param[in] iSample sample number last clicked. + */ + void sendLastClickPos(int iSample); + private: //========================================================================================================= /** diff --git a/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.cpp b/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.cpp index af2b7c2aba2..5e982d2066b 100644 --- a/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.cpp +++ b/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.cpp @@ -107,7 +107,10 @@ void RawDataViewer::init() m_pFiffRawView->setAttribute(Qt::WA_DeleteOnClose, false); connect(m_pFiffRawView.data(), &FiffRawView::sendSamplePos, - this, &RawDataViewer::onSendSamplePos, Qt::UniqueConnection); + this, &RawDataViewer::sendNewEventSample, Qt::UniqueConnection); + + connect(m_pFiffRawView.data(), &FiffRawView::sendLastClickPos, + this, &RawDataViewer::sendSampleSelected, Qt::UniqueConnection); connect(m_pFiffRawView.data(), &FiffRawView::realtimeDataUpdated, this, &RawDataViewer::onNewRealtimeData, Qt::UniqueConnection); @@ -256,12 +259,22 @@ void RawDataViewer::onModelChanged(QSharedPointer pNewModel) //============================================================================================================= -void RawDataViewer::onSendSamplePos(int iSample) +void RawDataViewer::sendNewEventSample(int iSample) +{ + QVariant data; + data.setValue(iSample); + + m_pCommu->publishEvent(EVENT_TYPE::ADD_NEW_EVENT, data); +} + +//============================================================================================================= + +void RawDataViewer::sendSampleSelected(int iSample) { QVariant data; data.setValue(iSample); - m_pCommu->publishEvent(EVENT_TYPE::NEW_EVENT_ADDED, data); + m_pCommu->publishEvent(EVENT_TYPE::SAMPLE_SELECTED, data); } //============================================================================================================= diff --git a/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.h b/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.h index 7bb97e57b6c..74f1da3f5fb 100644 --- a/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.h +++ b/applications/mne_analyze/plugins/rawdataviewer/rawdataviewer.h @@ -141,7 +141,15 @@ class RAWDATAVIEWERSHARED_EXPORT RawDataViewer : public ANSHAREDLIB::AbstractPlu * * @param[in] iSample The sample to be send. */ - void onSendSamplePos(int iSample); + void sendNewEventSample(int iSample); + + //========================================================================================================= + /** + * Handles if a new sample position should be dispatched + * + * @param[in] iSample The sample to be send. + */ + void sendSampleSelected(int iSample); //========================================================================================================= /** diff --git a/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.cpp b/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.cpp index c3677b3a13d..6b079801a0a 100644 --- a/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.cpp +++ b/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.cpp @@ -40,11 +40,27 @@ #include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= #include +#include +#include //============================================================================================================= // USED NAMESPACES @@ -59,6 +75,11 @@ using namespace ANSHAREDLIB; SourceLocalization::SourceLocalization() : m_pCommu(Q_NULLPTR) +, m_pFwdSolutionModel(Q_NULLPTR) +, m_pAverageDataModel(Q_NULLPTR) +, m_pRawDataModel(Q_NULLPTR) +, m_iSelectedSample(-1) +, m_bUpdateMinNorm(false) { } @@ -115,9 +136,28 @@ QWidget *SourceLocalization::getView() QDockWidget* SourceLocalization::getControl() { - //QDockWidget* pControl = new QDockWidget(getName()); + DISPLIB::MinimumNormSettingsView* pMinimumNormSettingsView = new DISPLIB::MinimumNormSettingsView(QString("MNESCAN/%1").arg(this->getName())); - return Q_NULLPTR; + connect(pMinimumNormSettingsView, &DISPLIB::MinimumNormSettingsView::methodChanged, + this, &SourceLocalization::onMethodChanged); + connect(pMinimumNormSettingsView, &DISPLIB::MinimumNormSettingsView::triggerTypeChanged, + this, &SourceLocalization::onTriggerTypeChanged); + connect(pMinimumNormSettingsView, &DISPLIB::MinimumNormSettingsView::timePointChanged, + this, &SourceLocalization::onTimePointValueChanged); + + QVBoxLayout* pControlLayout = new QVBoxLayout(); + pControlLayout->addWidget(pMinimumNormSettingsView); + + QWidget* containerWidget = new QWidget(); + containerWidget->setLayout(pControlLayout); + + QScrollArea* pControlScrollArea = new QScrollArea(); + pControlScrollArea->setWidget(containerWidget); + + QDockWidget* pControlDock = new QDockWidget(this->getName()); + pControlDock->setWidget(pControlScrollArea); + + return pControlDock; } //============================================================================================================= @@ -125,8 +165,17 @@ QDockWidget* SourceLocalization::getControl() void SourceLocalization::handleEvent(QSharedPointer e) { switch (e->getType()) { - default: - qWarning() << "[SourceLocalization::handleEvent] Received an Event that is not handled by switch cases."; + case EVENT_TYPE::SELECTED_MODEL_CHANGED: + onModelChanged(e->getData().value >()); + break; + case EVENT_TYPE::MODEL_REMOVED: + onModelRemoved(e->getData().value>()); + break; + case EVENT_TYPE::SAMPLE_SELECTED: + m_iSelectedSample = e->getData().value(); + sourceLocalizationFromSingleTrial(); + default: + qWarning() << "[Events::handleEvent] Received an Event that is not handled by switch cases."; } } @@ -135,7 +184,9 @@ void SourceLocalization::handleEvent(QSharedPointer e) QVector SourceLocalization::getEventSubscriptions(void) const { QVector temp; - //temp.push_back(SELECTED_MODEL_CHANGED); + temp.push_back(SELECTED_MODEL_CHANGED); + temp.push_back(MODEL_REMOVED); + temp.push_back(SAMPLE_SELECTED); return temp; } @@ -146,3 +197,239 @@ QString SourceLocalization::getBuildInfo() { return QString(SOURCELOCALIZATIONPLUGIN::buildDateTime()) + QString(" - ") + QString(SOURCELOCALIZATIONPLUGIN::buildHash()); } + +//============================================================================================================= + +void SourceLocalization::sourceLocalizationFromAverage() +{ + if(m_sourceLocalizationMode != SOURCE_LOC_FROM_AVG) { + return; + } + + if(!m_pFwdSolutionModel){ + qInfo() << "[SourceLocalization::performSourceLocalization] No forward solution available."; + return; + } + + if(!m_pAverageDataModel){ + qInfo() << "[SourceLocalization::performSourceLocalization] No average model available."; + return; + } +} + +//============================================================================================================= + +void SourceLocalization::sourceLocalizationFromSingleTrial() +{ + if(m_sourceLocalizationMode != SOURCE_LOC_FROM_SINGLE_TRIAL) { + return; + } + + if(!m_pFwdSolutionModel){ + qInfo() << "[SourceLocalization::performSourceLocalization] No forward solution available."; + return; + } + + if(!m_pRawDataModel){ + qInfo() << "[SourceLocalization::performSourceLocalization] No raw data model available."; + return; + } + + Eigen::MatrixXd data, times; + + float starting_sec = m_pRawDataModel->getSamplingFrequency() * static_cast(m_iSelectedSample); + + if(!m_pRawDataModel->getFiffIO()->m_qlistRaw.front()->read_raw_segment_times(data, + times, + starting_sec, + starting_sec + m_pRawDataModel->getSamplingFrequency() + )) + { + qWarning() << "Unable to load raw data for source estimation."; + return; + } + + auto covEstimate = estimateCovariance(data, m_pRawDataModel->getFiffInfo().data()); + + MNELIB::MNEInverseOperator invOp(*m_pRawDataModel->getFiffInfo().data(), + *m_pFwdSolutionModel->getFwdSolution().data(), + covEstimate, + 0.2f, + 0.8f); + + auto pMinimumNorm = INVERSELIB::MinimumNorm::SPtr(new INVERSELIB::MinimumNorm(invOp, 1.0f / pow(1.0f, 2), m_sMethod)); + + // Set up the inverse according to the parameters. + // Use 1 nave here because in case of evoked data as input the minimum norm will always be updated when the source estimate is calculated (see run method). + pMinimumNorm->doInverseSetup(1,true); + + int iNumberChannels = invOp.noise_cov->names.size(); + float tstep = 1.0f / m_pRawDataModel->getFiffInfo()->sfreq; + auto lChNamesFiffInfo = m_pRawDataModel->getFiffInfo()->ch_names; + auto lChNamesInvOp = invOp.noise_cov->names; + int iTimePointSps = m_pRawDataModel->getFiffInfo()->sfreq * 0.001f; + + MatrixXd matDataResized; + matDataResized.resize(iNumberChannels, data.cols()); + + for(int j = 0; j < iNumberChannels; ++j) { + matDataResized.row(j) = data.row(lChNamesFiffInfo.indexOf(lChNamesInvOp.at(j))); + } + + //TODO: Add picking here. See evoked part as input. + QSharedPointer pSourceEstimate = QSharedPointer(new MNELIB::MNESourceEstimate()); + *pSourceEstimate = pMinimumNorm->calculateInverse(matDataResized, + 0.0f, + tstep, + true); + + if(!pSourceEstimate->isEmpty()) { + if(iTimePointSps < pSourceEstimate->data.cols() && iTimePointSps >= 0) { + *pSourceEstimate = pSourceEstimate->reduce(iTimePointSps,1); + } +// m_pAnalyzeData->addModel(pFwdSolModel, +// "Src. Est. - " + QString::number(m_iSelectedSample)); + } + + +} + +//============================================================================================================= + +void SourceLocalization::onModelChanged(QSharedPointer pNewModel) +{ + switch(pNewModel->getType()){ + case ANSHAREDLIB::ANSHAREDLIB_FIFFRAW_MODEL: + m_pRawDataModel = qSharedPointerCast(pNewModel); + break; + case ANSHAREDLIB::ANSHAREDLIB_AVERAGING_MODEL: + m_pAverageDataModel = qSharedPointerCast(pNewModel); + sourceLocalizationFromAverage(); + break; + case ANSHAREDLIB::ANSHAREDLIB_FORWARDSOLUTION_MODEL: + m_pFwdSolutionModel = qSharedPointerCast(pNewModel); + + break; + default: + break; + } +} + +//============================================================================================================= + +void SourceLocalization::onModelRemoved(QSharedPointer pRemovedModel) +{ + +} + +//============================================================================================================= + +FIFFLIB::FiffCov SourceLocalization::estimateCovariance(const Eigen::MatrixXd& matData, + FIFFLIB::FiffInfo* info) +{ + QList lData; + lData.push_back(matData); + + int iSamples = matData.cols(); + + QFuture result = QtConcurrent::mappedReduced(lData, + computeCov, + reduceCov); + + result.waitForFinished(); + + CovComputeResult finalResult = result.result(); + + //Final computation + FIFFLIB::FiffCov computedCov; + computedCov.data = finalResult.matData; + + QStringList exclude; + for(int i = 0; ichs.size(); i++) { + if(info->chs.at(i).kind != FIFFV_MEG_CH && + info->chs.at(i).kind != FIFFV_EEG_CH) { + exclude << info->chs.at(i).ch_name; + } + } + bool doProj = true; + + if(iSamples > 0) { + finalResult.mu /= (float)iSamples; + computedCov.data.array() -= iSamples * (finalResult.mu * finalResult.mu.transpose()).array(); + computedCov.data.array() /= (iSamples - 1); + + computedCov.kind = FIFFV_MNE_NOISE_COV; + computedCov.diag = false; + computedCov.dim = computedCov.data.rows(); + + //ToDo do picks + computedCov.names = info->ch_names; + computedCov.projs = info->projs; + computedCov.bads = info->bads; + computedCov.nfree = iSamples; + + // regularize noise covariance + computedCov = computedCov.regularize(*info, 0.05, 0.05, 0.1, doProj, exclude); + + return computedCov; + } else { + qWarning() << "[RtCov::estimateCovariance] Number of samples equals zero. Regularization not possible. Returning empty covariance estimation."; + return FIFFLIB::FiffCov(); + } + +} + +//============================================================================================================= + +SourceLocalization::CovComputeResult SourceLocalization::computeCov(const MatrixXd &matData) +{ + CovComputeResult result; + result.mu = matData.rowwise().sum(); + result.matData = matData * matData.transpose(); + return result; +} + +//============================================================================================================= + +void SourceLocalization::reduceCov(CovComputeResult& finalResult, const CovComputeResult &tempResult) +{ + if(finalResult.matData.size() == 0 || finalResult.mu.size() == 0) { + finalResult.mu = tempResult.mu; + finalResult.matData = tempResult.matData; + } else { + finalResult.mu += tempResult.mu; + finalResult.matData += tempResult.matData; + } +} + +//============================================================================================================= + +void SourceLocalization::onMethodChanged(const QString& method) +{ + m_sMethod = method; +} + +//============================================================================================================= + +void SourceLocalization::onTriggerTypeChanged(const QString& triggerType) +{ + m_sAvrType = triggerType; +} + +//============================================================================================================= + +void SourceLocalization::onTimePointValueChanged(int iTimePointMs) +{ + Q_UNUSED(iTimePointMs); +// if(m_pFiffInfoInput && m_pCircularEvokedBuffer) { +// m_qMutex.lock(); +// m_iTimePointSps = m_pFiffInfoInput->sfreq * (float)iTimePointMs * 0.001f; +// m_qMutex.unlock(); + +// if(this->isRunning()) { +// while(!m_pCircularEvokedBuffer->push(m_currentEvoked)) { +// //Do nothing until the circular buffer is ready to accept new data again +// } +// } +// } +} diff --git a/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.h b/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.h index 7485a5d1ad4..ce2a1171a65 100644 --- a/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.h +++ b/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.h @@ -43,6 +43,8 @@ #include +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -56,6 +58,14 @@ namespace ANSHAREDLIB { class Communicator; + class AbstractModel; + class FiffRawViewModel; + class AveragingDataModel; + class ForwardSolutionModel; +} + +namespace INVERSELIB { + class MinimumNorm; } //============================================================================================================= @@ -109,8 +119,105 @@ class SOURCELOCALIZATIONSHARED_EXPORT SourceLocalization : public ANSHAREDLIB::A virtual void handleEvent(QSharedPointer e) override; virtual QVector getEventSubscriptions() const override; -private: +private: + + struct CovComputeResult { + Eigen::VectorXd mu; + Eigen::MatrixXd matData; + }; + + enum Mode{ + SOURCE_LOC_FROM_AVG, + SOURCE_LOC_FROM_SINGLE_TRIAL + }; + + void sourceLocalizationFromAverage(); + + void sourceLocalizationFromSingleTrial(); + + //========================================================================================================= + /** + * Loads new Fiff model whan current loaded model is changed + * + * @param[in, out] pNewModel pointer to currently loaded FiffRawView Model. + */ + void onModelChanged(QSharedPointer pNewModel); + + //========================================================================================================= + /** + * Handles clearing view if currently used model is being removed + * + * @param[in] pRemovedModel Pointer to model being removed. + */ + void onModelRemoved(QSharedPointer pRemovedModel); + + //========================================================================================================= + /** + * Perform actual covariance estimation. + * + * @param[in] inputData Data to estimate the covariance from. + */ + FIFFLIB::FiffCov estimateCovariance(const Eigen::MatrixXd& matData, + FIFFLIB::FiffInfo* info); + + //========================================================================================================= + /** + * Computer multiplication with transposed. + * + * @param[in] matData Data to self multiply with. + * + * @return The multiplication result. + */ + static CovComputeResult computeCov(const Eigen::MatrixXd &matData); + + //========================================================================================================= + /** + * Computer multiplication with transposed. + * + * @param[out] finalResult The final covariance estimation. + * @param[in] tempResult The intermediate result from the compute function. + */ + static void reduceCov(CovComputeResult& finalResult, const CovComputeResult &tempResult); + + //========================================================================================================= + /** + * Slot called when the method changed. + * + * @param[in] method The new method. + */ + void onMethodChanged(const QString &method); + + //========================================================================================================= + /** + * Slot called when the trigger type changed. + * + * @param[in] triggerType The new trigger type. + */ + void onTriggerTypeChanged(const QString& triggerType); + + //========================================================================================================= + /** + * Slot called when the time point changes. + * + * @param[in] iTimePointMs The new time point in ms. + */ + void onTimePointValueChanged(int iTimePointMs); + QPointer m_pCommu; /**< To broadcst signals. */ + + QSharedPointer m_pFwdSolutionModel; + QSharedPointer m_pAverageDataModel; + QSharedPointer m_pRawDataModel; + + + QString m_sAvrType; /**< The average type. */ + QString m_sMethod; /**< The method: "MNE" | "dSPM" | "sLORETA". */ + + + int m_iSelectedSample; + bool m_bUpdateMinNorm; + + Mode m_sourceLocalizationMode; }; } // NAMESPACE diff --git a/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.pro b/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.pro index 3ea7986bf35..4a8763a018e 100644 --- a/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.pro +++ b/applications/mne_analyze/plugins/sourcelocalization/sourcelocalization.pro @@ -36,7 +36,7 @@ include(../../../../mne-cpp.pri) TEMPLATE = lib -QT += gui widgets +QT += gui widgets concurrent CONFIG += skip_target_version_ext plugin diff --git a/applications/mne_analyze/plugins/view3d/view3d.cpp b/applications/mne_analyze/plugins/view3d/view3d.cpp index 9ebf722cf4c..1e4a7920d96 100644 --- a/applications/mne_analyze/plugins/view3d/view3d.cpp +++ b/applications/mne_analyze/plugins/view3d/view3d.cpp @@ -43,8 +43,7 @@ #include #include #include - - +#include #include #include @@ -55,6 +54,7 @@ #include #include #include +#include #include @@ -83,6 +83,8 @@ View3D::View3D() : m_pCommu(Q_NULLPTR) , m_pBemTreeCoreg(Q_NULLPTR) , m_pDigitizerCoreg(Q_NULLPTR) + , m_pDipoleFit(Q_NULLPTR) + , m_pRtMNEItem(Q_NULLPTR) , m_pView3D(Q_NULLPTR) , m_bPickingActivated(false) { @@ -361,10 +363,58 @@ void View3D::newDipoleFit(const INVERSELIB::ECDSet &ecdSet) //============================================================================================================= +void View3D::newSourceLoc(QSharedPointer pModel) +{ + auto pSourcEstimate = pModel->getSourceEstimate(); + auto pFwdSolution = pModel->getFwdSolution(); + auto pHeadTrans = pModel->getMRIHeadTrans(); + auto pAnnotationSet = pModel->getAnnotationSet(); + auto pSurfSet = pModel->getSurfSet(); + + if(pSourcEstimate && pFwdSolution && pHeadTrans && pAnnotationSet && pSurfSet){ + if(!m_pRtMNEItem){ + m_pRtMNEItem = m_p3DModel->addSourceData("Subject", "Functional Data", + *pSourcEstimate, + *pFwdSolution, + *pSurfSet, + *pAnnotationSet); + m_pRtMNEItem->setLoopState(false); + m_pRtMNEItem->setTimeInterval(17); + m_pRtMNEItem->setThresholds(QVector3D(0.0,5,10)); + m_pRtMNEItem->setColormapType("Hot"); + m_pRtMNEItem->setVisualizationType("Annotation based"); + m_pRtMNEItem->setNumberAverages(1); // Set to 1 because we want to enable time point picking which only includes one sample + m_pRtMNEItem->setAlpha(1.0); + m_pRtMNEItem->setStreamingState(true); + //m_pRtMNEItem->setSFreq(); + } else { + m_pRtMNEItem->addData(*pSourcEstimate); + } + + } else { + qWarning() << "[View3D::newSourceLoc] Missing data in sourec loc model:"; + if(!pSourcEstimate) qWarning() << "Source Estimate missing."; + if(!pFwdSolution) qWarning() << "Fwd Solution missing."; + if(!pHeadTrans) qWarning() << "MRI Head Trans missing."; + if(!pAnnotationSet) qWarning() << "AnnotationSet missing."; + if(!pSurfSet) qWarning() << "Surface Set missing."; + return; + } +} + +//============================================================================================================= + void View3D::onModelChanged(QSharedPointer pNewModel) { - if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_DIPOLEFIT_MODEL) { + switch(pNewModel->getType()){ + case MODEL_TYPE::ANSHAREDLIB_DIPOLEFIT_MODEL: newDipoleFit(qSharedPointerCast(pNewModel)->data(QModelIndex()).value()); + break; + case MODEL_TYPE::ANSHAREDLIB_SOURCEESTIMATE_MODEL: + newSourceLoc(qSharedPointerCast(pNewModel)); + break; + default: + break; } } diff --git a/applications/mne_analyze/plugins/view3d/view3d.h b/applications/mne_analyze/plugins/view3d/view3d.h index 56597266c0c..3aea03af893 100644 --- a/applications/mne_analyze/plugins/view3d/view3d.h +++ b/applications/mne_analyze/plugins/view3d/view3d.h @@ -62,6 +62,7 @@ namespace ANSHAREDLIB { class BemDataModel; class AbstractModel; class DipoleFitModel; + class SourceEstimateModel; } namespace DISP3DLIB { @@ -70,6 +71,7 @@ namespace DISP3DLIB { class BemTreeItem; class DigitizerSetTreeItem; class EcdDataTreeItem; + class MneDataTreeItem; } namespace DISPLIB { @@ -201,6 +203,9 @@ class VIEW3DSHARED_EXPORT View3D : public ANSHAREDLIB::AbstractPlugin */ void newDipoleFit(const INVERSELIB::ECDSet& ecdSet); + //========================================================================================================= + void newSourceLoc(QSharedPointer pModel); + //========================================================================================================= /** * Loads new model when current loaded model is changed @@ -226,6 +231,8 @@ class VIEW3DSHARED_EXPORT View3D : public ANSHAREDLIB::AbstractPlugin DISP3DLIB::DigitizerSetTreeItem* m_pDigitizerCoreg; /**< The 3D item pointing to the tracked digitizers. */ DISP3DLIB::DigitizerSetTreeItem* m_pMriFidCoreg; /**< The 3D item pointing to the mri fiducials. */ DISP3DLIB::EcdDataTreeItem* m_pDipoleFit; /**< The 3D item pointing to the dipole fit. */ + DISP3DLIB::MneDataTreeItem* m_pRtMNEItem; /**< The Disp3D real time items. */ + DISP3DLIB::View3D* m_pView3D; /**< The Disp3D view. */ DISPLIB::Control3DView* m_pControl3DView; /**< The 3D Control view. */ diff --git a/libraries/disp/viewers/formfiles/fwdsettingsview.ui b/libraries/disp/viewers/formfiles/fwdsettingsview.ui index bc044a84f2a..6dcb0bb9f43 100644 --- a/libraries/disp/viewers/formfiles/fwdsettingsview.ui +++ b/libraries/disp/viewers/formfiles/fwdsettingsview.ui @@ -6,8 +6,8 @@ 0 0 - 333 - 939 + 377 + 1012 @@ -15,186 +15,663 @@ - - - Forward Solution Information + + + 1 - - - - - Source Spaces: - - - - - - - true - - - - - - - Number of Sources: - - - - - - - true - - - - - - - Number of clustered Sources: - - - - - - - - - - true - - - - - - - Source Orientation - - - - - - - - - - true - - - - - - - Number of Channels - - - - - - - - - - true - - - - - - - Coordinate Frame - - - - - - - - 0 - 0 - - - - - - - true - - - - - - - - - - Clustering - - - - - - Brain Atlas Directory - - - - - - - - 140 - 0 - - - - - - - - ... - - - - - - - (lh+rh).aparc.a2009s.annot - - - - - - - QFrame::Panel - - - QFrame::Sunken - - - not loaded - - - - - - - Qt::Horizontal - - - - 142 - 0 - - - - - + + + Info + + + + + + Forward Soluton Information + + + + + + Source Spaces: + + + + + + + true + + + + + + + Number of Sources: + + + + + + + true + + + + + + + Number of clustered Sources: + + + + + + + + + + true + + + + + + + Source Orientation + + + + + + + + + + true + + + + + + + Number of Channels + + + + + + + + + + true + + + + + + + Coordinate Frame + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + + + + Clustering + + + + + + Brain Atlas Directory + + + + + + + + 140 + 0 + + + + + + + + ... + + + + + + + (lh+rh).aparc.a2009s.annot + + + + + + + QFrame::Panel + + + QFrame::Sunken + + + not loaded + + + + + + + Qt::Horizontal + + + + 142 + 0 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Files + + + + + + Forward Solution + + + false + + + + + + ... + + + + + + + + 140 + 0 + + + + + + + + + + + + + + Measurement File (with compensator inforamtion) + + + false + + + + + + + 140 + 0 + + + + + + + + + + + ... + + + + + + + + + + Source Space + + + false + + + + + + + 140 + 0 + + + + + + + + ... + + + + + + + + + + BEM Model + + + false + + + + + + ... + + + + + + + + 140 + 0 + + + + + + + + + + + MRI - Head Transformation + + + false + + + + + + + 140 + 0 + + + + + + + + ... + + + + + + + + + + Output for omitted source space points + + + false + + + + + + + 140 + 0 + + + + + + + + ... + + + + + + + + + + EEG model + + + false + + + + + + + 140 + 0 + + + + + + + + ... + + + + + + + + + + Qt::Vertical + + + + 334 + 118 + + + + + + + + + Settings + + + + + + Compute MEG Solution + + + + + + + Compute EEG Solution + + + + + + + Compute Gradient Solution + + + + + + + Fixed Orientation + + + + + + + Acurate + + + + + + + Compute in MRI space (else Head space) + + + + + + + Use threads + + + + + + + Calculate forward solution in all nodes + + + + + + + Identical head- and MRI- space + + + + + + + Filter Source Spaces + + + + + + + Scale Electrode Positions + + + + + + + Use equivalent source approach for EEG + + + + + + + Minimum distance skull <-> source [mm] + + + + + + 1 + + + + + + + + + + EEG scalp radius of sphere model [mm] + + + + + + 1 + + + 500.000000000000000 + + + 1.000000000000000 + + + + + + + + + + Sphere Model Origin (x,y,z) [mm] + + + + + + 1 + + + -500.000000000000000 + + + 500.000000000000000 + + + 1.000000000000000 + + + + + + + 1 + + + -500.000000000000000 + + + 500.000000000000000 + + + 1.000000000000000 + + + + + + + 1 + + + -500.000000000000000 + + + 500.000000000000000 + + + 1.000000000000000 + + + + + + + + + + EEG model name + + + false + + + + + + + 140 + 0 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - Forward Solution Computation + diff --git a/libraries/disp/viewers/fwdsettingsview.cpp b/libraries/disp/viewers/fwdsettingsview.cpp index 6d4c3075ef3..57de7956275 100644 --- a/libraries/disp/viewers/fwdsettingsview.cpp +++ b/libraries/disp/viewers/fwdsettingsview.cpp @@ -2,12 +2,13 @@ /** * @file fwdsettingsview.cpp * @author Ruben Dörfel + * Gabriel B Motta * @since 0.1.1 * @date May, 2020 * * @section LICENSE * - * Copyright (C) 2020, Ruben Dörfel. All rights reserved. + * Copyright (C) 2020, Ruben Dörfel, 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: @@ -40,6 +41,7 @@ #include "ui_fwdsettingsview.h" #include +#include //============================================================================================================= // QT INCLUDES @@ -307,3 +309,280 @@ void FwdSettingsView::clearView() { } + +//============================================================================================================= + +void FwdSettingsView::setSettings(QSharedPointer pSettings) +{ + m_pFwdSettings = pSettings; + + // init line edits + m_pUi->m_qLineEdit_SolName->setText(m_pFwdSettings->solname); + m_pUi->m_qLineEdit_MeasName->setText(m_pFwdSettings->measname); + m_pUi->m_qLineEdit_BemName->setText(m_pFwdSettings->bemname); + m_pUi->m_qLineEdit_SourceName->setText(m_pFwdSettings->srcname); + m_pUi->m_qLineEdit_MriName->setText(m_pFwdSettings->mriname); + m_pUi->m_qLineEdit_MinDistName->setText(m_pFwdSettings->mindistoutname); + m_pUi->m_qLineEdit_EEGModelFile->setText(m_pFwdSettings->eeg_model_file); + m_pUi->m_qLineEdit_EEGModelName->setText(m_pFwdSettings->eeg_model_name); + + // init checkboxes + m_pUi->m_check_bDoAll->setChecked(m_pFwdSettings->do_all); + m_pUi->m_check_bIncludeEEG->setChecked(m_pFwdSettings->include_eeg); + m_pUi->m_check_bIncludeMeg->setChecked(m_pFwdSettings->include_meg); + m_pUi->m_check_bComputeGrad->setChecked(m_pFwdSettings->compute_grad); + + if(m_pFwdSettings->coord_frame == FIFFV_COORD_MRI) { + m_pUi->m_check_bCoordframe->setChecked(true); + } else { + m_pUi->m_check_bCoordframe->setChecked(false); + } + + m_pUi->m_check_bAccurate->setChecked(m_pFwdSettings->accurate); + m_pUi->m_check_bFixedOri->setChecked(m_pFwdSettings->fixed_ori); + m_pUi->m_check_bFilterSpaces->setChecked(m_pFwdSettings->filter_spaces); + m_pUi->m_check_bMriHeadIdent->setChecked(m_pFwdSettings->mri_head_ident); + m_pUi->m_check_bUseThreads->setChecked(m_pFwdSettings->use_threads); + m_pUi->m_check_bUseEquivEeg->setChecked(m_pFwdSettings->use_equiv_eeg); + + // init Spin Boxes + m_pUi->m_doubleSpinBox_dMinDist->setValue(m_pFwdSettings->mindist*1000); + m_pUi->m_doubleSpinBox_dEegSphereRad->setValue(m_pFwdSettings->eeg_sphere_rad*1000); + m_pUi->m_doubleSpinBox_dVecR0x->setValue(m_pFwdSettings->r0.x()*1000); + m_pUi->m_doubleSpinBox_dVecR0y->setValue(m_pFwdSettings->r0.y()*1000); + m_pUi->m_doubleSpinBox_dVecR0z->setValue(m_pFwdSettings->r0.z()*1000); + + // connect line edits + connect(m_pUi->m_qLineEdit_SolName, &QLineEdit::textChanged, this, &FwdSettingsView::onSolNameChanged); + connect(m_pUi->m_qLineEdit_MinDistName, &QLineEdit::textChanged, this, &FwdSettingsView::onMinDistNameChanged); + + // connect checkboxes + connect(m_pUi->m_check_bDoAll, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bAccurate, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bFixedOri, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bCoordframe, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bIncludeEEG, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bIncludeMeg, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bUseThreads, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bComputeGrad, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bScaleEegPos, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bUseEquivEeg, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bFilterSpaces, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + connect(m_pUi->m_check_bMriHeadIdent, &QCheckBox::stateChanged, this, &FwdSettingsView::onCheckStateChanged); + + // connect spin boxes + connect(m_pUi->m_doubleSpinBox_dMinDist,static_cast(&QDoubleSpinBox::valueChanged), this, &FwdSettingsView::onMinDistChanged); + connect(m_pUi->m_doubleSpinBox_dEegSphereRad, static_cast(&QDoubleSpinBox::valueChanged), this, &FwdSettingsView::onEEGSphereRadChanged); + connect(m_pUi->m_doubleSpinBox_dVecR0x, static_cast(&QDoubleSpinBox::valueChanged), this, &FwdSettingsView::onEEGSphereOriginChanged); + connect(m_pUi->m_doubleSpinBox_dVecR0y, static_cast(&QDoubleSpinBox::valueChanged), this, &FwdSettingsView::onEEGSphereOriginChanged); + connect(m_pUi->m_doubleSpinBox_dVecR0z, static_cast(&QDoubleSpinBox::valueChanged), this, &FwdSettingsView::onEEGSphereOriginChanged); + + // connet push buttons + connect(m_pUi->m_qPushButton_SolNameDialog, &QPushButton::released, this, &FwdSettingsView::showFwdDirDialog); + connect(m_pUi->m_qPushButton_BemNameDialog, &QPushButton::released, this, &FwdSettingsView::showBemFileDialog); + connect(m_pUi->m_qPushButton_MeasNameDialog, &QPushButton::released, this, &FwdSettingsView::showMeasFileDialog); + connect(m_pUi->m_qPushButton_SourceNameDialog, &QPushButton::released, this, &FwdSettingsView::showSourceFileDialog); + connect(m_pUi->m_qPushButton_MriNameDialog, &QPushButton::released, this, &FwdSettingsView::showMriFileDialog); + connect(m_pUi->m_qPushButton_MinDistOutDialog, &QPushButton::released, this, &FwdSettingsView::showMinDistDirDialog); + connect(m_pUi->m_qPushButton_EEGModelFileDialog, &QPushButton::released, this, &FwdSettingsView::showEEGModelFileDialog); + +} + +//============================================================================================================= + +void FwdSettingsView::showFwdDirDialog() +{ + QString t_sSolDir = QFileDialog::getExistingDirectory(this, + tr("Select Directory to store the forward solution"), + QString(), + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + + m_pUi->m_qLineEdit_SolName->setText(t_sSolDir); +} + +//============================================================================================================= + +void FwdSettingsView::onSolNameChanged() +{ + QString t_sFileName = m_pUi->m_qLineEdit_SolName->text(); + + // check for file endings + if(t_sFileName.contains("-fwd.fif")) { + m_pFwdSettings->solname = t_sFileName; + } else { + qWarning() << "rtFwdSetup: make sure to name solution file correctly: -fwd.fif"; + } +} + +//============================================================================================================= + +void FwdSettingsView::showMeasFileDialog() +{ + QString t_sFileName = QFileDialog::getOpenFileName(this, + tr("Select Measurement File"), + QString(), + tr("Fif Files (*.fif)")); + + m_pUi->m_qLineEdit_MeasName->setText(t_sFileName); + + QFile t_fSource(t_sFileName); + if(t_fSource.open(QIODevice::ReadOnly)) { + m_pFwdSettings->measname = t_sFileName; + m_pUi->m_qLineEdit_MeasName->setText(t_sFileName); + } else { + qWarning() << "rtFwdSetup: Measurement file cannot be opened"; + } + t_fSource.close(); + +} + +//============================================================================================================= + +void FwdSettingsView::showSourceFileDialog() +{ + QString t_sFileName = QFileDialog::getOpenFileName(this, + tr("Select Source Space"), + QString(), + tr("Fif Files (*.fif)")); + + QFile t_fSource(t_sFileName); + if(t_fSource.open(QIODevice::ReadOnly)) { + m_pFwdSettings->srcname = t_sFileName; + m_pUi->m_qLineEdit_SourceName->setText(t_sFileName); + } else { + qWarning() << "rtFwdSetup: Source file cannot be opened"; + } + t_fSource.close(); +} + +//============================================================================================================= + +void FwdSettingsView::showBemFileDialog() +{ + QString t_sFileName = QFileDialog::getOpenFileName(this, + tr("Select Bem Model"), + QString(), + tr("Fif Files (*.fif)")); + + QFile t_fBem(t_sFileName); + if(t_fBem.open(QIODevice::ReadOnly)) { + m_pFwdSettings->bemname = t_sFileName; + m_pUi->m_qLineEdit_BemName->setText(t_sFileName); + } else { + qWarning() << "rtFwdSetup: Bem file cannot be opened"; + } + t_fBem.close(); +} + +//============================================================================================================= + +void FwdSettingsView::showMriFileDialog() +{ + QString t_sFileName = QFileDialog::getOpenFileName(this, + tr("Select Mri-Head Transformation"), + QString(), + tr("Fif Files (*.fif)")); + + QFile t_fMri(t_sFileName); + if(t_fMri.open(QIODevice::ReadOnly)) { + m_pFwdSettings->mriname = t_sFileName; + m_pUi->m_qLineEdit_MriName->setText(t_sFileName); + } else { + qWarning() << "rtFwdSetup: Mri-Head transformation cannot be opened"; + } + t_fMri.close(); +} + +//============================================================================================================= + +void FwdSettingsView::showEEGModelFileDialog() +{ + QString t_sFileName = QFileDialog::getOpenFileName(this, + tr("Select EEG model"), + QString(), + tr("Fif Files (*.fif)")); + + QFile t_fEegModel(t_sFileName); + if(t_fEegModel.open(QIODevice::ReadOnly)) { + m_pFwdSettings->eeg_model_file = t_sFileName; + m_pUi->m_qLineEdit_EEGModelFile->setText(t_sFileName); + } else { + qWarning() << "rtFwdSetup: Eeg model file cannot be opened"; + } + t_fEegModel.close(); +} + +//============================================================================================================= + +void FwdSettingsView::onEEGModelNameChanged() +{ + m_pFwdSettings->eeg_model_name = m_pUi->m_qLineEdit_EEGModelName->text(); +} + +//============================================================================================================= + +void FwdSettingsView::showMinDistDirDialog() +{ + QString t_sMinDistDir = QFileDialog::getExistingDirectory(this, + tr("Select output for omitted source space"), + QString(), + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + + m_pUi->m_qLineEdit_MinDistName->setText(t_sMinDistDir); +} + +//============================================================================================================= + +void FwdSettingsView::onMinDistNameChanged() +{ + QString t_sFileName = m_pUi->m_qLineEdit_MinDistName->text(); + m_pFwdSettings->mindistoutname = t_sFileName; +} + +//============================================================================================================= + +void FwdSettingsView::onMinDistChanged() +{ + m_pFwdSettings->mindist = m_pUi->m_doubleSpinBox_dMinDist->value()/1000; +} +//============================================================================================================= + +void FwdSettingsView::onEEGSphereRadChanged() +{ + m_pFwdSettings->eeg_sphere_rad = m_pUi->m_doubleSpinBox_dEegSphereRad->value()/1000; +} + +//============================================================================================================= + +void FwdSettingsView::onEEGSphereOriginChanged() +{ + m_pFwdSettings->r0.x() = m_pUi->m_doubleSpinBox_dVecR0x->value()/1000; + m_pFwdSettings->r0.y() = m_pUi->m_doubleSpinBox_dVecR0y->value()/1000; + m_pFwdSettings->r0.z() = m_pUi->m_doubleSpinBox_dVecR0z->value()/1000; +} + +//============================================================================================================= + +void FwdSettingsView::onCheckStateChanged() +{ + m_pFwdSettings->do_all = m_pUi->m_check_bDoAll->isChecked(); + m_pFwdSettings->include_eeg = m_pUi->m_check_bIncludeEEG->isChecked(); + m_pFwdSettings->include_meg = m_pUi->m_check_bIncludeMeg->isChecked(); + m_pFwdSettings->compute_grad = m_pUi->m_check_bComputeGrad->isChecked(); + + if( m_pUi->m_check_bCoordframe->isChecked()) { + m_pFwdSettings->coord_frame = FIFFV_COORD_MRI; + } else { + m_pFwdSettings->coord_frame = FIFFV_COORD_HEAD; + } + + m_pFwdSettings->accurate = m_pUi->m_check_bAccurate->isChecked(); + m_pFwdSettings->fixed_ori = m_pUi->m_check_bFixedOri->isChecked(); + m_pFwdSettings->filter_spaces = m_pUi->m_check_bFilterSpaces->isChecked(); + m_pFwdSettings->mri_head_ident = m_pUi->m_check_bMriHeadIdent->isChecked(); + m_pFwdSettings->use_threads = m_pUi->m_check_bUseThreads->isChecked(); + m_pFwdSettings->use_equiv_eeg = m_pUi->m_check_bUseEquivEeg->isChecked(); + m_pFwdSettings->scale_eeg_pos = m_pUi->m_check_bScaleEegPos->isChecked(); +} diff --git a/libraries/disp/viewers/fwdsettingsview.h b/libraries/disp/viewers/fwdsettingsview.h index 6b95374f63a..4c541998efc 100644 --- a/libraries/disp/viewers/fwdsettingsview.h +++ b/libraries/disp/viewers/fwdsettingsview.h @@ -2,12 +2,13 @@ /** * @file fwdsettingsview.h * @author Ruben Dörfel + * Gabriel B Motta * @since 0.1.1 * @date May, 2020 * * @section LICENSE * - * Copyright (C) 2020, Ruben Dörfel. All rights reserved. + * Copyright (C) 2020, Ruben Dörfel, 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: @@ -63,6 +64,10 @@ namespace FSLIB { class AnnotationSet; } +namespace FWDLIB{ + class ComputeFwdSettings; +} + namespace Ui { class FwdSettingsViewWidget; } @@ -179,6 +184,8 @@ class DISPSHARED_EXPORT FwdSettingsView : public AbstractView */ void clearView(); + void setSettings(QSharedPointer pSettings); + protected: //========================================================================================================= /** @@ -202,6 +209,95 @@ class DISPSHARED_EXPORT FwdSettingsView : public AbstractView QString m_sSettingsPath; /**< The settings path to store the GUI settings to. */ + QSharedPointer m_pFwdSettings; + +private: + //========================================================================================================= + /** + * Shows forward solution directory selection dialog + */ + void showFwdDirDialog(); + + //========================================================================================================= + /** + * change name of solution file + */ + void onSolNameChanged(); + + //========================================================================================================= + /** + * Shows measurement selection dialog + */ + void showMeasFileDialog(); + + //========================================================================================================= + /** + * Shows source space selection dialog + */ + void showSourceFileDialog(); + + //========================================================================================================= + /** + * Shows Bem model selection dialog + */ + void showBemFileDialog(); + + //========================================================================================================= + /** + * Shows Mri->Head transformation selection dialog + */ + void showMriFileDialog(); + + //========================================================================================================= + /** + * Shows output file selection dialog + */ + void showMinDistDirDialog(); + + QString m_sMinDistDir; + + //========================================================================================================= + /** + * Change name of MinDistDir output + */ + void onMinDistNameChanged(); + + //========================================================================================================= + /** + * Shows EEG model selection dialog + */ + void showEEGModelFileDialog(); + + //========================================================================================================= + /** + * Shows EEG model name selection selection dialog + */ + void onEEGModelNameChanged(); + + //========================================================================================================= + /** + * Change value of minimum distance skull - source + */ + void onMinDistChanged(); + + //========================================================================================================= + /** + * Change EEG sphere radius + */ + void onEEGSphereRadChanged(); + + //========================================================================================================= + /** + * Change EEG sphere origin + */ + void onEEGSphereOriginChanged(); + + //========================================================================================================= + /** + * Change settings from checkboxes + */ + void onCheckStateChanged(); + signals: //========================================================================================================= /** diff --git a/libraries/disp/viewers/helpers/bidsviewmodel.h b/libraries/disp/viewers/helpers/bidsviewmodel.h index 1834849dec8..845575479a6 100644 --- a/libraries/disp/viewers/helpers/bidsviewmodel.h +++ b/libraries/disp/viewers/helpers/bidsviewmodel.h @@ -59,7 +59,7 @@ //SUB-ITEMS #define BIDS_AVERAGE 20 -#define BIDS_EVENT 21 +#define BIDS_EVENT 21 #define BIDS_DIPOLE 22 #define BIDS_UNKNOWN 99 diff --git a/libraries/mne/mne_forwardsolution.h b/libraries/mne/mne_forwardsolution.h index a6b7bd70b2d..795512b7484 100644 --- a/libraries/mne/mne_forwardsolution.h +++ b/libraries/mne/mne_forwardsolution.h @@ -589,4 +589,14 @@ inline bool operator== (const MNEForwardSolution &a, const MNEForwardSolution &b } } // NAMESPACE +#ifndef metatype_mneforwardsolution +#define metatype_mneforwardsolution +Q_DECLARE_METATYPE(MNELIB::MNEForwardSolution);/**< Provides QT META type declaration of the MNELIB::MNEForwardSolution type. For signal/slot and QVariant usage.*/ +#endif + +#ifndef metatype_mneforwardsolutionsptr +#define metatype_mneforwardsolutionsptr +Q_DECLARE_METATYPE(MNELIB::MNEForwardSolution::SPtr);/**< Provides QT META type declaration of the MNELIB::MNEForwardSolution::SPtr type. For signal/slot and QVariant usage.*/ +#endif + #endif // MNE_FORWARDSOLUTION_H diff --git a/libraries/mne/mne_sourceestimate.h b/libraries/mne/mne_sourceestimate.h index f63a8c29c87..d464fabdd7d 100644 --- a/libraries/mne/mne_sourceestimate.h +++ b/libraries/mne/mne_sourceestimate.h @@ -221,4 +221,13 @@ inline bool MNESourceEstimate::isEmpty() const } } //NAMESPACE +#ifndef metatype_mnesourceestimate +Q_DECLARE_METATYPE(MNELIB::MNESourceEstimate);/**< Provides QT META type declaration of the MNELIB::MNEForwardSolution type. For signal/slot and QVariant usage.*/ +#endif + +#ifndef metatype_mnesourceestimatesptr +#define metatype_mnesourceestimatesptr +Q_DECLARE_METATYPE(MNELIB::MNESourceEstimate::SPtr);/**< Provides QT META type declaration of the MNELIB::MNEForwardSolution::SPtr type. For signal/slot and QVariant usage.*/ +#endif + #endif // MNESOURCEESTIMATE_H