Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Maint] Cleanup Hpi refactoring #890

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
102 changes: 52 additions & 50 deletions applications/mne_scan/plugins/hpi/hpi.cpp
Original file line number Diff line number Diff line change
@@ -217,7 +217,12 @@ void Hpi::update(SCMEASLIB::Measurement::SPtr pMeasurement)
}
}

if(m_bDoContinousHpi && (m_vCoilFreqs.size() >= 3)) {
m_mutex.lock();
bool bDoContinousHpi = m_bDoContinousHpi;
int iNumberHpiCoils = m_vCoilFreqs.size();
m_mutex.unlock();

if(bDoContinousHpi && (iNumberHpiCoils >= 3)) {
for(unsigned char i = 0; i < pRTMSA->getMultiSampleArray().size(); ++i) {
// Please note that we do not need a copy here since this function will block until
// the buffer accepts new data again. Hence, the data is not deleted in the actual
@@ -283,14 +288,7 @@ void Hpi::updateDigitizerInfo()

void Hpi::initPluginControlWidgets()
{
bool bFiffInfo = false;
m_mutex.lock();
if(m_pFiffInfo) {
bFiffInfo = true;
}
m_mutex.unlock();

if(bFiffInfo) {
QList<QWidget*> plControlWidgets;

// Projects Settings
@@ -366,14 +364,19 @@ void Hpi::updateProjections()
}
m_mutex.unlock();

m_mutex.lock();
Eigen::MatrixXd matProjectors = Eigen::MatrixXd::Identity(m_pFiffInfo->chs.size(), m_pFiffInfo->chs.size());
Eigen::MatrixXd matComp = Eigen::MatrixXd::Identity(m_pFiffInfo->chs.size(), m_pFiffInfo->chs.size());

if(m_bUseSSP) {
bool bUseSSP = m_bUseSSP;
m_mutex.unlock();

if(bUseSSP) {
// Use SSP + SGM + calibration
//Do a copy here because we are going to change the activity flags of the SSP's
m_mutex.lock();
FiffInfo infoTemp = *(m_pFiffInfo.data());

m_mutex.unlock();
//Turn on all SSP
for(int i = 0; i < infoTemp.projs.size(); ++i) {
infoTemp.projs[i].active = true;
@@ -387,13 +390,19 @@ void Hpi::updateProjections()
}
}

if(m_bUseComp) {
m_mutex.lock();
bool bUseComp = m_bUseComp;
m_mutex.unlock();

if(bUseComp) {
// Setup Comps
FiffCtfComp newComp;
//Do this always from 0 since we always read new raw data, we never actually perform a multiplication on already existing data
m_mutex.lock();
if(m_pFiffInfo->make_compensator(0, 101, newComp)) {
matComp = newComp.data->data;
}
m_mutex.unlock();
}

m_mutex.lock();
@@ -448,7 +457,11 @@ void Hpi::onDigitizersChanged(const QList<FIFFLIB::FiffDigPoint>& lDigitzers,

void Hpi::onDoSingleHpiFit()
{
if(m_vCoilFreqs.size() < 3) {
m_mutex.lock();
int iNumberHpiCoils = m_vCoilFreqs.size();
m_mutex.unlock();

if(iNumberHpiCoils < 3) {
QMessageBox msgBox;
msgBox.setText("Please input HPI coil frequencies first.");
msgBox.exec();
@@ -464,13 +477,16 @@ void Hpi::onDoSingleHpiFit()

void Hpi::onDoFreqOrder()
{
if(m_vCoilFreqs.size() < 3) {
m_mutex.lock();
int iNumberHpiCoils = m_vCoilFreqs.size();
m_mutex.unlock();

if(iNumberHpiCoils < 3) {
QMessageBox msgBox;
msgBox.setText("Please input HPI coil frequencies first.");
msgBox.exec();
return;
}

m_mutex.lock();
m_bDoFreqOrder = true;
m_mutex.unlock();
@@ -489,30 +505,31 @@ void Hpi::onCoilFrequenciesChanged(const QVector<int>& vCoilFreqs)

void Hpi::onSspStatusChanged(bool bChecked)
{
m_mutex.lock();
m_bUseSSP = bChecked;
m_mutex.unlock();
updateProjections();
}

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

void Hpi::onCompStatusChanged(bool bChecked)
{
m_mutex.lock();
m_bUseComp = bChecked;
m_mutex.unlock();
updateProjections();
}

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

void Hpi::onContHpiStatusChanged(bool bChecked)
{
// if(m_vCoilFreqs.size() < 3) {
// QMessageBox msgBox;
// msgBox.setText("Please load a digitizer set with at least 3 HPI coils first.");
// msgBox.exec();
// return;
// }

m_mutex.lock();
m_bDoContinousHpi = bChecked;
m_mutex.unlock();

}

//=============================================================================================================
@@ -527,44 +544,30 @@ void Hpi::setFittingWindowSize(int winSize)

void Hpi::onDevHeadTransAvailable(const FIFFLIB::FiffCoordTrans& devHeadTrans)
{
m_mutex.lock();
m_pFiffInfo->dev_head_t = devHeadTrans;
m_mutex.unlock();
}

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

void Hpi::run()
{
// Wait for fiff info
bool bFiffInfo = false;

while(true) {
m_mutex.lock();
if(m_pFiffInfo) {
bFiffInfo = true;
}
m_mutex.unlock();
if(bFiffInfo) {
break;
}
while(!m_pFiffInfo) {
msleep(100);
}

// init hpi fit
HpiModelParameters hpiModelParameters(m_vCoilFreqs,
m_pFiffInfo->sfreq,
m_pFiffInfo->linefreq,
false);
HpiFitResult fitResult;
fitResult.hpiFreqs = m_vCoilFreqs;
fitResult.errorDistances = QVector<double>(m_vCoilFreqs.size());
fitResult.devHeadTrans = m_pFiffInfo->dev_head_t;
fitResult.devHeadTrans.from = 1;
fitResult.devHeadTrans.to = 4;

m_mutex.lock();
FiffCoordTrans transDevHeadRef = m_pFiffInfo->dev_head_t;

int fittingWindowSize = m_iFittingWindowSize;
MatrixXd matDataMerged(m_pFiffInfo->chs.size(), fittingWindowSize);
HpiDataUpdater hpiDataUpdater = HpiDataUpdater(m_pFiffInfo);
m_mutex.unlock();

HPIFit HPI = HPIFit(hpiDataUpdater.getSensors());
HpiFitResult fitResult;
HpiModelParameters hpiModelParameters;

double dErrorMax = 0.0;
double dMeanErrorDist = 0.0;
@@ -577,11 +580,7 @@ void Hpi::run()
int iDataIndexCounter = 0;
MatrixXd matData;

m_mutex.lock();
int fittingWindowSize = m_iFittingWindowSize;
m_mutex.unlock();

MatrixXd matDataMerged(m_pFiffInfo->chs.size(), fittingWindowSize);
bool bOrder = false;

while(!isInterruptionRequested()) {
@@ -616,8 +615,11 @@ void Hpi::run()
m_pFiffInfo->sfreq,
m_pFiffInfo->linefreq,
false);
hpiDataUpdater.checkForUpdate(m_pFiffInfo);
HPI.checkForUpdate(hpiDataUpdater.getSensors());
bool bHasChanged = hpiDataUpdater.checkForUpdate(m_pFiffInfo);

if(bHasChanged) {
HPI.setSensorSet(hpiDataUpdater.getSensors());
}

hpiDataUpdater.prepareDataAndProjectors(matDataMerged,m_matCompProjectors);
bOrder = m_bDoFreqOrder;
3 changes: 2 additions & 1 deletion libraries/inverse/hpiFit/hpidataupdater.cpp
Original file line number Diff line number Diff line change
@@ -148,7 +148,7 @@ void HpiDataUpdater::updateHpiDigitizer(const QList<FiffDigPoint>& lDig)

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

void HpiDataUpdater::checkForUpdate(const FiffInfo::SPtr pFiffInfo)
bool HpiDataUpdater::checkForUpdate(const FiffInfo::SPtr pFiffInfo)
{
const bool bUpdate = checkIfChanged(pFiffInfo->bads,pFiffInfo->chs);
if(bUpdate)
@@ -158,6 +158,7 @@ void HpiDataUpdater::checkForUpdate(const FiffInfo::SPtr pFiffInfo)
updateHpiDigitizer(pFiffInfo->dig);
updateSensors(m_lChannels);
}
return bUpdate;
}

//=============================================================================================================
4 changes: 2 additions & 2 deletions libraries/inverse/hpiFit/hpidataupdater.h
Original file line number Diff line number Diff line change
@@ -103,9 +103,9 @@ class INVERSESHARED_EXPORT HpiDataUpdater
* Check if information in FiffInfo changed and update if necessary.
*
* @param[in] pFiffInfo The FiffInfo to check for changes.
*
* @return If information in pFiffInfo has changed and data was updated.
*/
void checkForUpdate(const QSharedPointer<FIFFLIB::FiffInfo> pFiffInfo);
bool checkForUpdate(const QSharedPointer<FIFFLIB::FiffInfo> pFiffInfo);

//=========================================================================================================
/**
2 changes: 1 addition & 1 deletion libraries/inverse/hpiFit/hpifit.cpp
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ HPIFit::HPIFit(const SensorSet& sensorSet)

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

void HPIFit::checkForUpdate(const SensorSet &sensorSet)
void HPIFit::setSensorSet(const SensorSet &sensorSet)
{
if(m_sensors != sensorSet) {
m_sensors = sensorSet;
11 changes: 2 additions & 9 deletions libraries/inverse/hpiFit/hpifit.h
Original file line number Diff line number Diff line change
@@ -138,13 +138,6 @@ class INVERSESHARED_EXPORT HPIFit
typedef QSharedPointer<HPIFit> SPtr; /**< Shared pointer type for HPIFit. */
typedef QSharedPointer<const HPIFit> ConstSPtr; /**< Const shared pointer type for HPIFit. */

//=========================================================================================================
/**
* Default constructor.
*
*/
explicit HPIFit();

//=========================================================================================================
/**
* Constructs the HPI from a SensorSet.
@@ -159,7 +152,7 @@ class INVERSESHARED_EXPORT HPIFit
*
* @param[in] SensorSet The MEG sensorSet used for the hpi fitting.
*/
void checkForUpdate(const SensorSet& sensorSet);
void setSensorSet(const SensorSet& sensorSet);

//=========================================================================================================
/**
@@ -170,7 +163,7 @@ class INVERSESHARED_EXPORT HPIFit
* @param[in] hpiModelParameters The model parameters to use for the Hpi Fitting, especially to compute the coil amplitudes.
* @param[in] matCoilsHead The hpi coil locations in head space.
* @param[in] bOrderFrequencies Order Hpi coils yes/no.
* @param[out] hpiFitResult The fitting results.
* @param[in,out] hpiFitResult The fitting results.
*/
void fit(const Eigen::MatrixXd& matProjectedData,
const Eigen::MatrixXd& matProjectors,
8 changes: 4 additions & 4 deletions libraries/inverse/hpiFit/hpimodelparameters.h
Original file line number Diff line number Diff line change
@@ -32,8 +32,8 @@
*
*/

#ifndef INVERSELIBE_HPIMODELPARAMETERS_H
#define INVERSELIBE_HPIMODELPARAMETERS_H
#ifndef HPIMODELPARAMETERS_H
#define HPIMODELPARAMETERS_H

//=============================================================================================================
// INCLUDES
@@ -70,9 +70,9 @@ namespace INVERSELIB {

//=============================================================================================================
/**
* Description of what this class is intended to do (in detail).
* HpiModelParamers holds the information to be used for the HpiFit in general, ans especially for extracting the hpi coil amplitudes from the measurement.
*
* @brief Brief description of this class.
* @brief HpiModelParamers holds the information to be used for the HpiFit in general, ans especially for extracting the hpi coil amplitudes from the measurement.
*/
class INVERSESHARED_EXPORT HpiModelParameters
{
2 changes: 1 addition & 1 deletion libraries/inverse/hpiFit/sensorset.cpp
Original file line number Diff line number Diff line change
@@ -131,7 +131,7 @@ void SensorSet::initMatrices(int ncoils, int np)

SensorSetCreator::SensorSetCreator()
{
const QString qPath = QString(QCoreApplication::applicationDirPath() + "/resources/general/coilDefinitions/coil_def.dat");
const QString qPath = QCoreApplication::applicationDirPath() + "/resources/general/coilDefinitions/coil_def.dat";
m_pCoilDefinitions = FwdCoilSet::SPtr(FwdCoilSet::read_coil_defs(qPath));
}

15 changes: 11 additions & 4 deletions libraries/inverse/hpiFit/sensorset.h
Original file line number Diff line number Diff line change
@@ -75,7 +75,14 @@ namespace FIFFLIB{

namespace INVERSELIB
{
enum class Accuracy : int{high = 2, medium = 1, low = 0};
enum class Accuracy : int{low = 0, medium = 1, high = 2};

//=============================================================================================================
/**
* A SensorSet object holds information about the position and orientation of the MEG sensor arrays.
*
* @brief A SensorSet object holds information about the position and orientation of the MEG sensor arrays.
*/

class INVERSESHARED_EXPORT SensorSet {

@@ -240,9 +247,9 @@ inline bool SensorSet::operator!= (const SensorSet &b) const

//=============================================================================================================
/**
* Create a SensorSet struct from a channel list with specified accuracy.
* Create a SensorSet struct from a channel list with specified accuracy. Reads sensor information from Coil Definition file.
*
* @brief Brief description of this class.
* @brief Create a SensorSet struct from a channel list with specified accuracy. Reads sensor information from Coil Definition file.
*/
class INVERSESHARED_EXPORT SensorSetCreator
{
@@ -269,7 +276,7 @@ class INVERSESHARED_EXPORT SensorSetCreator
const Accuracy& accuracy);

private:
QSharedPointer<FWDLIB::FwdCoilSet> m_pCoilDefinitions{nullptr}; // the coil definitions as template
QSharedPointer<FWDLIB::FwdCoilSet> m_pCoilDefinitions; // the coil definitions as template
};

//=============================================================================================================
10 changes: 2 additions & 8 deletions libraries/inverse/hpiFit/signalmodel.h
Original file line number Diff line number Diff line change
@@ -67,9 +67,9 @@ namespace INVERSELIB

//=============================================================================================================
/**
* Description of what this class is intended to do (in detail).
* This class creates and fits a linear model to extract the amplitudes of the hpi coils from measurement data.
*
* @brief Brief description of this class.
* @brief This class creates and fits a linear model to extract the amplitudes of the hpi coils from measurement data..
*/
class INVERSESHARED_EXPORT SignalModel
{
@@ -78,12 +78,6 @@ class INVERSESHARED_EXPORT SignalModel
typedef QSharedPointer<SignalModel> SPtr; /**< Shared pointer type for SignalModel. */
typedef QSharedPointer<const SignalModel> ConstSPtr; /**< Const shared pointer type for SignalModel. */

//=========================================================================================================
/**
* Constructs a SignalModel object.
*/
explicit SignalModel() = default;

//=========================================================================================================
/**
* Fit the data to the model constructed from given model parameters.
25 changes: 20 additions & 5 deletions testframes/test_hpiDataUpdater/test_hpiDataUpdater.cpp
Original file line number Diff line number Diff line change
@@ -89,6 +89,7 @@ private slots:
void testPrepareData();
void testGetSensors();
void testGetSensors_bads();
void testCheckForUpdates_return();
void testCheckForUpdates_sensors();
void testCheckForUpdates_data();
void testCheckForUpdates_projectors();
@@ -321,8 +322,6 @@ void TestHpiDataUpdater::testGetSensors()
void TestHpiDataUpdater::testGetSensors_bads()
{
// extract data for channels to use
int iAccuracy = 2;

SensorSetCreator sensorCreator;
SensorSet sensorsExpected = sensorCreator.updateSensorSet(m_lChannelsWithBads,Accuracy::high);

@@ -338,6 +337,22 @@ void TestHpiDataUpdater::testGetSensors_bads()

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

void TestHpiDataUpdater::testCheckForUpdates_return()
{
HpiDataUpdater hpiData = HpiDataUpdater(m_pFiffInfo);
m_pFiffInfo->bads << "MEG0113" << "MEG0112";
SensorSetCreator sensorCreator;
SensorSet sensorsExpected = sensorCreator.updateSensorSet(m_lChannelsWithBads,Accuracy::high);

/// act
bool hasChanged = hpiData.checkForUpdate(m_pFiffInfo);

/// assert
QVERIFY(hasChanged);
}

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

void TestHpiDataUpdater::testCheckForUpdates_sensors()
{
HpiDataUpdater hpiData = HpiDataUpdater(m_pFiffInfo);
@@ -346,7 +361,7 @@ void TestHpiDataUpdater::testCheckForUpdates_sensors()
SensorSet sensorsExpected = sensorCreator.updateSensorSet(m_lChannelsWithBads,Accuracy::high);

/// act
hpiData.checkForUpdate(m_pFiffInfo);
bool bHasChanged = hpiData.checkForUpdate(m_pFiffInfo);
SensorSet sensorsActual = hpiData.getSensors();

/// assert
@@ -366,7 +381,7 @@ void TestHpiDataUpdater::testCheckForUpdates_data()
}

/// act
hpiData.checkForUpdate(m_pFiffInfo);
bool bHasChanged = hpiData.checkForUpdate(m_pFiffInfo);
hpiData.prepareDataAndProjectors(m_matData,m_matProjectors);
MatrixXd matDataPrepared = hpiData.getData();

@@ -395,7 +410,7 @@ void TestHpiDataUpdater::testCheckForUpdates_projectors()
}

// act
hpiData.checkForUpdate(m_pFiffInfo);
bool bHasChanged = hpiData.checkForUpdate(m_pFiffInfo);
hpiData.prepareDataAndProjectors(m_matData,matProj);
MatrixXd matProjPrepared = hpiData.getProjectors();

4 changes: 2 additions & 2 deletions testframes/test_hpiFit/test_hpiFit.cpp
Original file line number Diff line number Diff line change
@@ -450,9 +450,9 @@ void TestHpiFit::testCheckForUpdate()
HPIFit HPI = HPIFit(hpiDataUpdater.getSensors());

m_pFiffInfo->bads << "MEG0113" << "MEG0112";
hpiDataUpdater.checkForUpdate(m_pFiffInfo);
bool bHasChanged = hpiDataUpdater.checkForUpdate(m_pFiffInfo);

HPI.checkForUpdate(hpiDataUpdater.getSensors());
HPI.setSensorSet(hpiDataUpdater.getSensors());

hpiDataUpdater.prepareDataAndProjectors(m_matData,m_matProjectors);
const auto& matProjectedData = hpiDataUpdater.getProjectedData();