[med-svn] [SCM] aghermann branch, master, updated. 4b06a66467a52311d413e817136ece62c0e9c24a
Andrei Zavada
johnhommer at gmail.com
Sun Jul 21 19:56:37 UTC 2013
The following commit has been merged in the master branch:
commit 6cf9ce525ce7ac2e433c1873e3a0a9fe36878760
Author: Andrei Zavada <johnhommer at gmail.com>
Date: Sat Jul 20 23:16:46 2013 +0300
next round of refactoring in libsigfile, around recording_time
diff --git a/src/aghermann/expdesign/recording.hh b/src/aghermann/expdesign/recording.hh
index 07cfedb..8b9ffe7 100644
--- a/src/aghermann/expdesign/recording.hh
+++ b/src/aghermann/expdesign/recording.hh
@@ -15,7 +15,7 @@
#include <cstdarg>
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "libmetrics/all.hh"
#include "aghermann/model/forward-decls.hh"
#include "forward-decls.hh"
diff --git a/src/aghermann/rk1968/rk1968.cc b/src/aghermann/rk1968/rk1968.cc
index 29b2e29..a5a80f7 100644
--- a/src/aghermann/rk1968/rk1968.cc
+++ b/src/aghermann/rk1968/rk1968.cc
@@ -13,7 +13,7 @@
#include <forward_list>
#include "libsigfile/page.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "aghermann/expdesign/recording.hh"
#include "aghermann/expdesign/primaries.hh"
#include "libmetrics/bands.hh"
diff --git a/src/common/subject_id.cc b/src/common/subject_id.cc
index cacede8..cfd32cf 100644
--- a/src/common/subject_id.cc
+++ b/src/common/subject_id.cc
@@ -182,30 +182,6 @@ update_from( const SSubjectId& j)
}
-int
-SSubjectId::
-parse_recording_id_edf_style( const string& s)
-{
- using namespace agh::str;
- int_least32_t status = 0;
- auto subfields = tokens( s, " ");
- if ( subfields.size() < 4 ) {
- id = subfields.front();
- status |= sigfile::CSource::nonconforming_patient_id;
- } else {
- if ( subfields.size() > 4 )
- status |= sigfile::CSource::extra_patientid_subfields;
- auto i = subfields.begin();
- id = *i++;
- gender = agh::SSubjectId::char_to_gender((*i++)[0]);
- dob = agh::SSubjectId::str_to_dob(*i++);
- name = join( tokens(*i++, "_"), " ");
- if ( not valid() )
- status |= sigfile::CSource::invalid_subject_details;
- }
- return status;
-}
-
// Local Variables:
// Mode: c++
diff --git a/src/libmetrics/mc.cc b/src/libmetrics/mc.cc
index 82b3fed..70fa09d 100644
--- a/src/libmetrics/mc.cc
+++ b/src/libmetrics/mc.cc
@@ -11,7 +11,7 @@
*/
#include "common/lang.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "mc.hh"
#if HAVE_CONFIG_H && !defined(VERSION)
diff --git a/src/libmetrics/page-metrics-base.cc b/src/libmetrics/page-metrics-base.cc
index 6de2003..2f261e9 100644
--- a/src/libmetrics/page-metrics-base.cc
+++ b/src/libmetrics/page-metrics-base.cc
@@ -19,7 +19,7 @@
#include <numeric>
#include <valarray>
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "page-metrics-base.hh"
#if HAVE_CONFIG_H && !defined(VERSION)
diff --git a/src/libmetrics/page-metrics-base.hh b/src/libmetrics/page-metrics-base.hh
index 219ce0a..2e4d1ae 100644
--- a/src/libmetrics/page-metrics-base.hh
+++ b/src/libmetrics/page-metrics-base.hh
@@ -18,7 +18,7 @@
#include "common/lang.hh"
#include "common/alg.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "forward-decls.hh"
#if HAVE_CONFIG_H && !defined(VERSION)
diff --git a/src/libmetrics/psd.cc b/src/libmetrics/psd.cc
index ed45f6f..7eddf6c 100644
--- a/src/libmetrics/psd.cc
+++ b/src/libmetrics/psd.cc
@@ -26,7 +26,7 @@
#include "common/lang.hh"
#include "common/fs.hh"
#include "libsigproc/sigproc.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "psd.hh"
using namespace std;
diff --git a/src/libmetrics/swu.cc b/src/libmetrics/swu.cc
index a5d7969..e1c123c 100644
--- a/src/libmetrics/swu.cc
+++ b/src/libmetrics/swu.cc
@@ -17,7 +17,7 @@
#include "common/lang.hh"
#include "common/fs.hh"
#include "libsigproc/sigproc.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "swu.hh"
using namespace std;
diff --git a/src/libsigfile/Makefile.am b/src/libsigfile/Makefile.am
index b861ba6..4dbc020 100644
--- a/src/libsigfile/Makefile.am
+++ b/src/libsigfile/Makefile.am
@@ -11,8 +11,8 @@ libsigfile_la_SOURCES := \
channel.hh \
source-base.cc \
source-base.hh \
- source.cc \
- source.hh \
+ typed-source.cc \
+ typed-source.hh \
edf.cc \
edf-io.cc \
edf.hh \
@@ -42,7 +42,7 @@ BUILT_SOURCES := \
forward-decls.hh.gch \
channel.hh.gch \
source-base.hh.gch \
- source.hh.gch \
+ typed-source.hh.gch \
edf.hh.gch \
tsv.hh.gch \
page.hh.gch
diff --git a/src/libsigfile/edf.cc b/src/libsigfile/edf.cc
index 4890dd4..579b1c3 100644
--- a/src/libsigfile/edf.cc
+++ b/src/libsigfile/edf.cc
@@ -23,7 +23,7 @@
#include "common/lang.hh"
#include "common/string.hh"
#include "edf.hh"
-#include "source.hh"
+#include "typed-source.hh"
using namespace std;
@@ -85,15 +85,16 @@ set_reserved( const string& s)
int
CEDFFile::
-set_start_time( time_t s)
+set_recording_date( const string& s)
{
- char b[9];
- // set start
- strftime( b, 9, "%d.%m.%y", localtime(&s));
- memcpy( header.recording_date, b, 8);
- strftime( b, 9, "%H.%M.%s", localtime(&s));
- memcpy( header.recording_time, b, 8);
-
+ memcpy( header.recording_date, s.c_str(), 8);
+ return 0;
+}
+int
+CEDFFile::
+set_recording_time( const string& s)
+{
+ memcpy( header.recording_time, s.c_str(), 8);
return 0;
}
@@ -341,8 +342,6 @@ CEDFFile (CEDFFile&& rv)
data_record_size = rv.data_record_size;
_subtype = rv._subtype;
- _start_time = rv._start_time;
- _end_time = rv._end_time;
swap( _patient_id, rv._patient_id);
swap( _recording_id, rv._recording_id);
@@ -482,7 +481,7 @@ _parse_header()
if ( !header_length || !n_data_records || !data_record_size || !n_channels ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
}
if ( n_channels == 0 ) {
@@ -499,50 +498,25 @@ _parse_header()
_status |=
_subject.parse_recording_id_edf_style( _patient_id);
- // deal with episode and session
- {
- int parsed_status;
- tie (_session, _episode, parsed_status) =
- figure_session_and_episode();
- _status |= parsed_status;
- }
-
- // parse times
- {
- struct tm ts;
- char *p;
- //memset( &ts, 0, sizeof(struct tm));
- ts.tm_isdst = 0; // importantly
- string tmp (header.recording_date, 8);
- p = strptime( tmp.c_str(), "%d.%m.%y", &ts);
- if ( p == NULL || *p != '\0' ) {
- _status |= date_unparsable;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
- return -2;
- }
- tmp = {string (header.recording_time, 8)};
- p = strptime( tmp.c_str(), "%H.%M.%S", &ts);
- if ( p == NULL || *p != '\0' ) {
- _status |= time_unparsable;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
- return -2;
- }
+ // times
+ figure_times(
+ string (header.recording_date, 8),
+ string (header.recording_time, 8),
+ TAcceptTimeFormat::edf_strict);
+ if ( _status & bad_datetime && !(_flags & CSource::TFlags::no_field_consistency_check) )
+ return -2;
+ _end_time = _start_time + (time_t)recording_time();
- // if ( ts.tm_year < 50 )
- // ts.tm_year += 100;
- _start_time = mktime( &ts);
- if ( _start_time == (time_t)-1 )
- _status |= (date_unparsable|time_unparsable);
- else
- _end_time = _start_time + n_data_records * data_record_size;
- }
+ // deal with episode and session
+ tie (_session, _episode) =
+ figure_session_and_episode();
// assign "reserved"
_reserved = trim( string (header.reserved, 44));
if ( n_channels > max_channels ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
} else {
channels.resize( n_channels);
@@ -561,7 +535,7 @@ _parse_header()
string suggested_type = tt.front();
H.ucd = {(tt.pop_front(), agh::str::join( tt, " "))};
if ( suggested_type != H.ucd.type_s() )
- _status |= recognised_channel_conflicting_type;
+ _status |= conflicting_channel_type;
} else {
H.ucd = sigfile::SChannel (isolated_label);
@@ -588,7 +562,7 @@ _parse_header()
if ( sscanf( H.header.physical_min, "%8lg",
&H.physical_min) != 1 ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
}
}
@@ -599,7 +573,7 @@ _parse_header()
if ( sscanf( H.header.physical_max, "%8lg",
&H.physical_max) != 1 ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
}
}
@@ -611,7 +585,7 @@ _parse_header()
if ( sscanf( H.header.digital_min, "%8d",
&H.digital_min) != 1 ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
}
}
@@ -622,7 +596,7 @@ _parse_header()
if ( sscanf( H.header.digital_max, "%8d",
&H.digital_max) != 1 ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
}
}
@@ -638,7 +612,7 @@ _parse_header()
strtoul( t.c_str(), &tail, 10);
if ( tail == NULL || *tail != '\0' ) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -2;
}
}
@@ -651,7 +625,7 @@ _parse_header()
return -1;
} catch (invalid_argument ex) {
_status |= bad_numfld;
- if ( not (flags() & sigfile::CSource::no_field_consistency_check) )
+ if ( not (_flags & sigfile::CSource::no_field_consistency_check) )
return -3;
}
@@ -868,48 +842,48 @@ CEDFFile::
explain_status( const int status)
{
list<string> recv;
- if ( status & sysfail )
- recv.emplace_back( "* stat or fopen error");
- if ( status & bad_header )
- recv.emplace_back( "* Ill-formed header");
if ( status & bad_version )
- recv.emplace_back( "* Bad Version signature (i.e., not an EDF file)");
- if ( status & missing_patient_id )
- recv.emplace_back( "* Missing PatientId");
- if ( status & bad_numfld )
- recv.emplace_back( "* Garbage in numerical fields");
- if ( status & date_unparsable )
- recv.emplace_back( "* Date field ill-formed");
- if ( status & time_unparsable )
- recv.emplace_back( "* Time field ill-formed");
- if ( status & (nosession|noepisode) )
- recv.emplace_back( "* No session/episode information in RecordingID");
- if ( status & non1020_channel )
- recv.emplace_back( "* Channel designation not following the 10-20 system");
+ recv.emplace_back( "Bad Version signature (i.e., not an EDF file)");
if ( status & nonconforming_patient_id )
- recv.emplace_back( "* PatientId not conforming to section 2.1.3.3 of EDF spec");
- if ( status & invalid_subject_details )
- recv.emplace_back( "* PatientId has incomplete or ill-formed subject details");
- if ( status & nonkemp_signaltype )
- recv.emplace_back( "* Signal type not listed in Kemp et al");
- if ( status & dup_channels )
- recv.emplace_back( "* Duplicate channel names");
- if ( status & nogain )
- recv.emplace_back( "* Physical or Digital Min value greater than Max");
- if ( status & too_many_channels )
- recv.emplace_back( string("* Number of channels grearter than ") + to_string(max_channels));
+ recv.emplace_back( "PatientId not conforming to section 2.1.3.3 of EDF spec");
if ( status & file_truncated )
- recv.emplace_back( "* File truncated");
+ recv.emplace_back( "File truncated");
if ( status & trailing_junk )
- recv.emplace_back( "* File has trailing junk");
+ recv.emplace_back( "File has trailing junk");
if ( status & extra_patientid_subfields )
- recv.emplace_back( "* Extra subfields in PatientId");
- if ( status & recognised_channel_conflicting_type )
- recv.emplace_back( "* Explicitly specified signal type does not match type of known channel name");
+ recv.emplace_back( "Extra subfields in PatientId");
if ( status & mmap_error )
- recv.emplace_back( "* mmap error");
+ recv.emplace_back( "mmap error");
+
+ return CSource::explain_status(status) + (recv.empty() ? "" : (join(recv, "\n") + '\n'));
+}
+
+
- return join(recv, "\n");
+
+
+int
+agh::SSubjectId::
+parse_recording_id_edf_style( const string& s)
+{
+ using namespace agh::str;
+ int_least32_t status = 0;
+ auto subfields = tokens( s, " ");
+ if ( subfields.size() < 4 ) {
+ id = subfields.front();
+ status |= sigfile::CEDFFile::nonconforming_patient_id;
+ } else {
+ if ( subfields.size() > 4 )
+ status |= sigfile::CEDFFile::extra_patientid_subfields;
+ auto i = subfields.begin();
+ id = *i++;
+ gender = agh::SSubjectId::char_to_gender((*i++)[0]);
+ dob = agh::SSubjectId::str_to_dob(*i++);
+ name = join( tokens(*i++, "_"), " ");
+ if ( not valid() )
+ status |= sigfile::CSource::invalid_subject_details;
+ }
+ return status;
}
diff --git a/src/libsigfile/edf.hh b/src/libsigfile/edf.hh
index cbf1d9c..8d661ba 100644
--- a/src/libsigfile/edf.hh
+++ b/src/libsigfile/edf.hh
@@ -36,7 +36,6 @@ using namespace std;
namespace sigfile {
-
class CEDFFile
: public CSource {
@@ -91,7 +90,8 @@ class CEDFFile
// interface
// status
string explain_status() const
- { return explain_status( _status); }
+ { return move(explain_status( _status)); }
+ static string explain_status( int);
// identification
const char* patient_id() const
@@ -106,10 +106,6 @@ class CEDFFile
{ return _reserved.c_str(); }
// times
- time_t start_time() const
- { return _start_time; }
- time_t end_time() const
- { return _end_time; }
double recording_time() const // in seconds
{ return n_data_records * data_record_size; }
@@ -122,7 +118,9 @@ class CEDFFile
{ return 1; }
int set_reserved( const string&); // but you can clobber "reserved" field if you must
- int set_start_time( time_t);
+ int set_recording_date( const string&);
+ int set_recording_time( const string&);
+
// channels
size_t n_channels() const
{ return channels.size(); }
@@ -363,12 +361,13 @@ class CEDFFile
trailing_junk = (1 << (COMMON_STATUS_BITS + 3)),
mmap_error = (1 << (COMMON_STATUS_BITS + 4)),
nogain = (1 << (COMMON_STATUS_BITS + 5)),
- recognised_channel_conflicting_type = (1 << (COMMON_STATUS_BITS + 6)),
+ nonconforming_patient_id = (1 << (COMMON_STATUS_BITS + 6)),
+ extra_patientid_subfields = (1 << (COMMON_STATUS_BITS + 7)),
inoperable = (bad_header
| bad_version
| bad_numfld
- | date_unparsable | time_unparsable
+ | bad_datetime
| dup_channels
| nogain
| sysfail
@@ -376,14 +375,10 @@ class CEDFFile
| file_truncated
| mmap_error)
};
- static string explain_status( int);
private:
TSubtype _subtype;
- time_t _start_time,
- _end_time;
-
string _patient_id, // this is trimmed, raw; parsed into SSubjectId fields
_recording_id,
// take care of file being named 'episode-1.edf'
diff --git a/src/libsigfile/source-base.cc b/src/libsigfile/source-base.cc
index 4b36926..e9a7340 100644
--- a/src/libsigfile/source-base.cc
+++ b/src/libsigfile/source-base.cc
@@ -269,22 +269,40 @@ CSource (CSource&& rv)
: _subject (move(rv._subject))
{
swap( _filename, rv._filename);
- _status = rv._status;
- _flags = rv._flags;
+ _status = rv._status;
+ _flags = rv._flags;
+
+ _start_time = rv._start_time;
+ _end_time = rv._end_time;
}
+int
+CSource::
+set_start_time( time_t s)
+{
+ _end_time = (_start_time = s)
+ + (time_t)recording_time();
+
+ char b[9];
+ strftime( b, 9, "%d.%m.%y", localtime(&s));
+ set_recording_date( b);
+ strftime( b, 9, "%H.%M.%s", localtime(&s));
+ set_recording_time( b);
+ return 0;
+}
-tuple<string, string, int>
+
+
+tuple<string, string>
CSource::
figure_session_and_episode()
{
- int status = 0;
string session, episode;
// (a) parsed from RecordingID_raw
@@ -297,7 +315,7 @@ figure_session_and_episode()
sscanf( rec_id_isolated.c_str(), T " (" T ")", int_session, int_episode) == 2 )
;
else
- status = (nosession|noepisode);
+ _status |= bad_session_or_episode;
#undef T
// (b) identified from file name
@@ -315,7 +333,7 @@ figure_session_and_episode()
fn_episode.erase( sz-2, 2);
}
- if ( status ) { // (a) failed
+ if ( _status & bad_session_or_episode ) { // (a) failed
episode.assign( fn_episode); // use RecordingID_raw as Session
session.assign( rec_id_isolated);
} else {
@@ -323,12 +341,35 @@ figure_session_and_episode()
session.assign( int_session);
}
- return make_tuple( session, episode, status);
+ return make_tuple( session, episode);
}
+void
+CSource::
+figure_times( const string& date_s, const string& time_s, TAcceptTimeFormat option)
+{
+ struct tm ts;
+ char *p;
+ //memset( &ts, 0, sizeof(struct tm));
+ ts.tm_isdst = 0; // importantly
+ p = strptime( date_s.c_str(), "%d.%m.%y", &ts);
+ if ( p == NULL || *p != '\0' ) {
+ _status |= bad_datetime;
+ }
+ p = strptime( time_s.c_str(), "%H.%M.%S", &ts);
+ if ( p == NULL || *p != '\0' ) {
+ _status |= bad_datetime;
+ }
+
+ // if ( ts.tm_year < 50 )
+ // ts.tm_year += 100;
+ _start_time = mktime( &ts);
+ if ( _start_time == (time_t)-1 )
+ _status |= bad_datetime;
+}
@@ -463,6 +504,41 @@ export_filtered( const int h,
}
+
+string
+CSource::
+explain_status( const int status)
+{
+ list<string> recv;
+ if ( status & sysfail )
+ recv.emplace_back( "stat or fopen error");
+ if ( status & bad_header )
+ recv.emplace_back( "Ill-formed header");
+ if ( status & missing_patient_id )
+ recv.emplace_back( "Missing PatientId");
+ if ( status & bad_numfld )
+ recv.emplace_back( "Garbage in numerical fields");
+ if ( status & bad_datetime )
+ recv.emplace_back( "Date/time field ill-formed");
+ if ( status & bad_session_or_episode )
+ recv.emplace_back( "No session/episode information in RecordingID");
+ if ( status & non1020_channel )
+ recv.emplace_back( "Channel designation not following the 10-20 system");
+ if ( status & invalid_subject_details )
+ recv.emplace_back( "PatientId has incomplete or ill-formed subject details");
+ if ( status & nonkemp_signaltype )
+ recv.emplace_back( "Signal type not listed in Kemp et al");
+ if ( status & dup_channels )
+ recv.emplace_back( "Duplicate channel names");
+ if ( status & too_many_channels )
+ recv.emplace_back( string("Number of channels grearter than ") + to_string(max_channels));
+ if ( status & conflicting_channel_type )
+ recv.emplace_back( "Explicitly specified signal type does not match type of known channel name");
+
+ return recv.empty() ? "" : agh::str::join(recv, "\n") + "\n";
+}
+
+
// Local Variables:
// Mode: c++
// indent-tabs-mode: 8
diff --git a/src/libsigfile/source-base.hh b/src/libsigfile/source-base.hh
index bea96f8..a96dd32 100644
--- a/src/libsigfile/source-base.hh
+++ b/src/libsigfile/source-base.hh
@@ -225,22 +225,18 @@ class CSource {
ok = 0,
bad_header = (1 << 0),
bad_numfld = (1 << 1),
- date_unparsable = (1 << 2),
- time_unparsable = (1 << 3),
- nosession = (1 << 4),
- noepisode = (1 << 5),
- nonkemp_signaltype = (1 << 6),
- non1020_channel = (1 << 7),
- dup_channels = (1 << 8),
- sysfail = (1 << 9),
- too_many_channels = (1 << 10),
- nonconforming_patient_id = (1 << 11),
- missing_patient_id = (1 << 12),
- invalid_subject_details = (1 << 13),
- extra_patientid_subfields = (1 << 14),
- bad_channel_count = (1 << 15)
+ bad_datetime = (1 << 2),
+ bad_session_or_episode = (1 << 3),
+ nonkemp_signaltype = (1 << 4),
+ non1020_channel = (1 << 5),
+ dup_channels = (1 << 6),
+ sysfail = (1 << 7),
+ too_many_channels = (1 << 8),
+ missing_patient_id = (1 << 9),
+ invalid_subject_details = (1 << 10),
+ conflicting_channel_type = (1 << 11),
};
- const static unsigned COMMON_STATUS_BITS = 15;
+ const static unsigned COMMON_STATUS_BITS = 11;
protected:
string _filename;
@@ -274,7 +270,10 @@ class CSource {
int status() const { return _status; }
int flags() const { return _flags; }
- virtual string explain_status() const = 0;
+ static string explain_status( int);
+ virtual string explain_status() const
+ { return move(explain_status( _status)); }
+
enum TDetails { with_channels = 1, with_annotations = 2 };
virtual string details( int which_details) const = 0;
@@ -295,10 +294,18 @@ class CSource {
virtual const char* session() const = 0;
// recording time and duration
- virtual time_t start_time() const = 0;
- virtual time_t end_time() const = 0;
+ time_t _start_time,
+ _end_time;
+ virtual time_t start_time() const
+ { return _start_time; }
+ virtual time_t end_time() const
+ { return _end_time; }
virtual double recording_time() const = 0;
+ virtual int set_start_time( time_t);
+ virtual int set_recording_date( const string&) = 0;
+ virtual int set_recording_time( const string&) = 0;
+
// channels
const static size_t max_channels = 1024;
@@ -352,7 +359,6 @@ class CSource {
virtual int set_episode( const string&) = 0;
virtual int set_session( const string&) = 0;
virtual int set_comment( const string&) = 0;
- virtual int set_start_time( time_t) = 0;
// get samples
// original
@@ -437,8 +443,12 @@ class CSource {
}
// supporting functions
- tuple<string, string, int>
- figure_session_and_episode();
+ tuple<string, string>
+ figure_session_and_episode(); // hand over the pair separately for specific ways to store these fields in derived classes
+
+ enum class TAcceptTimeFormat { edf_strict, any };
+ void
+ figure_times( const string&, const string&, TAcceptTimeFormat);
};
diff --git a/src/libsigfile/tsv.cc b/src/libsigfile/tsv.cc
index b4799ce..176cde8 100644
--- a/src/libsigfile/tsv.cc
+++ b/src/libsigfile/tsv.cc
@@ -21,7 +21,7 @@
#include "common/lang.hh"
#include "common/string.hh"
#include "tsv.hh"
-#include "source.hh"
+#include "typed-source.hh"
using namespace std;
@@ -33,19 +33,6 @@ using agh::str::tokens_trimmed;
using sigfile::CTSVFile;
-int
-CTSVFile::
-set_start_time( time_t s)
-{
- char b[9];
- strftime( b, 9, "%d.%m.%y", localtime(&s));
- metadata["recording_date"].assign( b);
- strftime( b, 9, "%H.%M.%s", localtime(&s));
- metadata["recording_time"].assign( b);
-
- return 0;
-}
-
@@ -126,8 +113,6 @@ CTSVFile (CTSVFile&& rv)
swap( metadata, rv.metadata);
_subtype = rv._subtype;
- _start_time = rv._start_time;
- _end_time = rv._end_time;
swap( channels, rv.channels);
swap( common_annotations, rv.common_annotations);
@@ -145,7 +130,7 @@ CTSVFile (CTSVFile&& rv)
CTSVFile::
~CTSVFile ()
{
- if ( not (flags() & sigfile::CSource::no_ancillary_files) )
+ if ( not (_flags & sigfile::CSource::no_ancillary_files) )
save_ancillary_files();
if ( _line0 )
free( (void*)_line0);
@@ -153,6 +138,20 @@ CTSVFile::
+int
+CTSVFile::
+set_recording_date( const string& s)
+{
+ metadata["recording_date"] = s;
+ return 0;
+}
+int
+CTSVFile::
+set_recording_time( const string& s)
+{
+ metadata["recording_time"] = s;
+ return 0;
+}
int
@@ -181,7 +180,7 @@ _parse_header()
// 2. pick essential bits
if ( metadata.find( "recording_id") == metadata.end() ) {
fprintf( stderr, "No session/episode in header\n");
- _status |= (nosession | noepisode);
+ _status |= bad_session_or_episode;
return -1;
}
@@ -191,6 +190,20 @@ _parse_header()
return -1;
}
+ if ( metadata.find( "recording_date") == metadata.end() ||
+ metadata.find( "recording_time") == metadata.end() ) {
+ fprintf( stderr, "No recording_date in header\n");
+ _status |= CSource::bad_datetime;
+ return -1;
+ }
+
+ figure_times(
+ metadata["recording_date"],
+ metadata["recording_time"],
+ TAcceptTimeFormat::any);
+ if ( _status & bad_datetime && !(_flags & CSource::TFlags::no_field_consistency_check) )
+ return -1;
+
if ( metadata.find( "comment") == metadata.end() )
;
@@ -210,11 +223,8 @@ _parse_header()
channels.emplace_back( h);
// 3. deal with episode and session
- int parsed_with_issues;
- tie( _session, _episode, parsed_with_issues) =
+ tie( _session, _episode) =
figure_session_and_episode();
- if ( parsed_with_issues )
- _status |= (nosession | noepisode);
// 4. are channels unique?
for ( auto &H : channels )
@@ -264,7 +274,6 @@ outer_break:
return -1;
}
- printf( "read %zu samples in %zu channels\n", ll/channels.size(), channels.size());
// vector -> valarray
for ( size_t h = 0; h < channels.size(); ++h ) {
channels[h].data.resize( ll);
@@ -272,6 +281,10 @@ outer_break:
channels[h].data[i] = c2[h][i];
}
+
+ // only now as late
+ _end_time = _start_time + (time_t)recording_time();
+
return 0;
}
@@ -355,37 +368,9 @@ CTSVFile::
explain_status( const int status)
{
list<string> recv;
- if ( status & sysfail )
- recv.emplace_back( "* stat or fopen error");
- if ( status & bad_header )
- recv.emplace_back( "* Ill-formed header");
- if ( status & missing_patient_id )
- recv.emplace_back( "* Missing PatientId");
- if ( status & bad_numfld )
- recv.emplace_back( "* Garbage in numerical fields");
- if ( status & date_unparsable )
- recv.emplace_back( "* Date field ill-formed");
- if ( status & time_unparsable )
- recv.emplace_back( "* Time field ill-formed");
- if ( status & nosession )
- recv.emplace_back( "* No session information in field RecordingID");
- if ( status & non1020_channel )
- recv.emplace_back( "* Channel designation not following the 10-20 system");
- if ( status & nonconforming_patient_id )
- recv.emplace_back( "* PatientId not conforming to section 2.1.3.3 of EDF spec");
- if ( status & invalid_subject_details )
- recv.emplace_back( "* PatientId has incomplete or ill-formed subject details");
- if ( status & nonkemp_signaltype )
- recv.emplace_back( "* Signal type not listed in Kemp et al");
- if ( status & dup_channels )
- recv.emplace_back( "* Duplicate channel names");
- if ( status & too_many_channels )
- recv.emplace_back( string("* Number of channels grearter than ") + to_string(max_channels));
- if ( status & extra_patientid_subfields )
- recv.emplace_back( "* Extra subfields in PatientId");
if ( status & bad_channel_count )
- recv.emplace_back( "* Number of channels declared in header different from number of columns of data");
- return join(recv, "\n");
+ recv.emplace_back( "Number of channels declared in header different from number of columns of data");
+ return CSource::explain_status(status) + (recv.empty() ? "" : (join(recv, "\n") + '\n'));
}
diff --git a/src/libsigfile/tsv.hh b/src/libsigfile/tsv.hh
index 4d84c3e..2a8b061 100644
--- a/src/libsigfile/tsv.hh
+++ b/src/libsigfile/tsv.hh
@@ -111,12 +111,10 @@ class CTSVFile
{ return _session.c_str(); }
// times
- time_t start_time() const
- { return _start_time; }
- time_t end_time() const
- { return _end_time; }
double recording_time() const // in seconds
{ return (double)channels.front().data.size() / _samplerate; } // all channels have the same sr, obviously
+ int set_recording_date( const string&);
+ int set_recording_time( const string&);
// setters
int set_patient_id( const string& s)
@@ -146,8 +144,6 @@ class CTSVFile
return 0;
}
- int set_start_time( time_t);
-
// channels
size_t n_channels() const
{ return channels.size(); }
@@ -335,9 +331,10 @@ class CTSVFile
enum TStatus : int_least32_t {
+ bad_channel_count = (1 << (COMMON_STATUS_BITS + 1)),
inoperable = (bad_header
| bad_numfld
- | date_unparsable | time_unparsable
+ | bad_datetime
| dup_channels
| sysfail
| too_many_channels)
@@ -352,8 +349,6 @@ class CTSVFile
TSubtype _subtype;
size_t _samplerate;
- time_t _start_time,
- _end_time;
FILE *_f;
char *_line0;
diff --git a/src/libsigfile/source.cc b/src/libsigfile/typed-source.cc
similarity index 96%
rename from src/libsigfile/source.cc
rename to src/libsigfile/typed-source.cc
index cceb968..26049a2 100644
--- a/src/libsigfile/source.cc
+++ b/src/libsigfile/typed-source.cc
@@ -1,5 +1,5 @@
/*
- * File name: libsigfile/source.cc
+ * File name: libsigfile/typed-source.cc
* Project: Aghermann
* Author: Andrei Zavada <johnhommer at gmail.com>
* Initial version: 2011-11-14
@@ -10,7 +10,7 @@
*/
-#include "source.hh"
+#include "typed-source.hh"
#include "edf.hh"
#include "tsv.hh"
diff --git a/src/libsigfile/source.hh b/src/libsigfile/typed-source.hh
similarity index 97%
rename from src/libsigfile/source.hh
rename to src/libsigfile/typed-source.hh
index b82261c..f372b92 100644
--- a/src/libsigfile/source.hh
+++ b/src/libsigfile/typed-source.hh
@@ -1,5 +1,5 @@
/*
- * File name: libsigfile/source.hh
+ * File name: libsigfile/typed-source.hh
* Project: Aghermann
* Author: Andrei Zavada <johnhommer at gmail.com>
* Initial version: 2011-11-11
diff --git a/src/tools/agh-profile-gen.cc b/src/tools/agh-profile-gen.cc
index 58e6144..e86c8c6 100644
--- a/src/tools/agh-profile-gen.cc
+++ b/src/tools/agh-profile-gen.cc
@@ -23,8 +23,7 @@
#include "common/alg.hh"
#include "common/fs.hh"
#include "common/string.hh"
-#include "libsigfile/edf.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "libmetrics/all.hh"
#if HAVE_CONFIG_H && !defined(VERSION)
diff --git a/src/tools/edfcat.cc b/src/tools/edfcat.cc
index afb5b8c..ad72592 100644
--- a/src/tools/edfcat.cc
+++ b/src/tools/edfcat.cc
@@ -21,7 +21,7 @@
#include <fstream>
#include "libsigproc/sigproc.hh"
#include "libsigfile/edf.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "common/alg.hh"
#include "common/fs.hh"
#include "common/string.hh"
diff --git a/src/tools/edfhed-gtk.cc b/src/tools/edfhed-gtk.cc
index 4a81384..091b394 100644
--- a/src/tools/edfhed-gtk.cc
+++ b/src/tools/edfhed-gtk.cc
@@ -12,7 +12,7 @@
#include <gtk/gtk.h>
#include "libsigfile/edf.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
void
diff --git a/src/tools/edfhed.cc b/src/tools/edfhed.cc
index 15cdb0d..1c96000 100644
--- a/src/tools/edfhed.cc
+++ b/src/tools/edfhed.cc
@@ -18,7 +18,7 @@
//#include <argp.h>
#include "common/fs.hh"
-#include "libsigfile/source.hh"
+#include "libsigfile/typed-source.hh"
#include "libsigfile/edf.hh"
// there's some deep and curious issue argp.h brings up if it is
@@ -261,8 +261,7 @@ set_recording_datetime_from_mtime( sigfile::CEDFFile& F)
static int
set_mtime_from_recording_datetime( sigfile::CEDFFile& F)
{
- if ( F.status() & sigfile::CEDFFile::date_unparsable ||
- F.status() & sigfile::CEDFFile::time_unparsable ) {
+ if ( F.status() & sigfile::CSource::bad_datetime ) {
fprintf( stderr, "Error: Bad recording_date or _time fields; not setting file mtime");
return -1;
}
--
Sleep experiment manager
More information about the debian-med-commit
mailing list