OpenWalnut  1.5.0dev
WEEGEvent.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <cstddef>
26 #include <limits>
27 #include <memory>
28 #include <sstream>
29 #include <vector>
30 
31 #include <osg/Array>
32 #include <osg/Geode>
33 #include <osg/Geometry>
34 #include <osg/PrimitiveSet>
35 #include <osg/Vec3>
36 #include <osg/Vec4>
37 #include <osg/ref_ptr>
38 #include <osgText/Text>
39 
40 #include "WEEGEvent.h"
41 #include "core/common/WStringUtils.h"
42 #include "core/common/exceptions/WOutOfBounds.h"
43 #include "core/dataHandler/WDataSetDipoles.h"
44 #include "core/dataHandler/WEEG2.h"
45 #include "core/dataHandler/WEEG2Segment.h"
46 #include "core/dataHandler/WEEGValueMatrix.h"
47 #include "core/graphicsEngine/WGEGroupNode.h"
48 
49 WEEGEvent::WEEGEvent( double time,
50  double yPos,
51  std::shared_ptr< WEEG2 > eeg,
52  std::size_t segmentID,
53  osg::ref_ptr< WGEGroupNode > parentNode,
54  bool snapToDipole,
55  bool proofOfConcept,
56  std::shared_ptr< WDataSetDipoles > dipoles )
57  : m_time( time ),
58  m_parentNode( parentNode )
59 {
60  if( segmentID < eeg->getNumberOfSegments() )
61  {
62  // snap to dipole
63  if( snapToDipole && !proofOfConcept && dipoles.get() )
64  {
65  const double epsilon = 1e-4;
66  double error = std::numeric_limits<double>::infinity();
67  for( size_t dipoleId = 0u; dipoleId < dipoles->getNumberOfDipoles(); ++dipoleId )
68  {
69  if( time < dipoles->getStartTime( dipoleId ) )
70  {
71  if( dipoles->getStartTime( dipoleId ) - time < error )
72  {
73  m_time = dipoles->getStartTime( dipoleId ) + epsilon;
74  error = dipoles->getStartTime( dipoleId ) - time;
75  }
76  }
77  else if( time > dipoles->getEndTime( dipoleId ) )
78  {
79  if( time - dipoles->getEndTime( dipoleId ) < error )
80  {
81  m_time = dipoles->getEndTime( dipoleId ) - epsilon;
82  error = time - dipoles->getEndTime( dipoleId );
83  }
84  }
85  else
86  {
87  m_time = time;
88  // error = 0.0;
89  break;
90  }
91  }
92  }
93 
94  const double sampleIDAsDouble = m_time * eeg->getSamplingRate();
95 
96  std::shared_ptr< WEEG2Segment > segment = eeg->getSegment( segmentID );
97  if( 0.0 <= sampleIDAsDouble && sampleIDAsDouble < segment->getNumberOfSamples() - 1 )
98  {
99  // calculate value of each channel at the given time position using
100  // linear interpolation
101  const std::size_t sampleID = sampleIDAsDouble;
102  const double fpart = sampleIDAsDouble - sampleID;
103  std::shared_ptr< WEEGValueMatrix > rawValues = segment->getValues( sampleID, 2 );
104  m_values.reserve( eeg->getNumberOfChannels() );
105  for( std::size_t channelID = 0; channelID < eeg->getNumberOfChannels(); ++channelID )
106  {
107  m_values.push_back( ( 1.0 - fpart ) * (*rawValues)[channelID][0] + fpart * (*rawValues)[channelID][1] );
108  }
109 
110  if( m_parentNode.valid() )
111  {
112  const osg::Vec4 color( 1.0f, 0.5f, 0.5f, 1.0f );
113 
114  // create geode to draw the event as line
115  osg::Geometry* geometry = new osg::Geometry;
116 
117  osg::Vec3Array* vertices = new osg::Vec3Array();
118  vertices->reserve( 2 );
119  vertices->push_back( osg::Vec3( m_time, -1048576.0f, 0.0f ) );
120  vertices->push_back( osg::Vec3( m_time, 1024.0f, 0.0f ) );
121  geometry->setVertexArray( vertices );
122 
123  osg::Vec4Array* colors = new osg::Vec4Array;
124  colors->push_back( color );
125  geometry->setColorArray( colors );
126  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
127 
128  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, 2 ) );
129 
130  // create text for the time label
131  osgText::Text* text = new osgText::Text;
132  text->setText( string_utils::toString( m_time ).c_str() );
133  text->setPosition( osg::Vec3( m_time, yPos + 10.0, 0.0 ) );
134  text->setAlignment( osgText::Text::LEFT_CENTER );
135  text->setAxisAlignment( osgText::Text::SCREEN );
136  text->setCharacterSize( 12 );
137  text->setCharacterSizeMode( osgText::Text::SCREEN_COORDS );
138  text->setColor( osg::Vec4( 0.0, 0.0, 1.0, 1.0 ) );
139  text->setBackdropType( osgText::Text::OUTLINE );
140  text->setBackdropColor( osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
141  text->setBackdropOffset( 0.1 );
142 
143  osg::Geode* geode = new osg::Geode;
144  geode->addDrawable( geometry );
145  geode->addDrawable( text );
146 
147 
148  m_node = geode;
149 
150  m_parentNode->insert( m_node );
151  }
152  }
153  else
154  {
155  std::ostringstream stream;
156  stream << "Invalid time for the EEG: " << m_time << "s";
157  throw WOutOfBounds( stream.str() );
158  }
159  }
160  else
161  {
162  std::ostringstream stream;
163  stream << "The EEG has no segment number " << segmentID;
164  throw WOutOfBounds( stream.str() );
165  }
166 }
167 
169  : m_time( -1.0 )
170 {
171 }
172 
174 {
175  if( m_parentNode.valid() && m_node.valid() )
176  {
177  m_parentNode->remove( m_node );
178  }
179 }
180 
181 double WEEGEvent::getTime() const
182 {
183  return m_time;
184 }
185 
186 const std::vector< double >& WEEGEvent::getValues() const
187 {
188  return m_values;
189 }
const std::vector< double > & getValues() const
Get the value of each channel at the time position.
Definition: WEEGEvent.cpp:186
WEEGEvent()
Constructor for an empty event.
Definition: WEEGEvent.cpp:168
osg::ref_ptr< WGEGroupNode > m_parentNode
parent node, where m_node is inserted and removed from
Definition: WEEGEvent.h:100
double getTime() const
Get the time position.
Definition: WEEGEvent.cpp:181
double m_time
time position in seconds
Definition: WEEGEvent.h:94
~WEEGEvent()
Destructor, removing m_node from m_parentNode.
Definition: WEEGEvent.cpp:173
std::vector< double > m_values
the value of each channel at the given time position
Definition: WEEGEvent.h:96
osg::ref_ptr< osg::Node > m_node
OSG node representing the event.
Definition: WEEGEvent.h:98
Indicates invalid element access of a container.
Definition: WOutOfBounds.h:37
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120