libGDF
Reader.cpp
00001 //
00002 // This file is part of libGDF.
00003 //
00004 // libGDF is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser General Public License as
00006 // published by the Free Software Foundation, either version 3 of
00007 // the License, or (at your option) any later version.
00008 //
00009 // libGDF is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with libGDF.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // Copyright 2010 Martin Billinger
00018 
00019 #include "GDF/Reader.h"
00020 #include "GDF/tools.h"
00021 #include <boost/numeric/conversion/cast.hpp>
00022 #include <boost/lexical_cast.hpp>
00023 //#include <iostream>
00024 
00025 namespace gdf
00026 {
00027     Reader::Reader( )
00028     {
00029         m_record_nocache = NULL;
00030         m_cache_enabled = true;
00031         m_events = NULL;
00032         m_filename = "";
00033     }
00034 
00035     //===================================================================================================
00036     //===================================================================================================
00037 
00038     Reader::~Reader( )
00039     {
00040         resetCache( );
00041         if( m_record_nocache ) delete m_record_nocache;
00042         if( m_events ) delete m_events;
00043     }
00044 
00045     //===================================================================================================
00046     //===================================================================================================
00047 
00048     void Reader::open( std::string filename )
00049     {
00050         assert( !m_file.is_open() );
00051         m_file.open( filename.c_str(), std::ios_base::in | std::ios::binary );
00052         if( m_file.fail() )
00053             throw exception::file_exists_not( filename );
00054 
00055         m_filename = filename;
00056         if( m_record_nocache ) delete m_record_nocache;
00057         m_record_nocache = NULL;
00058 
00059         if( m_events ) delete m_events;
00060         m_events = NULL;
00061 
00062         m_file >> m_header;
00063 
00064         // determine record length
00065         m_record_length = 0;
00066         for( size_t i=0; i<m_header.getMainHeader_readonly().get_num_signals(); i++ )
00067         {
00068             size_t samplesize = datatype_size( m_header.getSignalHeader_readonly( i ).get_datatype( ) );
00069             m_record_length += samplesize * m_header.getSignalHeader_readonly( i ).get_samples_per_record( );
00070 
00071             double fs = m_header.getSignalHeader( i ).get_samples_per_record( ) * m_header.getMainHeader_readonly().get_datarecord_duration(1) / m_header.getMainHeader_readonly().get_datarecord_duration(0);
00072             m_header.getSignalHeader( i ).set_samplerate( boost::numeric_cast<uint32>(fs) );
00073         }
00074 
00075         m_record_offset = m_header.getMainHeader_readonly().get_header_length( ) * 256;
00076         m_event_offset = boost::numeric_cast<size_t>( m_record_offset + m_header.getMainHeader_readonly().get_num_datarecords() * m_record_length );
00077 
00078         initCache( );
00079     }
00080 
00081     //===================================================================================================
00082     //===================================================================================================
00083 
00084     void Reader::close( )
00085     {
00086         m_file.close( );
00087     }
00088 
00089     //===================================================================================================
00090     //===================================================================================================
00091 
00092     void Reader::enableCache( bool b )
00093     {
00094         m_cache_enabled = b;
00095         resetCache( );
00096     }
00097 
00098     //===================================================================================================
00099     //===================================================================================================
00100 
00101     void Reader::initCache( )
00102     {
00103         resetCache( );
00104         m_record_cache.clear( );
00105         size_t num_records = boost::numeric_cast<size_t>( m_header.getMainHeader_readonly().get_num_datarecords() );
00106         m_record_cache.resize( num_records, NULL );
00107     }
00108 
00109     //===================================================================================================
00110     //===================================================================================================
00111 
00112     void Reader::resetCache( )
00113     {
00114         for( std::list<size_t>::iterator it = m_cache_entries.begin(); it != m_cache_entries.end(); it++ )
00115         {
00116             delete m_record_cache[*it];
00117             m_record_cache[*it] = NULL;
00118         }
00119         m_cache_entries.clear( );
00120 
00121         if( m_record_nocache ) delete m_record_nocache;
00122         m_record_nocache = new Record( &m_header );
00123     }
00124 
00125     //===================================================================================================
00126     //===================================================================================================
00127 
00128     size_t Reader::findRecord( uint16 channel_idx, size_t sample_idx )
00129     {
00130         return boost::numeric_cast<size_t>( floor( ((double)sample_idx) / ((double)m_header.getSignalHeader_readonly( channel_idx ).get_samples_per_record( )) ) );
00131     }
00132 
00133     //===================================================================================================
00134     //===================================================================================================
00135 
00136     void Reader::getSignals( std::vector< std::vector<double> > &buffer, double start_time, double end_time, std::vector<uint16> signal_indices )
00137     {
00138         using boost::numeric_cast;
00139 
00140         if( signal_indices.size() == 0 )
00141         {
00142             signal_indices.resize( m_header.getMainHeader_readonly().get_num_signals() );
00143             for( size_t i=0; i<m_header.getMainHeader_readonly().get_num_signals(); i++ )
00144                 signal_indices[i] = i;
00145         }
00146 
00147         buffer.resize( signal_indices.size() );
00148 
00149         double record_rate = m_header.getMainHeader_readonly().get_datarecord_duration(1) / m_header.getMainHeader_readonly().get_datarecord_duration(0);
00150         size_t record = boost::numeric_cast<size_t>( floor( start_time * record_rate ) );
00151 
00152 
00153         std::vector<size_t> start, samples_to_go, readpos, writepos;
00154 
00155         start.resize( signal_indices.size() );
00156         samples_to_go.resize( signal_indices.size() );
00157         readpos.resize( signal_indices.size() );
00158         writepos.resize( signal_indices.size() );
00159         for( size_t i=0; i<signal_indices.size(); i++ )
00160         {
00161             SignalHeader *sh = &m_header.getSignalHeader( signal_indices[i] );
00162             double fs = sh->get_samplerate( );
00163             start[i] = boost::numeric_cast<size_t>( floor( start_time * fs ) );
00164             samples_to_go[i] = boost::numeric_cast<size_t>( floor( end_time * fs ) );
00165             if( end_time < 0 )
00166                 samples_to_go[i] = boost::numeric_cast<size_t>( m_header.getMainHeader_readonly().get_num_datarecords() * sh->get_samples_per_record() );
00167             samples_to_go[i] = std::min( samples_to_go[i], boost::numeric_cast<size_t>( m_header.getMainHeader_readonly().get_num_datarecords() * sh->get_samples_per_record() ) );
00168             samples_to_go[i] -= start[i];
00169             buffer[i].resize( boost::numeric_cast<size_t>( samples_to_go[i] ) );
00170             readpos[i] = start[i] % sh->get_samples_per_record();
00171         }
00172 
00173         while( sum(samples_to_go) > 0 )
00174         {
00175             Record *r = getRecordPtr( record );
00176             for( size_t i=0; i<signal_indices.size(); i++ )
00177             {
00178                 SignalHeader *sh = &m_header.getSignalHeader( signal_indices[i] );
00179                 size_t n = std::min( boost::numeric_cast<size_t>(sh->get_samples_per_record( )) - readpos[i], samples_to_go[i] );
00180                 r->getChannel( signal_indices[i] )->deblitSamplesPhys( &buffer[i][writepos[i]], readpos[i], n );
00181                 samples_to_go[i] -= n;
00182                 writepos[i] += n;
00183                 readpos[i] = 0;
00184             }
00185             record++;
00186         }
00187     }
00188 
00189     //===================================================================================================
00190     //===================================================================================================
00191 
00192     void Reader::getSignal( uint16 channel_idx, double *buffer, size_t start, size_t end  )
00193     {
00194         using boost::numeric_cast;
00195 
00196         SignalHeader *sh = &m_header.getSignalHeader( channel_idx );
00197 
00198         if( end <= start )
00199             end = boost::numeric_cast<size_t>( sh->get_samples_per_record( ) * m_header.getMainHeader_readonly().get_num_datarecords( ) );
00200 
00201         size_t record = boost::numeric_cast<size_t>( floor( ((double)start)/((double)sh->get_samples_per_record()) ) );
00202         size_t readpos = start % sh->get_samples_per_record();
00203         size_t writepos = 0;
00204         size_t samples_to_go = end - start;
00205 
00206         while( samples_to_go > 0 )
00207         {
00208             Record *r = getRecordPtr( record );
00209 
00210             size_t n = std::min( (size_t)sh->get_samples_per_record( ) - readpos, samples_to_go );
00211             r->getChannel( channel_idx )->deblitSamplesPhys( &buffer[writepos], readpos, n );
00212             samples_to_go -= n;
00213             writepos += n;
00214             readpos = 0;
00215 
00216             record++;
00217         }
00218     }
00219 
00220     //===================================================================================================
00221     //===================================================================================================
00222 
00223     double Reader::getSample( uint16 channel_idx, size_t sample_idx )
00224     {
00225         Record *r = getRecordPtr( findRecord( channel_idx, sample_idx ) );
00226         size_t spr = m_header.getSignalHeader_readonly( channel_idx ).get_samples_per_record( );
00227         return r->getChannel( channel_idx )->getSamplePhys( sample_idx % spr );
00228     }
00229 
00230     //===================================================================================================
00231     //===================================================================================================
00232 
00233     Record *Reader::getRecordPtr( size_t index )
00234     {
00235         assert( index < boost::numeric_cast<size_t>(m_header.getMainHeader_readonly().get_num_datarecords()) );
00236         Record *r = m_record_cache[index];
00237         if( r == NULL )
00238         {
00239             size_t pos = m_record_offset + m_record_length*index;
00240             m_file.seekg( pos );
00241             if( m_cache_enabled )
00242             {
00243                 r = new Record( &m_header );
00244                 m_file >> *r;
00245                 m_record_cache[index] = r;
00246                 m_cache_entries.push_back( index );
00247             }
00248             else
00249             {
00250                 m_file >> *m_record_nocache;
00251                 r = m_record_nocache;
00252             }
00253         }
00254         return r;
00255     }
00256 
00257     //===================================================================================================
00258     //===================================================================================================
00259 
00260     void Reader::readRecord( size_t index, Record *rec )
00261     {
00262         assert( index < boost::numeric_cast<size_t>(m_header.getMainHeader_readonly().get_num_datarecords()) );
00263         Record *r = m_record_cache[index];
00264         if( r == NULL )
00265         {
00266             size_t pos = m_record_offset + m_record_length*index;
00267             m_file.seekg( pos );
00268             if( m_cache_enabled )
00269             {
00270                 r = new Record( &m_header );
00271                 m_file >> *r;
00272                 m_record_cache[index] = r;
00273                 m_cache_entries.push_back( index );
00274             }
00275             else
00276             {
00277                 m_file >> *rec; // read directly
00278                 return;
00279             }
00280         }
00281         *rec = *r;  // copy from cache
00282     }
00283 
00284     //===================================================================================================
00285     //===================================================================================================
00286 
00287     void Reader::precacheRecords( size_t start, size_t end )
00288     {
00289         for( size_t i=start; i<end; i++ )
00290             getRecordPtr( i );
00291     }
00292 
00293     //===================================================================================================
00294     //===================================================================================================
00295 
00296     EventHeader *Reader::getEventHeader( )
00297     {
00298         if( m_events == NULL )
00299         {
00300             if( m_file.is_open() )
00301             {
00302                 m_events = new EventHeader( );
00303                 m_file.seekg( m_event_offset );
00304                 readEvents( );
00305             }
00306             else
00307                 throw exception::file_not_open( "when attempting to read events" );
00308         }
00309         return m_events;
00310     }
00311 
00312     //===================================================================================================
00313     //===================================================================================================
00314 
00315     void Reader::readEvents( )
00316     {
00317         m_events->fromStream( m_file );
00318     }
00319 }
 All Data Structures Functions Variables Friends