libGDF
GDFHeaderAccess.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/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 }
 All Data Structures Functions Variables Friends