The following commit has been merged in the master branch:
commit d21bf89fe1a1baac595e7629aa72579376f4a5b6
Author: Andrei Zavada <[email protected]>
Date:   Mon Jul 22 01:56:20 2013 +0300

    support irregular time-series TSV data

diff --git a/ChangeLog b/ChangeLog
index e56dab1..7d125f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,7 +7,8 @@ v.0.9.1 (2013-xx-xx)
        * SF: Artifact Detection dialog will now not get confused after
          clicking outside it on other channels.
        * New tool agh-profile-gen, a standalone profile generator.
-       * ascii (tsv) format support.
+       * ascii (tsv) format support, including irregular, timestamped
+         time series data.
        * Score assistant now uses delta and theta ranges as defined by user.
 
 v.0.9.0.4 (2013-05-18)
diff --git a/src/libsigfile/tsv.cc b/src/libsigfile/tsv.cc
index 5fe877c..83f513e 100644
--- a/src/libsigfile/tsv.cc
+++ b/src/libsigfile/tsv.cc
@@ -258,34 +258,82 @@ int
 CTSVFile::
 _read_data()
 {
-       vector<vector<double>> c2 (channels.size());
-
        // _line0 contains the first row of data already (it is the
        // first line not beginning with a #)
+
+       vector<vector<double>> c2 (channels.size());
        size_t r, ll = 0;
-       do {
-               for ( r = 0; r < channels.size(); ++r ) {
-                       double x;
-                       if ( 1 != sscanf( _line0, "%lg%*[,\t]", &x) )
-                               goto outer_break;
-                       c2[r].push_back( x);
+
+       if ( metadata["series"] == "irregular" ) {
+               vector<unsigned long> offsets;
+               do {
+                       double ts;
+                       if ( 1 != sscanf( _line0, "%lg%*[,\t]", &ts) ) {
+                               fprintf( stderr, "Bad offset (at data line 
%zu)\n", ll);
+                               _status |= bad_offset;
+                               return -1;
+                       }
+                       if ( ll > 0 && ts * _samplerate <= offsets.back() ) {
+                               fprintf( stderr, "Offsets not increasing (at 
data line %zu)\n", ll);
+                               _status |= offsets_not_incteasing;
+                               return -1;
+                       }
+
+                       offsets.push_back( ts * _samplerate);
+
+                       for ( r = 0; r < channels.size(); ++r ) {
+                               double x;
+                               if ( 1 != sscanf( _line0, "%lg%*[,\t]", &x) )
+                                       goto outer_break1;
+                               c2[r].push_back( x);
+                       }
+                       ++ll;
+               } while ( getline( &_line0, &_line0_mallocked_bytes, _f) > 0 );
+       outer_break1:
+
+               if ( r != 0 && r != channels.size() ) {
+                       fprintf( stderr, "Number of data read (%zu) not a 
multiple of channel count (%zu)\n", r, channels.size());
+                       _status |= bad_channel_count;
+                       return -1;
                }
-               ++ll;
-       } while ( getline( &_line0, &_line0_mallocked_bytes, _f) > 0 );
 
-outer_break:
+             // interpolate and resample
+               for ( size_t h = 0; h < channels.size(); ++h ) {
+                       valarray<TFloat> interpolated =
+                               sigproc::interpolate<TFloat>(
+                                       offsets,
+                                       _samplerate,
+                                       c2[h],
+                                       1./_samplerate);
+                       channels[h].data.resize( interpolated.size());
+                       channels[h].data = interpolated;
+               }
 
-       if ( r != 0 && r != channels.size() ) {
-               fprintf( stderr, "Number of data read (%zu) not a multiple of 
channel count (%zu)\n", r, channels.size());
-               _status |= bad_channel_count;
-               return -1;
-       }
 
-       // vector -> valarray
-       for ( size_t h = 0; h < channels.size(); ++h ) {
-               channels[h].data.resize( ll);
-               for ( size_t i = 0; i < ll; ++i )
-                       channels[h].data[i] = c2[h][i];
+       } else {
+               do {
+                       for ( r = 0; r < channels.size(); ++r ) {
+                               double x;
+                               if ( 1 != sscanf( _line0, "%lg%*[,\t]", &x) )
+                                       goto outer_break2;
+                               c2[r].push_back( x);
+                       }
+                       ++ll;
+               } while ( getline( &_line0, &_line0_mallocked_bytes, _f) > 0 );
+       outer_break2:
+
+               if ( r != 0 && r != channels.size() ) {
+                       fprintf( stderr, "Number of data read (%zu) not a 
multiple of channel count (%zu)\n", r, channels.size());
+                       _status |= bad_channel_count;
+                       return -1;
+               }
+
+               // vector -> valarray
+               for ( size_t h = 0; h < channels.size(); ++h ) {
+                       channels[h].data.resize( ll);
+                       for ( size_t i = 0; i < ll; ++i )
+                               channels[h].data[i] = c2[h][i];
+               }
        }
 
 
@@ -377,6 +425,10 @@ explain_status( const int status)
        list<string> recv;
        if ( status & bad_channel_count )
                recv.emplace_back( "Number of channels declared in header 
different from number of columns of data");
+       if ( status & bad_offset )
+               recv.emplace_back( "Bad offset");
+       if ( status & offsets_not_incteasing )
+               recv.emplace_back( "Offsets in an irregular-series data not 
increasing");
        return CSource::explain_status(status) + (recv.empty() ? "" : 
(join(recv, "\n") + '\n'));
 }
 
diff --git a/src/libsigfile/tsv.hh b/src/libsigfile/tsv.hh
index c3fea05..56e6706 100644
--- a/src/libsigfile/tsv.hh
+++ b/src/libsigfile/tsv.hh
@@ -333,12 +333,16 @@ class CTSVFile
 
        enum TStatus : int_least32_t {
                bad_channel_count        = (1 << (COMMON_STATUS_BITS + 1)),
+               bad_offset               = (1 << (COMMON_STATUS_BITS + 2)),
+               offsets_not_incteasing   = (1 << (COMMON_STATUS_BITS + 3)),
                inoperable               = (bad_header
                                           | bad_numfld
                                           | bad_datetime
                                           | dup_channels
                                           | sysfail
-                                          | too_many_channels)
+                                          | too_many_channels
+                                          | bad_offset
+                                          | offsets_not_incteasing)
        };
        static string explain_status( int);
 

-- 
Sleep experiment manager

_______________________________________________
debian-med-commit mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit

Reply via email to