|
libGDF
|
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 }