|
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/GDFHeaderAccess.h" 00020 #include "GDF/tools.h" 00021 #include "GDF/Exceptions.h" 00022 #include <boost/lexical_cast.hpp> 00023 #include <boost/numeric/conversion/cast.hpp> 00024 #include <list> 00025 #include <string> 00026 //#include <iostream> 00027 00028 const double epsilon_d = 1e-15; 00029 const double epsilon_f = 1e-15; 00030 const double epsilon_i = 1; 00031 00032 00033 namespace gdf 00034 { 00035 GDFHeaderAccess::GDFHeaderAccess( ) 00036 { 00037 enableAutoRecordDuration( ); 00038 setLock( false ); 00039 } 00040 00041 //=================================================================================================== 00042 //=================================================================================================== 00043 00044 GDFHeaderAccess::~GDFHeaderAccess( ) 00045 { 00046 //std::cout << "~GDFHeaderAccess( )" << std::endl; 00047 } 00048 00049 //=================================================================================================== 00050 //=================================================================================================== 00051 00052 void GDFHeaderAccess::clear( ) 00053 { 00054 assert( !m_lock ); 00055 m_mainhdr.setDefaultValues( ); 00056 m_sighdr.clear( ); 00057 m_events.clear( ); 00058 enableAutoRecordDuration( ); 00059 } 00060 00061 //=================================================================================================== 00062 //=================================================================================================== 00063 00064 void GDFHeaderAccess::sanitize( ) 00065 { 00066 using boost::lexical_cast; 00067 00068 std::list< std::string > warnings, errors; 00069 00070 // ------------ Check number of signals ------------------ 00071 if( m_sighdr.size() == 0 ) 00072 warnings.push_back( "GDF will contain no signals." ); 00073 00074 m_mainhdr.set_num_signals( m_sighdr.size() ); 00075 00076 // ------------ Check signal indices ------------------ 00077 std::map<uint16,SignalHeader>::iterator it = m_sighdr.begin( ); 00078 std::string tmp; 00079 for( size_t i=0; it != m_sighdr.end(); it++, i++ ) 00080 while( it->first != i ) 00081 tmp = tmp + lexical_cast<std::string>(i++)+','; 00082 if( tmp.length() > 0 ) 00083 { 00084 tmp = tmp.substr(0,tmp.length()-1); 00085 errors.push_back( "Signal indices not contiguous (Missing signals number "+tmp+")." ); 00086 } 00087 00088 // ------------ Gather Sampling rates ------------------ 00089 std::vector<uint32> fs; 00090 for( it=m_sighdr.begin( ); it!=m_sighdr.end(); it++ ) 00091 { 00092 uint32 rate = it->second.get_samplerate( ); 00093 fs.push_back( rate ); 00094 } 00095 00096 uint32 ddur[2]; 00097 if( fs.size() == 0 ) 00098 { 00099 // ------------ No Signals: set record duration to 0 ------------------ 00100 ddur[0] = 0; 00101 ddur[1] = 1; 00102 } 00103 else if( drd_den == 0 ) 00104 { 00105 // ------------ Automatically Set datarecord duration ------------------ 00106 ddur[0] = 1; 00107 ddur[1] =gcd( fs ); 00108 00109 if( ddur[1] == 0 ) // invalid sampling rates, set record duration to 0 00110 { 00111 ddur[0] = 0; 00112 ddur[1] = 1; 00113 } 00114 } 00115 else 00116 { 00117 // ------------ Manually Set datarecord duration ------------------ 00118 if( (gcd(fs) * drd_num) % drd_den != 0 ) 00119 errors.push_back( "(Manually set) record duration does not fit sample rates." ); 00120 ddur[0] = drd_num; 00121 ddur[1] = drd_den; 00122 } 00123 m_mainhdr.set_datarecord_duration( ddur, 2 ); 00124 00125 // ------------ Signal specific information ------------------ 00126 for( it=m_sighdr.begin( ); it!=m_sighdr.end(); it++ ) 00127 { 00128 // ------------ Check data type ------------------ 00129 if( it->second.get_datatype() == INVALID_TYPE ) 00130 errors.push_back( "Signal "+lexical_cast<std::string>(it->first)+" has no valid data type." ); 00131 00132 // ------------ Check sampling rate ------------------ 00133 it->second.set_samples_per_record( it->second.get_samplerate() * ddur[0] / ddur[1] ); 00134 if( it->second.get_samples_per_record() == 0 ) 00135 errors.push_back( "Signal "+lexical_cast<std::string>(it->first)+" has sample rate set to 0 or not set at all." ); 00136 00137 // ------------ Check ranges ------------------ 00138 if( it->second.get_digmin() > it->second.get_digmax() ) 00139 errors.push_back( "Signal "+lexical_cast<std::string>(it->first)+" has digmin > digmax." ); 00140 00141 if( it->second.get_digmin() == it->second.get_digmax() ) 00142 errors.push_back( "Signal "+lexical_cast<std::string>(it->first)+" has digmin = digmax." ); 00143 00144 if( it->second.get_physmin() == it->second.get_physmax() ) 00145 errors.push_back( "Signal "+lexical_cast<std::string>(it->first)+" has physmin = physmax." ); 00146 } 00147 00148 m_mainhdr.set_header_length( 1 + m_sighdr.size() + m_taghdr.getLength() ); 00149 00150 00151 if( m_events.getMode() != 1 && m_events.getMode() != 3 ) 00152 errors.push_back( "Event Mode "+lexical_cast<std::string>(m_events.getMode())+" is not valid."); 00153 00154 if( m_events.getSamplingRate() < 0 ) 00155 { 00156 if( fs.size() > 0) 00157 m_events.setSamplingRate( boost::numeric_cast<float32>( max(fs) ) ); 00158 else 00159 errors.push_back( "Could not determine event sampling rate." ); 00160 } 00161 00162 if( warnings.size() > 0 || errors.size() > 0 ) 00163 throw exception::header_issues( warnings, errors ); 00164 } 00165 00166 //=================================================================================================== 00167 //=================================================================================================== 00168 00169 void GDFHeaderAccess::setRecordDuration( uint32 num, uint32 den ) 00170 { 00171 uint32 ddur[2]; 00172 drd_num = num; 00173 drd_den = den; 00174 ddur[0] = num; 00175 ddur[1] = den; 00176 m_mainhdr.set_datarecord_duration( ddur, 2 ); 00177 } 00178 00179 //=================================================================================================== 00180 //=================================================================================================== 00181 00182 void GDFHeaderAccess::enableAutoRecordDuration( ) 00183 { 00184 drd_num = 0; 00185 drd_den = 0; 00186 } 00187 00188 //=================================================================================================== 00189 //=================================================================================================== 00190 00191 const MainHeader &GDFHeaderAccess::getMainHeader_readonly( ) const 00192 { 00193 return m_mainhdr; 00194 } 00195 00196 //=================================================================================================== 00197 //=================================================================================================== 00198 00199 MainHeader &GDFHeaderAccess::getMainHeader( ) 00200 { 00201 assert( !m_lock ); 00202 return m_mainhdr; 00203 } 00204 00205 //=================================================================================================== 00206 //=================================================================================================== 00207 00208 const SignalHeader &GDFHeaderAccess::getSignalHeader_readonly( size_t idx ) const 00209 { 00210 std::map<uint16,SignalHeader>::const_iterator it = m_sighdr.find( idx ); 00211 if( it == m_sighdr.end() ) 00212 throw exception::signal_exists_not( boost::lexical_cast<std::string>( idx ) ); 00213 return it->second; 00214 } 00215 00216 //=================================================================================================== 00217 //=================================================================================================== 00218 00219 SignalHeader &GDFHeaderAccess::getSignalHeader( size_t idx ) 00220 { 00221 //throw exception::signal_exists_not( boost::lexical_cast<std::string>( idx ) ); 00222 assert( !m_lock ); 00223 std::map<uint16,SignalHeader>::iterator it = m_sighdr.find( idx ); 00224 if( it == m_sighdr.end() ) 00225 //return m_sighdr.begin()->second; 00226 throw exception::signal_exists_not( boost::lexical_cast<std::string>( idx ) ); 00227 return it->second; 00228 } 00229 00230 //=================================================================================================== 00231 //=================================================================================================== 00232 00233 bool GDFHeaderAccess::createSignal( size_t index, bool throwexc ) 00234 { 00235 assert( !m_lock ); 00236 std::map<uint16,SignalHeader>::iterator it = m_sighdr.find( index ); 00237 if( it != m_sighdr.end() ) 00238 { 00239 if( throwexc ) 00240 throw exception::signal_exists( boost::lexical_cast<std::string>( index ) ); 00241 else 00242 return false; 00243 } 00244 m_sighdr[index]; 00245 return true; 00246 } 00247 00248 //=================================================================================================== 00249 //=================================================================================================== 00250 00251 size_t GDFHeaderAccess::getFirstFreeSignalIndex( ) 00252 { 00253 size_t index = 0; 00254 std::map<uint16,SignalHeader>::const_iterator it = m_sighdr.begin( ); 00255 for( ; it!=m_sighdr.end(); it++ ) 00256 { 00257 if( it->first != index ) 00258 return index; 00259 index++; 00260 } 00261 return index; 00262 } 00263 00264 //=================================================================================================== 00265 //=================================================================================================== 00266 00267 size_t GDFHeaderAccess::getNumSignals( ) const 00268 { 00269 return m_sighdr.size( ); 00270 } 00271 00272 //=================================================================================================== 00273 //=================================================================================================== 00274 00275 void GDFHeaderAccess::swapSignals( size_t a, size_t b ) 00276 { 00277 assert( !m_lock ); 00278 std::map<uint16,SignalHeader>::iterator ita = m_sighdr.find( a ); 00279 std::map<uint16,SignalHeader>::iterator itb = m_sighdr.find( b ); 00280 00281 if( ita == m_sighdr.end() ) 00282 throw exception::signal_exists_not( boost::lexical_cast<std::string>( a ) ); 00283 if( itb == m_sighdr.end() ) 00284 throw exception::signal_exists_not( boost::lexical_cast<std::string>( b ) ); 00285 00286 std::swap( ita->second, itb->second ); 00287 } 00288 00289 //=================================================================================================== 00290 //=================================================================================================== 00291 00292 void GDFHeaderAccess::relocateSignal( size_t src, size_t dst ) 00293 { 00294 assert( !m_lock ); 00295 std::map<uint16,SignalHeader>::iterator ita = m_sighdr.find( src ); 00296 std::map<uint16,SignalHeader>::iterator itb = m_sighdr.find( dst ); 00297 00298 if( ita == m_sighdr.end() ) 00299 throw exception::signal_exists_not( boost::lexical_cast<std::string>( src ) ); 00300 if( itb != m_sighdr.end() ) 00301 throw exception::signal_exists( boost::lexical_cast<std::string>( dst ) ); 00302 00303 m_sighdr[dst] = ita->second; 00304 m_sighdr.erase( ita ); 00305 } 00306 00307 //=================================================================================================== 00308 //=================================================================================================== 00309 00310 EventHeader &GDFHeaderAccess::getEventHeader( ) 00311 { 00312 return m_events; 00313 } 00314 00315 //=================================================================================================== 00316 //=================================================================================================== 00317 00318 std::ostream& operator<< (std::ostream& out, const GDFHeaderAccess& hdr) 00319 { 00320 const MainHeader *mh = &hdr.m_mainhdr; 00321 mh->version_id.tostream( out ); 00322 mh->patient_id.tostream( out ); 00323 mh->reserved_1.tostream( out ); 00324 mh->patient_drugs.tostream( out ); 00325 mh->patient_weight.tostream( out ); 00326 mh->patient_height.tostream( out ); 00327 mh->patient_flags.tostream( out ); 00328 mh->recording_id.tostream( out ); 00329 mh->recording_location.tostream( out ); 00330 mh->recording_start.tostream( out ); 00331 mh->patient_birthday.tostream( out ); 00332 mh->header_length.tostream( out ); 00333 mh->patient_ICD.tostream( out ); 00334 mh->equipment_provider_classification.tostream( out ); 00335 mh->reserved_2.tostream( out ); 00336 mh->patient_headsize.tostream( out ); 00337 mh->pos_reference.tostream( out ); 00338 mh->pos_ground.tostream( out ); 00339 mh->num_datarecords.tostream( out ); 00340 mh->datarecord_duration.tostream( out ); 00341 mh->num_signals.tostream( out ); 00342 mh->reserved_3.tostream( out ); 00343 00344 assert( out.tellp() == std::streampos(256) ); 00345 00346 size_t ns = mh->get_num_signals( ); 00347 00348 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).label.tostream( out ); 00349 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).transducer_type.tostream( out ); 00350 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).physical_dimension.tostream( out ); 00351 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).physical_dimension_code.tostream( out ); 00352 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).physmin.tostream( out ); 00353 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).physmax.tostream( out ); 00354 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).digmin.tostream( out ); 00355 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).digmax.tostream( out ); 00356 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).reserved_1.tostream( out ); 00357 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).lowpass.tostream( out ); 00358 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).highpass.tostream( out ); 00359 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).notch.tostream( out ); 00360 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).samples_per_record.tostream( out ); 00361 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).datatype.tostream( out ); 00362 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).sensor_pos.tostream( out ); 00363 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).sensor_info.tostream( out ); 00364 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader_readonly(i).reserved_2.tostream( out ); 00365 00366 assert( out.tellp() == std::streampos(256+256*ns) ); 00367 00368 //throw exception::feature_not_implemented( ); 00369 00370 return out; 00371 } 00372 00373 //=================================================================================================== 00374 //=================================================================================================== 00375 00376 std::istream& operator>> (std::istream& in, GDFHeaderAccess& hdr) 00377 { 00378 hdr.clear( ); 00379 00380 MainHeader *mh = &hdr.m_mainhdr; 00381 mh->version_id.fromstream( in ); 00382 if (mh->get_version_id() != "GDF 2.10") 00383 throw exception::incompatible_gdf_version (mh->get_version_id ()); 00384 mh->patient_id.fromstream( in ); 00385 mh->reserved_1.fromstream( in ); 00386 mh->patient_drugs.fromstream( in ); 00387 mh->patient_weight.fromstream( in ); 00388 mh->patient_height.fromstream( in ); 00389 mh->patient_flags.fromstream( in ); 00390 mh->recording_id.fromstream( in ); 00391 mh->recording_location.fromstream( in ); 00392 mh->recording_start.fromstream( in ); 00393 mh->patient_birthday.fromstream( in ); 00394 mh->header_length.fromstream( in ); 00395 mh->patient_ICD.fromstream( in ); 00396 mh->equipment_provider_classification.fromstream( in ); 00397 mh->reserved_2.fromstream( in ); 00398 mh->patient_headsize.fromstream( in ); 00399 mh->pos_reference.fromstream( in ); 00400 mh->pos_ground.fromstream( in ); 00401 mh->num_datarecords.fromstream( in ); 00402 mh->datarecord_duration.fromstream( in ); 00403 mh->num_signals.fromstream( in ); 00404 mh->reserved_3.fromstream( in ); 00405 00406 assert( in.tellg() == std::streampos(256) ); 00407 00408 size_t ns = mh->get_num_signals( ); 00409 00410 for( uint16 i=0; i<ns; i++ ) 00411 hdr.createSignal( i ); 00412 00413 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).label.fromstream( in ); 00414 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).transducer_type.fromstream( in ); 00415 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).physical_dimension.fromstream( in ); 00416 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).physical_dimension_code.fromstream( in ); 00417 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).physmin.fromstream( in ); 00418 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).physmax.fromstream( in ); 00419 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).digmin.fromstream( in ); 00420 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).digmax.fromstream( in ); 00421 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).reserved_1.fromstream( in ); 00422 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).lowpass.fromstream( in ); 00423 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).highpass.fromstream( in ); 00424 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).notch.fromstream( in ); 00425 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).samples_per_record.fromstream( in ); 00426 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).datatype.fromstream( in ); 00427 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).sensor_pos.fromstream( in ); 00428 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).sensor_info.fromstream( in ); 00429 for( uint16 i=0; i<ns; i++ ) hdr.getSignalHeader(i).reserved_2.fromstream( in ); 00430 00431 assert( in.tellg() == std::streampos(256+256*ns) ); 00432 00433 return in; 00434 } 00435 00436 //=================================================================================================== 00437 //=================================================================================================== 00438 00439 size_t GDFHeaderAccess::getNumberOfSamplesInSignal( size_t signal_index ) const 00440 { 00441 std::map<uint16,SignalHeader>::const_iterator it = m_sighdr.find( signal_index ); 00442 if( it == m_sighdr.end() ) 00443 return 0; 00444 00445 return boost::numeric_cast<size_t>(m_mainhdr.get_num_datarecords()) * boost::numeric_cast<size_t>(it->second.get_samples_per_record()); 00446 } 00447 }