Commit e8315fe1 authored by cornimueller's avatar cornimueller

[ADD #89] Added electrode positions to the WEEGChannelInfo. It get's the...

[ADD #89] Added electrode positions to the WEEGChannelInfo. It get's the positions from a new WPositionsLibrary class which is constructed by a WReaderELC. This reader supports more ELC-files than the old method.
[DOC] Corrected wrong spelling of "electrode" in the WMEEGView module.
parent d4416897
......@@ -33,27 +33,33 @@
#include "exceptions/WDHException.h"
#include "io/WPagerEEG.h"
#include "WEEGChannelInfo.h"
#include "WEEGPositionsLibrary.h"
#include "WEEG2Segment.h"
#include "WEEG2.h"
WEEG2::WEEG2( boost::shared_ptr< WPagerEEG > pager )
WEEG2::WEEG2( boost::shared_ptr< WPagerEEG > pager, boost::shared_ptr< WEEGPositionsLibrary > positionsLibrary )
{
if( !pager )
{
throw WDHException( "Couldn't construct new EEG: pager invalid" );
}
if( !positionsLibrary )
{
throw WDHException( "Couldn't construct new EEG: positions library invalid" );
}
m_segments.reserve( pager->getNumberOfSegments() );
for( std::size_t segmentID = 0; segmentID < pager->getNumberOfSegments(); ++segmentID )
{
m_segments.push_back( boost::shared_ptr< WEEG2Segment >( new WEEG2Segment( pager, segmentID ) ) );
m_segments.push_back( boost::shared_ptr< WEEG2Segment >( new WEEG2Segment( segmentID, pager ) ) );
}
m_channelInfos.reserve( pager->getNumberOfChannels() );
for( std::size_t channelID = 0; channelID < pager->getNumberOfChannels(); ++channelID )
{
m_channelInfos.push_back( boost::shared_ptr< WEEGChannelInfo >( new WEEGChannelInfo( pager, channelID ) ) );
m_channelInfos.push_back( boost::shared_ptr< WEEGChannelInfo >( new WEEGChannelInfo( channelID, pager, positionsLibrary ) ) );
}
}
......
......@@ -33,6 +33,7 @@
#include "io/WPagerEEG.h"
#include "WEEGChannelInfo.h"
#include "WEEGPositionsLibrary.h"
#include "WEEG2Segment.h"
#include "WRecording.h"
......@@ -49,8 +50,10 @@ public:
*
* \param pager pager class which contains the data, read from a file on
* demand
* \param positionsLibrary class which contains the positions of the
* electrodes
*/
explicit WEEG2( boost::shared_ptr< WPagerEEG > pager );
WEEG2( boost::shared_ptr< WPagerEEG > pager, boost::shared_ptr< WEEGPositionsLibrary > positionsLibrary );
/**
* Get the number of segments this EEG consists of.
......
......@@ -35,9 +35,9 @@
#include "WEEG2Segment.h"
WEEG2Segment::WEEG2Segment( boost::shared_ptr< WPagerEEG > pager, std::size_t segmentID )
: m_pager( pager ),
m_segmentID( segmentID )
WEEG2Segment::WEEG2Segment( std::size_t segmentID, boost::shared_ptr< WPagerEEG > pager )
: m_segmentID( segmentID ),
m_pager( pager )
{
if( !m_pager )
{
......
......@@ -43,11 +43,11 @@ public:
/**
* Constructor
*
* \param segmentID number of this segment
* \param pager pager class which contains the data, read from a file on
* demand
* \param segmentID number of this segment
*/
WEEG2Segment( boost::shared_ptr< WPagerEEG > pager, std::size_t segmentID );
WEEG2Segment( std::size_t segmentID, boost::shared_ptr< WPagerEEG > pager );
/**
* Get the values of all channels for a given sample range.
......@@ -60,8 +60,8 @@ public:
protected:
private:
boost::shared_ptr< WPagerEEG > m_pager; //!< pager class which contains the data, read from a file on demand
std::size_t m_segmentID; //!< number of this segment
boost::shared_ptr< WPagerEEG > m_pager; //!< pager class which contains the data, read from a file on demand
};
#endif // WEEG2SEGMENT_H
......@@ -30,18 +30,27 @@
#include <boost/shared_ptr.hpp>
#include "../common/exceptions/WOutOfBounds.h"
#include "../common/math/WPosition.h"
#include "exceptions/WDHException.h"
#include "io/WPagerEEG.h"
#include "WEEGPositionsLibrary.h"
#include "WEEGChannelInfo.h"
WEEGChannelInfo::WEEGChannelInfo( boost::shared_ptr< WPagerEEG > pager, std::size_t channelID )
WEEGChannelInfo::WEEGChannelInfo( std::size_t channelID,
boost::shared_ptr< WPagerEEG > pager,
boost::shared_ptr< WEEGPositionsLibrary > positionsLibrary )
{
if( !pager )
{
throw WDHException( "Couldn't construct new EEG channel info: pager invalid" );
}
if( !positionsLibrary )
{
throw WDHException( "Couldn't construct new EEG channel info: positions library invalid" );
}
if( channelID >= pager->getNumberOfChannels() )
{
std::ostringstream stream;
......@@ -50,9 +59,16 @@ WEEGChannelInfo::WEEGChannelInfo( boost::shared_ptr< WPagerEEG > pager, std::siz
}
m_label = pager->getChannelLabel( channelID );
m_position = positionsLibrary->getPosition( m_label );
}
std::string WEEGChannelInfo::getLabel() const
{
return m_label;
}
wmath::WPosition WEEGChannelInfo::getPosition() const
{
return m_position;
}
......@@ -31,7 +31,9 @@
#include <boost/shared_ptr.hpp>
#include "../common/math/WPosition.h"
#include "io/WPagerEEG.h"
#include "WEEGPositionsLibrary.h"
/**
......@@ -45,11 +47,15 @@ public:
/**
* Constructor
*
* \param channelID number of this channel
* \param pager pager class which contains the data, read from a file on
* demand
* \param channelID number of this channel
* \param positionsLibrary class which contains the positions of the
* electrodes
*/
WEEGChannelInfo( boost::shared_ptr< WPagerEEG > pager, std::size_t channelID );
WEEGChannelInfo( std::size_t channelID,
boost::shared_ptr< WPagerEEG > pager,
boost::shared_ptr< WEEGPositionsLibrary > positionsLibrary );
/**
* Get the label of the channel.
......@@ -58,9 +64,17 @@ public:
*/
std::string getLabel() const;
/**
* Get the position of the electrode.
*
* \return position
*/
wmath::WPosition getPosition() const;
protected:
private:
std::string m_label; //!< label of the channel
wmath::WPosition m_position; //!< position of the electrode
};
#endif // WEEGCHANNELINFO_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <map>
#include <string>
#include "../common/WStringUtils.h"
#include "../common/exceptions/WOutOfBounds.h"
#include "../common/math/WPosition.h"
#include "WEEGPositionsLibrary.h"
WEEGPositionsLibrary::WEEGPositionsLibrary( const std::map< std::string, wmath::WPosition >& positions )
{
// put all the elements from positions in m_posititions, but convert the labels to uppercase
for( std::map< std::string, wmath::WPosition >::const_iterator iter = positions.begin(); iter != positions.end(); ++iter )
{
m_positions[string_utils::toUpper( iter->first )] = iter->second;
}
}
wmath::WPosition WEEGPositionsLibrary::getPosition( std::string label ) const
{
std::map< std::string, wmath::WPosition >::const_iterator iter = m_positions.find( string_utils::toUpper( label ) );
if( iter == m_positions.end() )
{
throw WOutOfBounds( "EEG Positions Library doesn't contain a position for electrode " + label );
}
return iter->second;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WEEGPOSITIONSLIBRARY_H
#define WEEGPOSITIONSLIBRARY_H
#include <map>
#include <string>
#include "../common/math/WPosition.h"
/**
* Class which contains the positions of EEG electrodes by label.
* \ingroup dataHandler
*/
class WEEGPositionsLibrary
{
public:
/**
* Constructor
*
* \param positions mapping from labels to positions
*/
explicit WEEGPositionsLibrary( const std::map< std::string, wmath::WPosition >& positions );
/**
* Get the position of an electrode with the given label
*
* \param label label of the electrode
* \return position of the electrode
*/
wmath::WPosition getPosition( std::string label ) const;
protected:
private:
std::map< std::string, wmath::WPosition > m_positions; //!< mapping from labels to positions
};
#endif // WEEGPOSITIONSLIBRARY_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <cstddef>
#include <fstream>
#include <map>
#include <string>
#include <vector>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include "../../common/math/WPosition.h"
#include "../../common/WLogger.h"
#include "../../common/WStringUtils.h"
#include "../exceptions/WDHIOFailure.h"
#include "../exceptions/WDHNoSuchFile.h"
#include "../exceptions/WDHParseError.h"
#include "../WEEGPositionsLibrary.h"
#include "WReaderELC.h"
WReaderELC::WReaderELC( std::string fname )
: WReader( fname )
{
}
boost::shared_ptr< WEEGPositionsLibrary > WReaderELC::read()
{
std::ifstream ifs;
ifs.open( m_fname.c_str(), std::ifstream::in );
if( !ifs || ifs.bad() )
{
throw WDHNoSuchFile( "Problem loading file " + m_fname + ". Probably file not found." );
}
std::string line;
while( ifs.good() && line.substr( 0, 16 ) != "NumberPositions=" ) // go to number of positions
{
std::getline( ifs, line );
if( !ifs.good() )
{
throw WDHIOFailure( "Unexpected end of file " + m_fname );
}
}
std::vector< std::string > tokens = string_utils::tokenize( line );
std::size_t numPositions = boost::lexical_cast< std::size_t >( tokens.at( 1 ) );
while( ifs.good() && line.substr( 0, 9 ) != "Positions" ) // go to line before start of positions
{
std::getline( ifs, line );
if( !ifs.good() )
{
throw WDHIOFailure( "Unexpected end of file " + m_fname );
}
}
std::size_t posCounter = 0;
std::vector< wmath::WPosition > positions;
positions.reserve( numPositions );
while( posCounter != numPositions && ifs.good() && line.substr( 0, 6 ) != "Labels" ) // run through all positions
{
std::getline( ifs, line );
if( !ifs.good() )
{
throw WDHIOFailure( "Unexpected end of file " + m_fname );
}
else
{
++posCounter;
std::vector< std::string > lineTokens = string_utils::tokenize( line, ":" );
std::vector< std::string > posTokens = string_utils::tokenize( lineTokens.back() );
double posX = boost::lexical_cast< double >( posTokens.at( posTokens.size() - 3 ) );
double posY = boost::lexical_cast< double >( posTokens.at( posTokens.size() - 2 ) );
double posZ = boost::lexical_cast< double >( posTokens.at( posTokens.size() - 1 ) );
positions.push_back( wmath::WPosition( posX, posY, posZ ) );
}
}
if( positions.size() != numPositions )
{
throw WDHParseError( "Could not find correct number of Positions regarding to NumberPositions statement in file " + m_fname );
}
while( ifs.good() && line.substr( 0, 6 ) != "Labels" ) // go to line before start of labels
{
std::getline( ifs, line );
if( !ifs.good() )
{
throw WDHIOFailure( "Unexpected end of file " + m_fname );
}
}
std::size_t labelCounter = 0;
std::map< std::string, wmath::WPosition > positionsMap;
while( labelCounter != numPositions && ifs.good() ) // run through all labels
{
std::getline( ifs, line );
if( ifs.fail() )
{
throw WDHIOFailure( "Unexpected end of file " + m_fname );
}
else
{
std::vector< std::string > labelTokens = string_utils::tokenize( line );
for( std::size_t i = 0; i < labelTokens.size(); ++i )
{
positionsMap[labelTokens[i]] = positions[labelCounter];
++labelCounter;
}
}
}
if( positionsMap.size() != numPositions )
{
throw WDHParseError( "Could not find correct number of Labels regarding to NumberPositions statement in file " + m_fname );
}
ifs.close();
for( std::map< std::string, wmath::WPosition >::const_iterator iter = positionsMap.begin(); iter != positionsMap.end(); ++iter )
{
wlog::debug( "WReaderELC" ) << iter->first << ": " << iter->second;
}
return boost::shared_ptr< WEEGPositionsLibrary >( new WEEGPositionsLibrary( positionsMap ) );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WREADERELC_H
#define WREADERELC_H
#include <string>
#include <boost/shared_ptr.hpp>
#include "WReader.h"
#include "../WEEGPositionsLibrary.h"
/**
* Read electrode positions from an ELC file.
* \ingroup dataHandler
*/
class WReaderELC : public WReader
{
public:
/**
* Constructs a reader object.
*
* \param fname path to file which should be loaded
*/
explicit WReaderELC( std::string fname );
/**
* Read the file and create a dataset out of it.
*
* \return reference to the dataset
*/
boost::shared_ptr< WEEGPositionsLibrary > read();
protected:
private:
};
#endif // WREADERELC_H
......@@ -85,16 +85,16 @@ void WMEEGView::connectors()
void WMEEGView::properties()
{
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
m_drawElektrodes = m_properties2->addProperty( "Draw Elektrodes",
"Draw the 3D positions of the elektrodes.",
m_drawElectrodes = m_properties2->addProperty( "Draw Electrodes",
"Draw the 3D positions of the electrodes.",
true,
m_propCondition );
m_drawHeadSurface = m_properties2->addProperty( "Draw Head Surface",
"Draw the head surface between the elektrodes.",
"Draw the head surface between the electrodes.",
true,
m_propCondition );
m_drawLabels = m_properties2->addProperty( "Draw Labels",
"Draw the labels of the elektrodes at their 3D positions.",
"Draw the labels of the electrodes at their 3D positions.",
true,
m_propCondition );
}
......@@ -175,22 +175,22 @@ void WMEEGView::moduleMain()
}
}
// draw elektrodes property changed?
if( m_drawElektrodes->changed() )
// draw electrodes property changed?
if( m_drawElectrodes->changed() )
{
if( m_elektrodesNode.valid() )
if( m_electrodesNode.valid() )
{
m_rootNode3d->remove( m_elektrodesNode );
m_rootNode3d->remove( m_electrodesNode );
}
if( m_drawElektrodes->get( true ) && m_eeg.get() )
if( m_drawElectrodes->get( true ) && m_eeg.get() )
{
m_elektrodesNode = drawElektrodes();
m_rootNode3d->insert( m_elektrodesNode );
m_electrodesNode = drawElectrodes();
m_rootNode3d->insert( m_electrodesNode );
}
else
{
m_elektrodesNode = NULL;
m_electrodesNode = NULL;
}
}
......@@ -416,14 +416,14 @@ void WMEEGView::redraw()
m_event.setNode( NULL );
}
if( m_drawElektrodes->get( true ) )
if( m_drawElectrodes->get( true ) )
{
m_elektrodesNode = drawElektrodes();
m_rootNode3d->addChild( m_elektrodesNode );
m_electrodesNode = drawElectrodes();
m_rootNode3d->addChild( m_electrodesNode );
}
else
{
m_elektrodesNode = NULL;
m_electrodesNode = NULL;
}
if( m_drawHeadSurface->get( true ) )
......@@ -463,18 +463,18 @@ void WMEEGView::redraw()
m_event.setTime( -1.0 );
m_event.setNode( NULL );
m_elektrodesNode = NULL;
m_electrodesNode = NULL;
m_headSurfaceNode = NULL;
m_labelsNode = NULL;
}
}
osg::ref_ptr< osg::Node > WMEEGView::drawElektrodes()
osg::ref_ptr< osg::Node > WMEEGView::drawElectrodes()
{
// draw 3d positions of elektrodes
// draw 3d positions of electrodes
const float sphereSize = 4.0f;
osg::ref_ptr< osg::Group > elektrodes( new osg::Group );
osg::ref_ptr< osg::Group > electrodes( new osg::Group );
for( size_t channel = 0; channel < m_eeg->getNumberOfChannels(); ++channel )
{
......@@ -486,10 +486,10 @@ osg::ref_ptr< osg::Node > WMEEGView::drawElektrodes()
osg::Geode* sphereGeode = new osg::Geode;
sphereGeode->addDrawable( shape );
elektrodes->addChild( sphereGeode );
electrodes->addChild( sphereGeode );
}
return elektrodes;
return electrodes;
}
osg::ref_ptr< osg::Node > WMEEGView::drawHeadSurface()
......@@ -534,7 +534,7 @@ osg::ref_ptr< osg::Node > WMEEGView::drawHeadSurface()
osg::ref_ptr< osg::Node > WMEEGView::drawLabels()
{
// draw elektrode labels in 3d
// draw electrode labels in 3d
const float sphereSize = 4.0f;
const osg::Vec3 text3dOffset( 0.0, 0.0, sphereSize );
const double text3dSize = 32.0;
......
......@@ -124,7 +124,7 @@ private:
/**
* Property determining whether elekrode positions should be drawn.
*/
WPropBool m_drawElektrodes;
WPropBool m_drawElectrodes;
/**
* Property determining whether the head surface should be drawn.
......@@ -159,9 +159,9 @@ private:
osg::ref_ptr< WGEGroupNode > m_rootNode3d;
/**
* OSG node for the 3D display of the elektrode positions