[med-svn] [SCM] aghermann branch, master, updated. 551e213a23b59b71cba6a9c3a282d1b60e21b854
andrei zavada
jh at johnhommer.com
Sun Apr 21 23:17:56 UTC 2013
The following commit has been merged in the master branch:
commit 86c1ce0c12e75a6a2de7670767e65f097bcc9bd7
Author: andrei zavada <jh at johnhommer.com>
Date: Sat Apr 13 10:15:00 2013 +0000
WIP
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 209e348..86c6ae1 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -7,12 +7,14 @@ noinst_LIBRARIES := \
liba_a_SOURCES := \
libcommon.cc \
+ subject_id.cc \
config-validate.hh \
string.hh \
globals.hh \
alg.hh \
fs.hh \
- lang.hh
+ lang.hh \
+ subject_id.hh
if DO_PCH
BUILT_SOURCES := \
@@ -20,7 +22,8 @@ BUILT_SOURCES := \
string.hh.gch \
globals.hh.gch \
alg.hh.gch \
- fs.hh.gch
+ fs.hh.gch \
+ subject_id.hh
%.hh.gch: %.hh
$(CXXCOMPILE) -c $<
diff --git a/src/common/subject_id.cc b/src/common/subject_id.cc
new file mode 100644
index 0000000..21b5ac1
--- /dev/null
+++ b/src/common/subject_id.cc
@@ -0,0 +1,120 @@
+/*
+ * File name: common/subject_id.cc
+ * Project: Aghermann
+ * Author: Andrei Zavada <johnhommer at gmail.com>
+ * Initial version: 2013-04-13
+ *
+ * Purpose: subject_id shared between agh::CSubject and libsigfile::CSource
+ *
+ * License: GPL
+ */
+
+#include <ctime>
+
+#include <string>
+#include <cstring>
+#include "string.hh"
+#include "subject_id.hh"
+
+#if HAVE_CONFIG_H && !defined(VERSION)
+# include "config.h"
+#endif
+
+using namespace std;
+using agh::SSubjectId;
+
+SSubjectId::TGender
+SSubjectId::
+char_to_gender( char x)
+{
+ switch ( x ) {
+ case 'M':
+ case 'm':
+ return TGender::male;
+ case 'F':
+ case 'f':
+ return TGender::female;
+ default:
+ return TGender::unknown;
+ }
+}
+
+
+char
+__attribute__ ((const))
+SSubjectId::
+gender_sign( TGender g)
+{
+ switch ( g ) {
+ case TGender::male:
+ return 'M';
+ case TGender::female:
+ return 'F';
+ default:
+ return 'X';
+ }
+}
+
+
+
+namespace {
+
+int str_to_english_month( const string& s)
+{
+ if ( strcasecmp( s.c_str(), "jan") == 0 )
+ return 0;
+ if ( strcasecmp( s.c_str(), "feb") == 0 )
+ return 1;
+ if ( strcasecmp( s.c_str(), "mar") == 0 )
+ return 2;
+ if ( strcasecmp( s.c_str(), "apr") == 0 )
+ return 3;
+ if ( strcasecmp( s.c_str(), "may") == 0 )
+ return 4;
+ if ( strcasecmp( s.c_str(), "jun") == 0 )
+ return 5;
+ if ( strcasecmp( s.c_str(), "jul") == 0 )
+ return 6;
+ if ( strcasecmp( s.c_str(), "aug") == 0 )
+ return 7;
+ if ( strcasecmp( s.c_str(), "sep") == 0 )
+ return 8;
+ if ( strcasecmp( s.c_str(), "oct") == 0 )
+ return 9;
+ if ( strcasecmp( s.c_str(), "nov") == 0 )
+ return 10;
+ if ( strcasecmp( s.c_str(), "dec") == 0 )
+ return 11;
+ else
+ return -1;
+}
+}
+
+
+time_t
+SSubjectId::
+str_to_dob( const string& s)
+{
+ struct tm t;
+ memset( &t, '\0', sizeof (t));
+
+ // strptime( s, "%d-", &t); // will suck in non-US locales, so
+ auto ff = agh::str::tokens(s, "-");
+ if ( ff.size() != 3 )
+ return (time_t)0;
+ auto f = ff.begin();
+ try {
+ t.tm_mday = stoi( *f++);
+ t.tm_mon = str_to_english_month(*f++);
+ t.tm_year = 1900 + stoi(*f);
+ return mktime( &t);
+ } catch (...) {
+ return (time_t)0;
+ }
+}
+
+
+// Local Variables:
+// Mode: c++
+// indent-tabs-mode: 8
+// End:
diff --git a/src/common/subject_id.hh b/src/common/subject_id.hh
new file mode 100644
index 0000000..4827df5
--- /dev/null
+++ b/src/common/subject_id.hh
@@ -0,0 +1,72 @@
+/*
+ * File name: common/subject_id.hh
+ * Project: Aghermann
+ * Author: Andrei Zavada <johnhommer at gmail.com>
+ * Initial version: 2013-04-13
+ *
+ * Purpose: subject_id shared between agh::CSubject and libsigfile::CSource
+ *
+ * License: GPL
+ */
+
+#ifndef _AGH_SUBJECT_ID
+#define _AGH_SUBJECT_ID
+
+#include <ctime>
+
+#include <string>
+#include <cstring>
+
+#if HAVE_CONFIG_H && !defined(VERSION)
+# include "config.h"
+#endif
+
+using namespace std;
+
+namespace agh {
+
+
+// follow http://www.edfplus.info/specs/edfplus.html#datarecords, section 2.1.3.3
+struct SSubjectId {
+ string id,
+ name;
+ time_t dob;
+ enum class TGender : char {
+ unknown = 'X', male = 'M', female = 'F'
+ };
+ TGender gender;
+
+ SSubjectId ( const string& id_ = "", const string& name_ = "",
+ time_t dob_ = (time_t)0,
+ TGender gender_ = TGender::unknown)
+ : id (id_),
+ name (name_),
+ dob (dob_),
+ gender (gender_)
+ {}
+ SSubjectId (SSubjectId&& rv)
+ {
+ id.swap( rv.id);
+ name.swap( rv.name);
+ dob = rv.dob;
+ gender = rv.gender;
+ }
+
+ char gender_sign() const
+ {
+ return gender_sign(gender);
+ }
+
+ static char gender_sign( TGender);
+ static TGender char_to_gender( char);
+ static time_t str_to_dob( const string&);
+};
+
+} // namespace agh
+
+#endif
+
+// Local Variables:
+// Mode: c++
+// indent-tabs-mode: 8
+// End:
diff --git a/src/expdesign/primaries.cc b/src/expdesign/primaries.cc
index 86efc10..ba19774 100644
--- a/src/expdesign/primaries.cc
+++ b/src/expdesign/primaries.cc
@@ -27,7 +27,7 @@
using namespace std;
using namespace agh;
-
+using confval::SValidator;
agh::CExpDesign::
CExpDesign (const string& session_dir_,
@@ -40,46 +40,46 @@ CExpDesign (const string& session_dir_,
swa_laden_pages_before_SWA_0 (3),
_id_pool (0),
config_keys_g ({
- confval::SValidator<double>("ctl_param.step_size", &ctl_params0.siman_params.step_size),
- confval::SValidator<double>("ctl_param.boltzmann_k", &ctl_params0.siman_params.k, confval::SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
- confval::SValidator<double>("ctl_param.t_initial", &ctl_params0.siman_params.t_initial, confval::SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
- confval::SValidator<double>("ctl_param.damping_mu", &ctl_params0.siman_params.mu_t, confval::SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
- confval::SValidator<double>("ctl_param.t_min", &ctl_params0.siman_params.t_min, confval::SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
- confval::SValidator<double>("profile.req_scored_pc", &req_percent_scored, confval::SValidator<double>::SVFRangeIn( 80., 100.)),
- confval::SValidator<double>("fft_param.binsize", &fft_params.binsize, confval::SValidator<double>::SVFRangeIn( .125, 1.)),
- confval::SValidator<double>("artifacts.dampen_factor", &af_dampen_factor, confval::SValidator<double>::SVFRangeIn( 0., 1.)),
- confval::SValidator<double>("mc_param.mc_gain", &mc_params.mc_gain, confval::SValidator<double>::SVFRangeIn( 0., 100.)),
- confval::SValidator<double>("mc_param.f0fc", &mc_params.f0fc, confval::SValidator<double>::SVFRangeEx( 0., 80.)),
- confval::SValidator<double>("mc_param.bandwidth", &mc_params.bandwidth, confval::SValidator<double>::SVFRangeIn( 0.125, 2.)),
- confval::SValidator<double>("mc_param.iir_backpolate", &mc_params.iir_backpolate, confval::SValidator<double>::SVFRangeIn( 0., 1.)),
- confval::SValidator<double>("swu_param.min_upswing_duration",
- &swu_params.min_upswing_duration, confval::SValidator<double>::SVFRangeIn( 0.01, 1.)),
+ SValidator<double>("ctl_param.step_size", &ctl_params0.siman_params.step_size),
+ SValidator<double>("ctl_param.boltzmann_k", &ctl_params0.siman_params.k, SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
+ SValidator<double>("ctl_param.t_initial", &ctl_params0.siman_params.t_initial, SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
+ SValidator<double>("ctl_param.damping_mu", &ctl_params0.siman_params.mu_t, SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
+ SValidator<double>("ctl_param.t_min", &ctl_params0.siman_params.t_min, SValidator<double>::SVFRangeEx( DBL_MIN, 1e9)),
+ SValidator<double>("profile.req_scored_pc", &req_percent_scored, SValidator<double>::SVFRangeIn( 80., 100.)),
+ SValidator<double>("fft_param.binsize", &fft_params.binsize, SValidator<double>::SVFRangeIn( .125, 1.)),
+ SValidator<double>("artifacts.dampen_factor", &af_dampen_factor, SValidator<double>::SVFRangeIn( 0., 1.)),
+ SValidator<double>("mc_param.mc_gain", &mc_params.mc_gain, SValidator<double>::SVFRangeIn( 0., 100.)),
+ SValidator<double>("mc_param.f0fc", &mc_params.f0fc, SValidator<double>::SVFRangeEx( 0., 80.)),
+ SValidator<double>("mc_param.bandwidth", &mc_params.bandwidth, SValidator<double>::SVFRangeIn( 0.125, 2.)),
+ SValidator<double>("mc_param.iir_backpolate", &mc_params.iir_backpolate, SValidator<double>::SVFRangeIn( 0., 1.)),
+ SValidator<double>("swu_param.min_upswing_duration",
+ &swu_params.min_upswing_duration, SValidator<double>::SVFRangeIn( 0.01, 1.)),
}),
config_keys_d ({
- confval::SValidator<int>("fft_param.welch_window_type", (int*)&fft_params.welch_window_type, confval::SValidator<int>::SVFRangeIn( 0, (int)sigproc::TWinType_total - 1)),
- confval::SValidator<int>("fft_param.plan_type", (int*)&fft_params.plan_type, confval::SValidator<int>::SVFRangeIn( 0, (int)metrics::psd::TFFTWPlanType_total - 1)),
- confval::SValidator<int>("artifacts.dampen_window_type",(int*)&af_dampen_window_type, confval::SValidator<int>::SVFRangeIn( 0, (int)sigproc::TWinType_total - 1)),
- confval::SValidator<int>("ctl_param.iters_fixed_t", &ctl_params0.siman_params.iters_fixed_T, confval::SValidator<int>::SVFRangeIn( 1, 1000000)),
- confval::SValidator<int>("ctl_param.n_tries", &ctl_params0.siman_params.n_tries, confval::SValidator<int>::SVFRangeIn( 1, 10000)),
+ SValidator<int>("fft_param.welch_window_type", (int*)&fft_params.welch_window_type, SValidator<int>::SVFRangeIn( 0, (int)sigproc::TWinType_total - 1)),
+ SValidator<int>("fft_param.plan_type", (int*)&fft_params.plan_type, SValidator<int>::SVFRangeIn( 0, (int)metrics::psd::TFFTWPlanType_total - 1)),
+ SValidator<int>("artifacts.dampen_window_type",(int*)&af_dampen_window_type, SValidator<int>::SVFRangeIn( 0, (int)sigproc::TWinType_total - 1)),
+ SValidator<int>("ctl_param.iters_fixed_t", &ctl_params0.siman_params.iters_fixed_T, SValidator<int>::SVFRangeIn( 1, 1000000)),
+ SValidator<int>("ctl_param.n_tries", &ctl_params0.siman_params.n_tries, SValidator<int>::SVFRangeIn( 1, 10000)),
}),
config_keys_z ({
- confval::SValidator<size_t>("smp.num_threads", &num_threads, confval::SValidator<size_t>::SVFRangeIn( 0, 20)),
- confval::SValidator<size_t>("mc_params.n_bins", &mc_params.n_bins, confval::SValidator<size_t>::SVFRangeIn( 1, 100)),
- confval::SValidator<size_t>("profile.swa_laden_pages_before_SWA_0",
- &swa_laden_pages_before_SWA_0, confval::SValidator<size_t>::SVFRangeIn( 1, 100)),
- confval::SValidator<size_t>("fft_param.pagesize", &fft_params.pagesize, confval::SValidator<size_t>::SVFRangeIn( 4, 120)),
- confval::SValidator<size_t>("mc_param.smooth_side", &mc_params.smooth_side, confval::SValidator<size_t>::SVFRangeIn( 0, 5)),
+ SValidator<size_t>("smp.num_threads", &num_threads, SValidator<size_t>::SVFRangeIn( 0, 20)),
+ SValidator<size_t>("mc_params.n_bins", &mc_params.n_bins, SValidator<size_t>::SVFRangeIn( 1, 100)),
+ SValidator<size_t>("profile.swa_laden_pages_before_SWA_0",
+ &swa_laden_pages_before_SWA_0, SValidator<size_t>::SVFRangeIn( 1, 100)),
+ SValidator<size_t>("fft_param.pagesize", &fft_params.pagesize, SValidator<size_t>::SVFRangeIn( 4, 120)),
+ SValidator<size_t>("mc_param.smooth_side", &mc_params.smooth_side, SValidator<size_t>::SVFRangeIn( 0, 5)),
}),
config_keys_b ({
- confval::SValidator<bool>("ctl_param.DBAmendment1", &ctl_params0.DBAmendment1),
- confval::SValidator<bool>("ctl_param.DBAmendment2", &ctl_params0.DBAmendment2),
- confval::SValidator<bool>("ctl_param.AZAmendment1", &ctl_params0.AZAmendment1),
- confval::SValidator<bool>("ctl_param.AZAmendment2", &ctl_params0.AZAmendment2),
- confval::SValidator<bool>("profile.score_unscored_as_wake",
+ SValidator<bool>("ctl_param.DBAmendment1", &ctl_params0.DBAmendment1),
+ SValidator<bool>("ctl_param.DBAmendment2", &ctl_params0.DBAmendment2),
+ SValidator<bool>("ctl_param.AZAmendment1", &ctl_params0.AZAmendment1),
+ SValidator<bool>("ctl_param.AZAmendment2", &ctl_params0.AZAmendment2),
+ SValidator<bool>("profile.score_unscored_as_wake",
&score_unscored_as_wake),
}),
config_keys_s ({
- confval::SValidator<string>("LastUsedVersion", &last_used_version),
+ SValidator<string>("LastUsedVersion", &last_used_version),
})
{
char *tmp = canonicalize_file_name(session_dir_.c_str());
@@ -107,7 +107,7 @@ CExpDesign (const string& session_dir_,
mc_params.scope = fft_params.pagesize;
#ifdef _OPENMP
- omp_set_num_threads( (num_threads == 0) ? agh::global::num_procs : num_threads);
+ omp_set_num_threads( (num_threads == 0) ? global::num_procs : num_threads);
printf( "SMP enabled with %d threads\n", omp_get_max_threads());
#endif
if ( last_used_version != VERSION ) {
@@ -389,57 +389,6 @@ used_samplerates( sigfile::SChannel::TType type) const
-const char*
-__attribute__ ((const))
-agh::CSubject::
-gender_sign( TGender g)
-{
- switch ( g ) {
- case TGender::male:
- return "M";
- case TGender::female:
- return "F";
- case TGender::neuter:
- return "o";
- default:
- return "??";
- }
-}
-
-agh::CSubject::
-CSubject (const string& dir,
- sid_type id)
- : short_name (dir.substr( dir.rfind('/')+1)),
- gender (TGender::neuter),
- age (21),
- _status (0),
- _id (id),
- _dir (dir)
-{
- ifstream ifs (_dir + "/.subject_info");
- char gender_char;
- if ( ifs.good() and
- (getline( ifs, full_name, '\n'),
- ifs >> gender_char >> age,
- getline( ifs, comment, '\n'),
- ifs.good()) )
- gender = (TGender)gender_char;
- else
- full_name = short_name;
-}
-
-
-agh::CSubject::
-~CSubject ()
-{
- ofstream ofs (_dir + "/.subject_info");
- char gender_char = (char)gender;
- if ( ofs.good() )
- ofs << full_name << endl
- << gender_char << endl
- << age << endl
- << comment << endl;
-}
diff --git a/src/expdesign/primaries.hh b/src/expdesign/primaries.hh
index 00fab5c..d29387f 100644
--- a/src/expdesign/primaries.hh
+++ b/src/expdesign/primaries.hh
@@ -23,6 +23,7 @@
#include <stdexcept>
#include "common/config-validate.hh"
+#include "common/subject_id.hh"
#include "sigproc/winfun.hh"
#include "model/achermann.hh"
#include "recording.hh"
@@ -41,27 +42,25 @@ using namespace std;
typedef size_t sid_type;
-class CSubject {
+class CSubject : public SSubjectId {
void operator=( const CSubject&) = delete;
CSubject () = delete;
public:
- enum class TGender : char {
- neuter = 'o', male = 'M', female = 'F'
- };
- static const char* gender_sign( TGender g);
-
- public:
- string short_name,
- full_name;
- TGender gender;
- int age;
+ float age() const;
string comment;
const string& dir() const { return _dir; }
- CSubject (const string& dir, sid_type id);
+ CSubject (const CSubject&) = default;
+ CSubject (const string& dir, sid_type id)
+ : agh::SSubjectId (dir.substr( dir.rfind('/')+1)),
+ _status (0),
+ _id (id),
+ _dir (dir)
+ {}
+
~CSubject ();
class SEpisodeSequence;
@@ -221,11 +220,11 @@ class CSubject {
bool operator==( const CSubject &o) const
{
- return short_name == o.short_name;
+ return id == o.id;
}
bool operator==( const string& n) const
{
- return short_name == n;
+ return SSubjectId::id == n;
}
bool operator==( sid_type id) const
{
@@ -328,7 +327,7 @@ class CExpDesign {
{
map<string, CJGroup>::const_iterator G;
const CSubject& J = subject_by_x(j, &G);
- return _session_dir + '/' + G->first + '/' + J.short_name;
+ return _session_dir + '/' + G->first + '/' + J.SSubjectId::id;
}
// scan tree: build all structures
diff --git a/src/expdesign/recording.hh b/src/expdesign/recording.hh
index e197099..71b66fd 100644
--- a/src/expdesign/recording.hh
+++ b/src/expdesign/recording.hh
@@ -153,7 +153,7 @@ class CRecording {
const metrics::mc::SPPack&);
~CRecording ();
- const char* subject() const { return _source().name.c_str(); }
+ const char* subject() const { return _source().subject().name.c_str(); }
const char* session() const { return _source().session(); }
const char* episode() const { return _source().episode(); }
const char* channel() const { return _source().channel_by_id(_sig_no); }
diff --git a/src/expdesign/tree-scanner.cc b/src/expdesign/tree-scanner.cc
index e074779..d2333c8 100644
--- a/src/expdesign/tree-scanner.cc
+++ b/src/expdesign/tree-scanner.cc
@@ -100,7 +100,6 @@ add_one( sigfile::CTypedSource&& Fmc,
// printf( "E0 %s: ", e0.name());
// puts( asctime( localtime(&e0.start_time())));
// puts( asctime( localtime(&e0.start_rel)));
- // printf( "--\n");
double shift = difftime( e0.start_rel, e0.start_time());
e0.end_rel = e0.end_time() + shift;
@@ -151,16 +150,16 @@ register_intree_source( sigfile::CTypedSource&& F,
}
// refuse to register sources of wrong subjects
- if ( j_name != F().id ) {
+ if ( j_name != F()._subject.id ) {
log_message( "%s: file belongs to subject %s (\"%s\"), is misplaced here under subject \"%s\"\n",
- F().filename(), F().id.c_str(), F().name.c_str(), j_name.c_str());
+ F().filename(), F()._subject.id.c_str(), F()._subject.name.c_str(), j_name.c_str());
return -1;
}
try {
- auto existing_group = group_of( F().id.c_str());
+ auto existing_group = group_of( F()._subject.id.c_str());
if ( g_name != existing_group ) {
log_message( "%s: subject %s (\"%s\") belongs to a different group (\"%s\")\n",
- F().filename(), F().id.c_str(), F().name.c_str(), existing_group);
+ F().filename(), F()._subject.id.c_str(), F()._subject.name.c_str(), existing_group);
return -1;
}
} catch (invalid_argument) {
@@ -190,7 +189,7 @@ register_intree_source( sigfile::CTypedSource&& F,
// insert/update episode observing start/end times
printf( "\nCExpDesign::register_intree_source( file: \"%s\", J: %s (\"%s\"), E: \"%s\", D: \"%s\")\n",
- F().filename(), F().id.c_str(), F().name.c_str(), F().episode(), F().session());
+ F().filename(), F().subject().id.c_str(), F().subject().name.c_str(), F().episode(), F().session());
switch ( J->measurements[F().session()].add_one(
move(F), fft_params, swu_params, mc_params) ) { // this will do it
case AGH_EPSEQADD_OVERLAP:
@@ -319,7 +318,7 @@ scan_tree( TMsmtCollectProgressIndicatorFun user_progress_fun)
if ( D.second.episodes.size() < n_episodes &&
complete_episode_set.front() != D.second.episodes.begin()->name() ) { // the baseline is missing
log_message( "No Baseline episode in %s's %s: skip this session\n",
- J.short_name.c_str(), D.first.c_str());
+ J.id.c_str(), D.first.c_str());
J.measurements.erase(D.first);
goto startover;
}
diff --git a/src/libsigfile/edf.cc b/src/libsigfile/edf.cc
index 123cab6..5004b6b 100644
--- a/src/libsigfile/edf.cc
+++ b/src/libsigfile/edf.cc
@@ -73,9 +73,8 @@ set_session( const char* s)
int
sigfile::CEDFFile::
-set_comment( const char *s)
+set_reserved( const char *s)
{
- fprintf( stderr, "Writing to reserved EDF field: don't do that!\n");
memcpy( header.reserved, agh::str::pad( s, 44).c_str(), 44);
return strlen(s) > 44;
}
@@ -155,6 +154,7 @@ CEDFFile (const char *fname_, int flags_)
// artifacts, per signal
if ( flags_ & sigfile::CTypedSource::no_ancillary_files )
return;
+
// else read artifacts, filters and annotations from external files
for ( auto &H : channels ) {
ifstream thomas (make_fname_artifacts( H.label));
@@ -265,7 +265,7 @@ CEDFFile (const char *fname_, TSubtype subtype_, int flags_,
_lay_out_header();
strncpy( header.version_number, version_string, 8);
- set_patient_id( "Fafa_1 M X Mr._Fafa");
+ _subject.id = "Fafa_1";
set_recording_id( "Zzz");
set_comment( fname_);
set_start_time( time(NULL));
@@ -547,16 +547,18 @@ _parse_header()
// sub-parse patient_id into SSubjectId struct
{
auto subfields = agh::str::tokens( _patient_id, " ");
- if ( subfields.size() != 4 ) {
+ if ( unlikely (_patient_id.empty()) ) {
+ fprintf( stderr, "%s: Missing patient_id\n", filename());
+ _subject.id = _subject.name = "Fafa";
+ } else if ( subfields.size() != 4 ) {
fprintf( stderr, "%s: Nonconforming patient_id\n", filename());
- SSubjectId::id = SSubjectId::name = subfields.front();
- SSubjectId::gender = TGender::unknown;
+ _subject.id = _subject.name = subfields.front();
} else {
auto i = subfields.begin();
- SSubjectId::id = *i++;
- SSubjectId::gender = SSubjectId::char_to_gender((*i++)[0]);
- SSubjectId::dob = SSubjectId::str_to_dob(*i++);
- SSubjectId::name = agh::str::join( agh::str::tokens(*i++, "_"), " ");
+ _subject.id = *i++;
+ _subject.gender = agh::SSubjectId::char_to_gender((*i++)[0]);
+ _subject.dob = agh::SSubjectId::str_to_dob(*i++);
+ _subject.name = agh::str::join( agh::str::tokens(*i++, "_"), " ");
}
}
diff --git a/src/libsigfile/edf.hh b/src/libsigfile/edf.hh
index cd482e8..f20fc5d 100644
--- a/src/libsigfile/edf.hh
+++ b/src/libsigfile/edf.hh
@@ -118,13 +118,15 @@ class CEDFFile
{ return n_data_records * data_record_size; }
// setters
- int set_patient_id( const char* s);
- int set_recording_id( const char* s);
- int set_episode( const char* s);
- int set_session( const char* s);
- int set_comment( const char *s);
- int set_start_time( time_t s);
-
+ int set_patient_id( const char*);
+ int set_recording_id( const char*);
+ int set_episode( const char*);
+ int set_session( const char*);
+ int set_reserved( const char*);
+ int set_comment( const char* s)
+ { return set_reserved( s); }
+
+ int set_start_time( time_t);
// channels
size_t n_channels() const
{ return channels.size(); }
diff --git a/src/libsigfile/source-base.cc b/src/libsigfile/source-base.cc
index 0cf16ab..6c25a72 100644
--- a/src/libsigfile/source-base.cc
+++ b/src/libsigfile/source-base.cc
@@ -109,8 +109,8 @@ sigfile::SFilterPack::
dirty_signature() const
{
DEF_UNIQUE_CHARP (tmp);
- assert (asprintf( &tmp, "%g%d%g%d%d",
- low_pass_cutoff, low_pass_order, high_pass_cutoff, high_pass_order, (int)notch_filter));
+ ASPRINTF( &tmp, "%g%d%g%d%d",
+ low_pass_cutoff, low_pass_order, high_pass_cutoff, high_pass_order, (int)notch_filter);
return hash<std::string>() (tmp);
}
@@ -121,7 +121,8 @@ dirty_signature() const
sigfile::CSource::
-CSource( CSource&& rv)
+CSource (CSource&& rv)
+ : _subject (move(rv._subject))
{
swap( _filename, rv._filename);
_status = rv._status;
diff --git a/src/libsigfile/source-base.hh b/src/libsigfile/source-base.hh
index 45bed88..80ffeb1 100644
--- a/src/libsigfile/source-base.hh
+++ b/src/libsigfile/source-base.hh
@@ -14,7 +14,9 @@
#include "common/fs.hh"
#include "common/alg.hh"
+#include "common/subject_id.hh"
#include "sigproc/winfun.hh"
+#include "expdesign/forward-decls.hh"
#include "channel.hh"
#if HAVE_CONFIG_H && !defined(VERSION)
@@ -186,94 +188,24 @@ struct SFilterPack {
-// follow http://www.edfplus.info/specs/edfplus.html#datarecords, section 2.1.3.3
-struct SSubjectId {
- string id,
- name;
- time_t dob;
- enum class TGender : char {
- unknown = 'X', male = 'M', female = 'F'
- };
- TGender gender;
- static TGender char_to_gender( char x)
- {
- switch ( x ) {
- case 'M':
- case 'm':
- return TGender::male;
- case 'F':
- case 'f':
- return TGender::female;
- default:
- return TGender::unknown;
- }
- }
- static int str_to_english_month( const string& s)
- {
- if ( strcasecmp( s.c_str(), "jan") == 0 )
- return 0;
- if ( strcasecmp( s.c_str(), "feb") == 0 )
- return 1;
- if ( strcasecmp( s.c_str(), "mar") == 0 )
- return 2;
- if ( strcasecmp( s.c_str(), "apr") == 0 )
- return 3;
- if ( strcasecmp( s.c_str(), "may") == 0 )
- return 4;
- if ( strcasecmp( s.c_str(), "jun") == 0 )
- return 5;
- if ( strcasecmp( s.c_str(), "jul") == 0 )
- return 6;
- if ( strcasecmp( s.c_str(), "aug") == 0 )
- return 7;
- if ( strcasecmp( s.c_str(), "sep") == 0 )
- return 8;
- if ( strcasecmp( s.c_str(), "oct") == 0 )
- return 9;
- if ( strcasecmp( s.c_str(), "nov") == 0 )
- return 10;
- if ( strcasecmp( s.c_str(), "dec") == 0 )
- return 11;
- else
- return -1;
- }
- static time_t str_to_dob( const string& s)
- {
- struct tm t;
- memset( &t, '\0', sizeof (t));
-
- // strptime( s, "%d-", &t); // will suck in non-US locales, so
- auto ff = agh::str::tokens(s, "-");
- if ( ff.size() != 3 )
- return (time_t)0;
- auto f = ff.begin();
- try {
- t.tm_mday = stoi( *f++);
- t.tm_mon = str_to_english_month(*f++);
- t.tm_year = 1900 + stoi(*f);
- return mktime( &t);
- } catch (...) {
- return (time_t)0;
- }
- }
-};
-
-
-
-class CSource : public SSubjectId {
+class CSource {
friend class CTypedSource;
+ friend class agh::CSubject;
+ friend class agh::CExpDesign;
protected:
string _filename;
int _status;
int _flags;
+ agh::SSubjectId
+ _subject;
public:
DELETE_DEFAULT_METHODS (CSource);
- CSource (const string& fname, int flags = 0)
- : _filename (fname),
+ CSource (const string& fname_, int flags_ = 0)
+ : _filename (fname_),
_status (0),
- _flags (flags)
+ _flags (flags_)
{}
- CSource( CSource&& rv);
+ CSource( CSource&&);
virtual ~CSource()
{}
@@ -288,6 +220,10 @@ class CSource : public SSubjectId {
{
return _filename.c_str();
}
+ const agh::SSubjectId& subject() const
+ {
+ return _subject;
+ }
virtual const char* patient_id() const = 0;
virtual const char* recording_id() const = 0;
virtual const char* comment() const = 0;
diff --git a/src/metrics/mc.cc b/src/metrics/mc.cc
index 26c5e5f..9d210c1 100644
--- a/src/metrics/mc.cc
+++ b/src/metrics/mc.cc
@@ -75,7 +75,7 @@ fname_base() const
DEF_UNIQUE_CHARP (_);
ASPRINTF( &_,
"%s.%s-%lu"
- ":%lu-%g_%g" "_%g" "_%g_%g",
+ ":%zu-%g_%g" "_%g" "_%g_%g",
_using_F().filename(), _using_F().channel_by_id(_using_sig_no),
_using_F().dirty_signature( _using_sig_no),
Pp.pagesize,
@@ -95,7 +95,7 @@ mirror_fname() const
string basename_dot = agh::fs::make_fname_base (_using_F().filename(), "", true);
ASPRINTF( &_,
"%s-%s-%lu"
- ":%lu-%g_%g" "_%g" "_%g_%g" "_%g_%g@%zu"
+ ":%zu-%g_%g" "_%g" "_%g_%g" "_%g_%g@%zu"
".mc",
basename_dot.c_str(), _using_F().channel_by_id(_using_sig_no),
_using_F().dirty_signature( _using_sig_no),
@@ -162,7 +162,7 @@ export_tsv( const string& fname) const
fprintf( f, "## Subject: %s; Session: %s, Episode: %s recorded %.*s; Channel: %s\n"
"## Total EEG Microcontinuity course (%zu %zu-sec pages) from %g up to %g Hz in bins of %g Hz\n"
"#Page\t",
- _using_F().name.c_str(), _using_F().session(), _using_F().episode(),
+ _using_F().subject().name.c_str(), _using_F().session(), _using_F().episode(),
(int)strlen(asctime_)-1, asctime_,
_using_F().channel_by_id(_using_sig_no),
pages(), Pp.pagesize, Pp.freq_from, Pp.freq_from + Pp.bandwidth * bins(), Pp.bandwidth);
@@ -196,7 +196,7 @@ export_tsv( size_t bin,
fprintf( f, "## Microcontinuity profile of\n"
"## Subject: %s; Session: %s, Episode: %s recorded %.*s; Channel: %s\n"
"## Course (%zu %zu-sec pages) in range %g-%g Hz\n",
- _using_F().name.c_str(), _using_F().session(), _using_F().episode(),
+ _using_F().subject().name.c_str(), _using_F().session(), _using_F().episode(),
(int)strlen(asctime_)-1, asctime_,
_using_F().channel_by_id(_using_sig_no),
pages(), Pp.pagesize, Pp.freq_from, Pp.freq_from + (bin+1) * Pp.bandwidth);
diff --git a/src/metrics/page-metrics-base.cc b/src/metrics/page-metrics-base.cc
index 3064806..082bfb8 100644
--- a/src/metrics/page-metrics-base.cc
+++ b/src/metrics/page-metrics-base.cc
@@ -217,7 +217,7 @@ export_tsv( const string& fname) const
char *asctime_ = asctime( localtime( &sttm));
fprintf( f, "## Subject: %s; Session: %s, Episode: %s recorded %.*s; Channel: %s\n"
"#Page\t",
- _using_F().name.c_str(), _using_F().session(), _using_F().episode(),
+ _using_F().subject().name.c_str(), _using_F().session(), _using_F().episode(),
(int)strlen(asctime_)-1, asctime_,
_using_F().channel_by_id(_using_sig_no));
diff --git a/src/metrics/psd.cc b/src/metrics/psd.cc
index 6137127..dbb7faf 100644
--- a/src/metrics/psd.cc
+++ b/src/metrics/psd.cc
@@ -267,7 +267,7 @@ export_tsv( const string& fname) const
fprintf( f, "## Subject: %s; Session: %s, Episode: %s recorded %.*s; Channel: %s\n"
"## Total spectral power course (%zu %zu-sec pages) up to %g Hz in bins of %g Hz\n"
"#Page\t",
- _using_F().name.c_str(), _using_F().session(), _using_F().episode(),
+ _using_F().subject().name.c_str(), _using_F().session(), _using_F().episode(),
(int)strlen(asctime_)-1, asctime_,
_using_F().channel_by_id(_using_sig_no),
pages(), Pp.pagesize, _bins*Pp.binsize, Pp.binsize);
@@ -303,7 +303,7 @@ export_tsv( float from, float upto,
fprintf( f, "PSD profile of\n"
"## Subject: %s; Session: %s, Episode: %s recorded %.*s; Channel: %s\n"
"## Course (%zu %zu-sec pages) in range %g-%g Hz\n",
- _using_F().name.c_str(), _using_F().session(), _using_F().episode(),
+ _using_F().subject().name.c_str(), _using_F().session(), _using_F().episode(),
(int)strlen(asctime_)-1, asctime_,
_using_F().channel_by_id(_using_sig_no),
pages(), Pp.pagesize, from, upto);
diff --git a/src/metrics/swu.cc b/src/metrics/swu.cc
index 0c8cafd..efe7c26 100644
--- a/src/metrics/swu.cc
+++ b/src/metrics/swu.cc
@@ -155,7 +155,7 @@ export_tsv( const string& fname) const
fprintf( f, "## Subject: %s; Session: %s, Episode: %s recorded %.*s; Channel: %s\n"
"## SWU course (%zu %zu-sec pages)\n"
"#Page\tSWU\n",
- _using_F().name.c_str(), _using_F().session(), _using_F().episode(),
+ _using_F().subject().name.c_str(), _using_F().session(), _using_F().episode(),
(int)strlen(asctime_)-1, asctime_,
_using_F().channel_by_id(_using_sig_no),
pages(), Pp.pagesize);
--
Sleep experiment manager
More information about the debian-med-commit
mailing list