[med-svn] [SCM] aghermann branch, master, updated. 17c5ded0cb1e251d8640a94750eb700b2e062b2a

Andrei Zavada johnhommer at gmail.com
Sun Feb 24 13:40:20 UTC 2013


The following commit has been merged in the master branch:
commit 26716231d8817e5b42bdc1bb5757e05dd537ab97
Author: Andrei Zavada <johnhommer at gmail.com>
Date:   Tue Feb 19 02:48:01 2013 +0200

    complete 8c20fa6bdea

diff --git a/src/expdesign/primaries.cc b/src/expdesign/primaries.cc
index f8131f5..86efc10 100644
--- a/src/expdesign/primaries.cc
+++ b/src/expdesign/primaries.cc
@@ -339,9 +339,9 @@ enumerate_eeg_channels() const
 			for ( auto &D : J.measurements )
 				for ( auto &E : D.second.episodes )
 					for ( auto &F : E.sources )
-						for ( size_t h = 0; h < F.n_channels(); ++h )
-							if ( F.signal_type(h) == sigfile::SChannel::TType::eeg )
-								recp.push_back( F.channel_by_id(h));
+						for ( size_t h = 0; h < F().n_channels(); ++h )
+							if ( F().signal_type(h) == sigfile::SChannel::TType::eeg )
+								recp.push_back( F().channel_by_id(h));
 	recp.sort();
 	recp.unique();
 	return recp;
@@ -357,7 +357,7 @@ enumerate_all_channels() const
 			for ( auto &D : J.measurements )
 				for ( auto &E : D.second.episodes )
 					for ( auto &F : E.sources ) {
-						auto Ins = F.channel_list();
+						auto Ins = F().channel_list();
 						recp.insert( recp.end(),
 							     Ins.begin(), Ins.end());
 					}
@@ -377,10 +377,10 @@ used_samplerates( sigfile::SChannel::TType type) const
 			for ( auto &D : J.measurements )
 				for ( auto &E : D.second.episodes )
 					for ( auto &F : E.sources )
-						for ( size_t h = 0; h < F.n_channels(); ++h )
+						for ( size_t h = 0; h < F().n_channels(); ++h )
 							if ( type == sigfile::SChannel::other or
-							     type == F.signal_type(h) ) {
-								recp.push_back( F.samplerate(h));
+							     type == F().signal_type(h) ) {
+								recp.push_back( F().samplerate(h));
 							}
 	recp.sort();
 	recp.unique();
@@ -448,7 +448,7 @@ agh::CSubject::
 
 
 agh::CSubject::SEpisode::
-SEpisode (sigfile::CSource&& F_,
+SEpisode (sigfile::CTypedSource&& F_,
 	  const metrics::psd::SPPack& fft_params,
 	  const metrics::swu::SPPack& swu_params,
 	  const metrics::mc::SPPack& mc_params)
@@ -456,9 +456,9 @@ SEpisode (sigfile::CSource&& F_,
       // move it in place
 	sources.emplace_back( move(F_));
 	auto& F = sources.back();
-	auto HH = F.channel_list();
+	auto HH = F().channel_list();
 	printf( "CSubject::SEpisode::SEpisode( \"%s\"): %s\n",
-		F.filename(), agh::str::join(HH, ", ").c_str());
+		F().filename(), agh::str::join(HH, ", ").c_str());
 	int h = 0;
 	for ( auto& H : HH )
 		recordings.insert( {H, {F, h++, fft_params, swu_params, mc_params}});
@@ -472,11 +472,11 @@ get_annotations() const
 	list<agh::CSubject::SEpisode::SAnnotation>
 		ret;
 	for ( auto &F : sources ) {
-		auto HH = F.channel_list();
+		auto HH = F().channel_list();
 		for ( size_t h = 0; h < HH.size(); ++h ) {
-			auto &AA = F.annotations(h);
+			auto &AA = F().annotations(h);
 			for ( auto &A : AA )
-				ret.emplace_back( F, h, A);
+				ret.emplace_back( F(), h, A);
 		}
 	}
 	ret.sort();
@@ -577,7 +577,7 @@ sync()
 			for ( auto &D : J.measurements )
 				for ( auto &E : D.second.episodes )
 					for ( auto &F : E.sources )
-						F.write_ancillary_files();
+						F().write_ancillary_files();
 }
 
 
diff --git a/src/expdesign/primaries.hh b/src/expdesign/primaries.hh
index a3b30b0..f07a4ad 100644
--- a/src/expdesign/primaries.hh
+++ b/src/expdesign/primaries.hh
@@ -67,10 +67,10 @@ class CSubject {
 	class SEpisodeSequence;
 	class SEpisode {
 	    public:
-		const time_t& start_time() const	{ return sources.front().start_time();	}
-		const time_t& end_time() const		{ return sources.front().end_time();	}
-		const time_t& start_time()		{ return sources.front().start_time();	}
-		const time_t& end_time()		{ return sources.front().end_time();	}
+		const time_t& start_time() const	{ return sources.front()().start_time(); }
+		const time_t& end_time() const		{ return sources.front()().end_time();	 }
+		const time_t& start_time()		{ return sources.front()().start_time(); }
+		const time_t& end_time()		{ return sources.front()().end_time();	 }
 		time_t	// relative to start_time
 			start_rel,
 			end_rel;
@@ -79,7 +79,7 @@ class CSubject {
 		TRecordingSet
 			recordings; // one per channel, naturally
 
-		SEpisode (sigfile::CSource&& Fmc,
+		SEpisode (sigfile::CTypedSource&& Fmc,
 			  const metrics::psd::SPPack&,
 			  const metrics::swu::SPPack&,
 			  const metrics::mc::SPPack&);
@@ -87,7 +87,7 @@ class CSubject {
 		const char*
 		name() const
 			{
-				return sources.front().episode();
+				return sources.front()().episode();
 			}
 		bool
 		operator==( const string& e) const
@@ -97,8 +97,8 @@ class CSubject {
 		bool
 		operator<( const SEpisode& rv) const
 			{
-				return sources.front().end_time()
-					< rv.sources.front().start_time();
+				return sources.front()().end_time()
+					< rv.sources.front()().start_time();
 			}
 
 		struct SAnnotation
@@ -136,7 +136,7 @@ class CSubject {
 	    // 	friend class agh::CSubject;
 	    // 	friend class aghui::SScoringFacility;
 	      // allow multiple sources (possibly supplying different channels)
-		list<sigfile::CSource>
+		list<sigfile::CTypedSource>
 			sources;
 	};
 
@@ -185,7 +185,7 @@ class CSubject {
 	      // either construct a new episode from F, or update an
 	      // existing one (add F to its sources)
 		int
-		add_one( sigfile::CSource&&,
+		add_one( sigfile::CTypedSource&&,
 			 const metrics::psd::SPPack&,
 			 const metrics::swu::SPPack&,
 			 const metrics::mc::SPPack&,
@@ -339,7 +339,7 @@ class CExpDesign {
 
     public:
       // edf sources
-	int register_intree_source( sigfile::CSource&&,
+	int register_intree_source( sigfile::CTypedSource&&,
 				    const char **reason_if_failed_p = nullptr);
 
       // model runs
diff --git a/src/expdesign/recording.cc b/src/expdesign/recording.cc
index b5a079e..ea43687 100644
--- a/src/expdesign/recording.cc
+++ b/src/expdesign/recording.cc
@@ -20,7 +20,7 @@ using namespace std;
 
 
 agh::CRecording::
-CRecording (sigfile::CSource& F, int sig_no,
+CRecording (sigfile::CTypedSource& F, int sig_no,
 	    const metrics::psd::SPPack& fft_params,
 	    const metrics::swu::SPPack& swu_params,
 	    const metrics::mc::SPPack& mc_params)
@@ -119,23 +119,23 @@ CProfile (CSubject& J, const string& d, const sigfile::SChannel& h,
 			_pagesize = M.psd_profile.Pp.pagesize;
 			_pages_in_bed = 0;
 		} else
-			if ( _pagesize != F.pagesize() ) {
+			if ( _pagesize != M.pagesize() ) {
 				_status |= TFlags::euneq_pagesize;
 				return;  // this is really serious, so return now
 			}
 
 		int	pa = (size_t)difftime( F.start_time(), _0at) / _pagesize,
 //			pz = (size_t)difftime( F.end_time(), _0at) / _pagesize;
-			pz = pa + F.length_in_seconds() / _pagesize;
+			pz = pa + M.hypnogram().pages();
 	      // anchor zero page, get pagesize from edf^W CBinnedPower^W either goes
-		printf( "CProfile::CProfile(): adding %s of [%s, %s, %s] %zu pages (%d indeed) recorded %s",
+		printf( "CProfile::CProfile(): adding %s of [%s, %s, %s] %zu pages (%zu full, %zu in hypnogram) recorded %s",
 			metrics::name(params.metric), F.subject(), F.session(), F.episode(),
-			F.pages(), pz-pa, ctime( &F.start_time()));
+			M.total_pages(), M.full_pages(), M.hypnogram().pages(), ctime( &F.start_time()));
 
-		if ( pz - pa != (int)F.pages() ) {
-			fprintf( stderr, "CProfile::CProfile(): correcting end page to match page count in EDF: %d->%zu\n",
-				 pz, pa + F.pages());
-			pz = pa + F.pages();
+		if ( pz - pa != (int)M.full_pages() ) {
+			fprintf( stderr, "CProfile::CProfile(): correcting end page to match full page count in EDF: %d->%zu\n",
+				 pz, pa + M.full_pages());
+			pz = pa + M.full_pages();
 		}
 		_pages_in_bed += (pz-pa);
 
@@ -182,14 +182,14 @@ CProfile (CRecording& M,
 
 	int	pa = (size_t)difftime( M.F().start_time(), _0at) / _pagesize,
 		pz = (size_t)difftime( M.F().end_time(), _0at) / _pagesize;
-	printf( "CProfile::CProfile(): adding single recording %s of [%s, %s, %s] %zu pages (%d indeed) recorded %s",
+	printf( "CProfile::CProfile(): adding single recording %s of [%s, %s, %s] %zu pages (%zu full, %zu in hypnogram) recorded %s",
 		metrics::name(params.metric), M.F().subject(), M.F().session(), M.F().episode(),
-		M.F().pages(), pz-pa, ctime( &M.F().start_time()));
+		M.total_pages(), M.full_pages(), M.hypnogram().pages(), ctime( &M.F().start_time()));
 
-	if ( pz - pa != (int)M.F().pages() ) {
-		fprintf( stderr, "CProfile::CProfile(): correct end page to match page count in EDF: %d->%zu\n",
-			 pz, pa + M.F().pages());
-		pz = pa + M.F().pages();
+	if ( pz - pa != (int)M.full_pages() ) {
+		fprintf( stderr, "CProfile::CProfile(): correcting end page to match full page count in EDF: %d->%zu\n",
+			 pz, pa + M.full_pages());
+		pz = pa + M.full_pages();
 	}
 	_pages_in_bed += (pz-pa);
 
@@ -247,8 +247,9 @@ create_timeline()
 	for ( auto Mi = _mm_list.begin(); Mi != _mm_list.end(); ++Mi ) {
 		auto& M = **Mi;
 		const auto& F = M.F();
+		const auto& Y = M.hypnogram();
 
-		if ( F.percent_scored() < req_percent_scored )
+		if ( Y.percent_scored() < req_percent_scored )
 			_status |= TFlags::enoscore;
 
 	      // collect M's power and scores
@@ -258,7 +259,7 @@ create_timeline()
 		size_t	pa = (size_t)difftime( F.start_time(), _0at) / _pagesize,
 			pz = (size_t)difftime( F.end_time(), _0at) / _pagesize;
 		for ( size_t p = pa; p < pz; ++p ) {
-			_timeline[p] = sigfile::SPageSimulated {F[p-pa]};
+			_timeline[p] = sigfile::SPageSimulated {Y[p-pa]};
 		      // fill unscored/MVT per user setting
 			if ( !_timeline[p].is_scored() ) {
 				if ( score_unscored_as_wake )
diff --git a/src/expdesign/recording.hh b/src/expdesign/recording.hh
index a34fcee..e416809 100644
--- a/src/expdesign/recording.hh
+++ b/src/expdesign/recording.hh
@@ -147,30 +147,36 @@ class CRecording {
 		_source (rv._source),
 		_sig_no (rv._sig_no)
 		{}
-	CRecording (sigfile::CSource& F, int sig_no,
+	CRecording (sigfile::CTypedSource& F, int sig_no,
 		    const metrics::psd::SPPack&,
 		    const metrics::swu::SPPack&,
 		    const metrics::mc::SPPack&);
        ~CRecording ();
 
-	const char* subject() const      {  return _source.subject(); }
-	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); }
+	const char* subject() const      {  return _source().subject(); }
+	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); }
 
 	sigfile::SChannel::TType signal_type() const
 		{
-			return _source.signal_type(_sig_no);
+			return _source().signal_type(_sig_no);
 		}
 
-	const sigfile::CSource&	F() const
+	const sigfile::CSource& F() const
 		{
-			return _source;
+			return _source();
 		}
 	sigfile::CSource& F()  // although we shouldn't want to access CEDFFile writably from CRecording,
 		{      // this shortcut saves us the trouble of AghCC->subject_by_x(,,,).measurements...
-			return _source;  // on behalf of aghui::SChannelPresentation
+			return _source();  // on behalf of aghui::SChannelPresentation
 		}
+	const sigfile::CHypnogram&
+	hypnogram() const
+		{
+			return *(sigfile::CHypnogram*)&_source;
+		}
+
 	int h() const
 		{
 			return _sig_no;
@@ -178,35 +184,36 @@ class CRecording {
 
 	bool operator<( const CRecording &o) const
 		{
-			return _source.end_time() < o._source.start_time();
+			return _source().end_time() < o._source().start_time();
 		}
 
 	time_t start() const
 		{
-			return _source.start_time();
+			return _source().start_time();
 		}
 	time_t end() const
 		{
-			return _source.end_time();
+			return _source().end_time();
 		}
 
-	// this one damn identical in two bases
+	// this one damn identical in all bases
 	size_t pagesize() const
 		{
 			return ((metrics::psd::CProfile*)this) -> Pp.pagesize;
 		}
 
+	// actual page counts based on actual edf samples
 	size_t total_pages() const
 		{
-			return _source.recording_time() / pagesize();
+			return _source().recording_time() / pagesize();
 		}
 	size_t full_pages() const
 		{
-			return round(_source.recording_time() / pagesize());
+			return round(_source().recording_time() / pagesize());
 		}
 	size_t total_samples() const
 		{
-			return _source.recording_time() * _source.samplerate(_sig_no);
+			return _source().recording_time() * _source().samplerate(_sig_no);
 		}
 
 	valarray<TFloat>
@@ -247,7 +254,7 @@ class CRecording {
     protected:
 	int	_status;
 
-	sigfile::CSource&
+	sigfile::CTypedSource&
 		_source;
 	int	_sig_no;
 };
diff --git a/src/expdesign/tree-scanner.cc b/src/expdesign/tree-scanner.cc
index d59c7b4..553e2c7 100644
--- a/src/expdesign/tree-scanner.cc
+++ b/src/expdesign/tree-scanner.cc
@@ -41,14 +41,14 @@ agh::CExpDesign::TMsmtCollectProgressIndicatorFun
 
 int
 agh::CSubject::SEpisodeSequence::
-add_one( sigfile::CSource&& Fmc,
+add_one( sigfile::CTypedSource&& Fmc,
 	 const metrics::psd::SPPack& fft_params,
 	 const metrics::swu::SPPack& swu_params,
 	 const metrics::mc::SPPack& mc_params,
 	 float max_hours_apart)
 {
 	auto Ei = find( episodes.begin(), episodes.end(),
-			Fmc.episode());
+			Fmc().episode());
 
 	if ( Ei == episodes.end() ) {
 	      // ensure the newly added episode is well-placed
@@ -56,29 +56,29 @@ add_one( sigfile::CSource&& Fmc,
 		      // does not overlap with existing ones
 			if ( agh::alg::overlap(
 				     E.start_time(), E.end_time(),
-				     Fmc.start_time(), Fmc.end_time()) )
+				     Fmc().start_time(), Fmc().end_time()) )
 				return AGH_EPSEQADD_OVERLAP;
 
 		// or is not too far off
 		if ( episodes.size() > 0 &&
 		     episodes.begin()->sources.size() > 0 &&
-		     fabs( difftime( episodes.begin()->sources.begin()->start_time(), Fmc.start_time())) / 3600 > max_hours_apart )
+		     fabs( difftime( (*episodes.begin()->sources.begin())().start_time(), Fmc().start_time())) / 3600 > max_hours_apart )
 			return AGH_EPSEQADD_TOOFAR;
 
 		printf( "CSubject::SEpisodeSequence::add_one( \"%s\")\n",
-			Fmc.filename());
+			Fmc().filename());
 		episodes.emplace_back( move(Fmc), fft_params, swu_params, mc_params);
 		episodes.sort();
 
 	} else { // same as SEpisode() but done on an existing one
 	      // check that the edf source being added has exactly the same timestamp and duration
 		printf( "CSubject::SEpisodeSequence::add_one( \"%s\") try in-place\n",
-			Fmc.filename());
-		if ( fabs( difftime( Ei->start_time(), Fmc.start_time())) > 1 )
+			Fmc().filename());
+		if ( fabs( difftime( Ei->start_time(), Fmc().start_time())) > 1 )
 			return AGH_EPSEQADD_TOOFAR;
 		Ei->sources.emplace_back( move(Fmc));
 		auto& F = Ei->sources.back();
-		auto HH = F.channel_list();
+		auto HH = F().channel_list();
 		int h = 0;
 		for ( auto &H : HH )
 			Ei->recordings.insert( {H, {F, h++, fft_params, swu_params, mc_params}});
@@ -128,15 +128,15 @@ add_one( sigfile::CSource&& Fmc,
 // create new session/episode as necessary
 int
 agh::CExpDesign::
-register_intree_source( sigfile::CSource&& F,
+register_intree_source( sigfile::CTypedSource&& F,
 			const char **reason_if_failed_p)
 {
 	try {
 	      // parse fname (as appearing in the right place in the
 	      // tree) as ./group/subject/session/episode.edf
 	      // in order to validate this source wrt its placement in the tree
-		string toparse (F.filename());
-		if ( strncmp( F.filename(), _session_dir.c_str(), _session_dir.size()) == 0 )
+		string toparse (F().filename());
+		if ( strncmp( F().filename(), _session_dir.c_str(), _session_dir.size()) == 0 )
 			toparse.erase( 0, _session_dir.size());
 		list<string> broken_path = agh::fs::path_elements( toparse);
 		assert ( broken_path.size() == 5 );
@@ -153,16 +153,16 @@ register_intree_source( sigfile::CSource&& F,
 		}
 
 		// refuse to register sources of wrong subjects
-		if ( j_name != F.subject() ) {
+		if ( j_name != F().subject() ) {
 			log_message( "%s: file belongs to subject \"%s\", is misplaced here under subject \"%s\"\n",
-				     F.filename(), F.subject(), j_name.c_str());
+				     F().filename(), F().subject(), j_name.c_str());
 			return -1;
 		}
 		try {
-			auto existing_group = group_of( F.subject());
+			auto existing_group = group_of( F().subject());
 			if ( g_name != existing_group ) {
 				log_message( "%s: subject \"%s\" belongs to a different group (\"%s\")\n",
-					     F.filename(), F.subject(), existing_group);
+					     F().filename(), F().subject(), existing_group);
 				return -1;
 			}
 		} catch (invalid_argument) {
@@ -170,15 +170,15 @@ register_intree_source( sigfile::CSource&& F,
 		}
 
 		// but correct session/episode fields
-		if ( d_name != F.session() ) {
+		if ( d_name != F().session() ) {
 			log_message( "%s: correcting embedded session \"%s\" to match placement in the tree (\"%s\")\n",
-				     F.filename(), F.session(), d_name.c_str());
-			F.set_session( d_name.c_str());
+				     F().filename(), F().session(), d_name.c_str());
+			F().set_session( d_name.c_str());
 		}
-		if ( e_name != F.episode() ) {
+		if ( e_name != F().episode() ) {
 			log_message( "%s: correcting embedded episode \"%s\" to match file name\n",
-				     F.filename(), F.episode());
-			F.set_episode( e_name.c_str());
+				     F().filename(), F().episode());
+			F().set_episode( e_name.c_str());
 		}
 
 		CSubject *J;
@@ -192,16 +192,16 @@ register_intree_source( sigfile::CSource&& F,
 
 	      // insert/update episode observing start/end times
 		printf( "\nCExpDesign::register_intree_source( file: \"%s\", J: \"%s\", E: \"%s\", D: \"%s\")\n",
-			   F.filename(), F.subject(), F.episode(), F.session());
-		switch ( J->measurements[F.session()].add_one(
+			F().filename(), F().subject(), 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:
 			log_message( "%s: not added as it overlaps with existing episodes\n",
-				     F.filename());
+				     F().filename());
 			return -1;
 		case AGH_EPSEQADD_TOOFAR:
 			log_message( "%s: not added as it is too far removed from the rest\n",
-				     F.filename());
+				     F().filename());
 			return -1;
 		default:
 			return 0;
@@ -249,8 +249,8 @@ edf_file_processor( const char *fname, const struct stat*, int flag, struct FTW
 			++__cur_edf_file;
 			only_progress_fun( fname, agh::fs::__n_edf_files, __cur_edf_file);
 			try {
-				sigfile::CSource f_tmp {fname, __expdesign->fft_params.pagesize};
-				string st = f_tmp.explain_status();
+				sigfile::CTypedSource f_tmp {fname, __expdesign->fft_params.pagesize};
+				string st = f_tmp().explain_status();
 				if ( not st.empty() )
 					__expdesign->log_message( "%s: %s\n", fname, st.c_str());
 				__expdesign -> register_intree_source( move(f_tmp));
@@ -335,8 +335,8 @@ scan_tree( TMsmtCollectProgressIndicatorFun user_progress_fun)
 			for ( auto &D : J.measurements )
 				for ( auto &E : D.second.episodes )
 					tms[D.first][E.name()].emplace_back(
-						E.sources.front().start_time(),
-						E.sources.front().recording_time());
+						E.sources.front()().start_time(),
+						E.sources.front()().recording_time());
 		for ( auto &D : complete_session_set )
 			for ( auto &E : complete_episode_set )
 				G.second.avg_episode_times[D][E] =
diff --git a/src/libsigfile/edf.cc b/src/libsigfile/edf.cc
index c21efce..44e9005 100644
--- a/src/libsigfile/edf.cc
+++ b/src/libsigfile/edf.cc
@@ -113,7 +113,7 @@ const char version_string[8]  = {'0',' ',' ',' ', ' ',' ',' ',' '};
 
 sigfile::CEDFFile::
 CEDFFile (const char *fname_, int flags_)
-      : CSource_base (fname_, flags_)
+      : CSource (fname_, flags_)
 {
 	{
 		struct stat stat0;
@@ -151,7 +151,7 @@ CEDFFile (const char *fname_, int flags_)
 	header_length = 256 + (channels.size() * 256);
 
       // artifacts, per signal
-	if ( flags_ & sigfile::CSource::no_ancillary_files )
+	if ( flags_ & sigfile::CTypedSource::no_ancillary_files )
 		return;
       // else read artifacts, filters and annotations from external files
 	for ( auto &H : channels ) {
@@ -223,7 +223,7 @@ CEDFFile (const char *fname_, int flags_,
 	  const list<pair<string, size_t>>& channels_,
 	  size_t data_record_size_,
 	  size_t n_data_records_)
-      : CSource_base (fname_, flags_),
+      : CSource (fname_, flags_),
 	data_record_size (data_record_size_),
 	n_data_records (n_data_records_)
 {
@@ -352,7 +352,7 @@ resize( size_t new_records)
 
 sigfile::CEDFFile::
 CEDFFile (CEDFFile&& rv)
-      : CSource_base (move(rv))
+      : CSource (move(rv))
 {
 	header = rv.header; // no need to re-layout as we don't mremap
 	n_data_records   = rv.n_data_records;
@@ -386,7 +386,7 @@ sigfile::CEDFFile::
 		munmap( _mmapping, _fsize);
 		close( _fd);
 
-		if ( not (flags() & sigfile::CSource::no_ancillary_files) )
+		if ( not (flags() & sigfile::CTypedSource::no_ancillary_files) )
 			write_ancillary_files();
 	}
 }
diff --git a/src/libsigfile/edf.hh b/src/libsigfile/edf.hh
index 581d3c2..62812fd 100644
--- a/src/libsigfile/edf.hh
+++ b/src/libsigfile/edf.hh
@@ -39,7 +39,7 @@ namespace sigfile {
 
 
 class CEDFFile
-  : public CSource_base {
+  : public CSource {
 
       // deleted
 	bool operator==( const CEDFFile&) const = delete;
@@ -48,7 +48,7 @@ class CEDFFile
     public:
       // ctor
 	CEDFFile( const CEDFFile&)
-	      : CSource_base("invalid")
+	      : CSource("")
 		{
 			throw invalid_argument("nono");
 		}
@@ -179,14 +179,16 @@ class CEDFFile
 
 	list<SAnnotation>&
 	annotations( int h)
-		{
-			return (*this)[h].annotations;
-		}
+		{ return (*this)[h].annotations; }
 	list<SAnnotation>&
 	annotations( const char* h)
-		{
-			return (*this)[h].annotations;
-		}
+		{ return (*this)[h].annotations; }
+	const list<SAnnotation>&
+	annotations( int h) const
+		{ return (*this)[h].annotations; }
+	const list<SAnnotation>&
+	annotations( const char* h) const
+		{ return (*this)[h].annotations; }
 
 	// artifacts
 	SArtifacts&
diff --git a/src/libsigfile/forward-decls.hh b/src/libsigfile/forward-decls.hh
index 0db5dae..4c44934 100644
--- a/src/libsigfile/forward-decls.hh
+++ b/src/libsigfile/forward-decls.hh
@@ -20,8 +20,8 @@ struct SPageWithSWA;
 struct SPageSimulated;
 
 struct SChannel;
-class CSource_base;
 class CSource;
+class CTypedSource;
 class CHypnogram;
 
 } // namespace sigfile
diff --git a/src/libsigfile/source-base.cc b/src/libsigfile/source-base.cc
index 974dd23..0cf16ab 100644
--- a/src/libsigfile/source-base.cc
+++ b/src/libsigfile/source-base.cc
@@ -120,8 +120,8 @@ dirty_signature() const
 
 
 
-sigfile::CSource_base::
-CSource_base( CSource_base&& rv)
+sigfile::CSource::
+CSource( CSource&& rv)
 {
 	swap( _filename, rv._filename);
 	_status = rv._status;
diff --git a/src/libsigfile/source-base.hh b/src/libsigfile/source-base.hh
index e002334..f3b27f7 100644
--- a/src/libsigfile/source-base.hh
+++ b/src/libsigfile/source-base.hh
@@ -188,21 +188,21 @@ struct SFilterPack {
 
 
 
-class CSource_base {
-	friend class CSource;
+class CSource {
+	friend class CTypedSource;
     protected:
 	string	_filename;
 	int	_status;
 	int	_flags;
     public:
-	DELETE_DEFAULT_METHODS (CSource_base);
-	CSource_base( const string& fname, int flags = 0)
+	DELETE_DEFAULT_METHODS (CSource);
+	CSource (const string& fname, int flags = 0)
 	      : _filename (fname),
 		_status (0),
 		_flags (flags)
 		{}
-	CSource_base( CSource_base&& rv);
-	virtual ~CSource_base()
+	CSource( CSource&& rv);
+	virtual ~CSource()
 		{}
 
 	int status()	const { return _status; }
@@ -245,8 +245,12 @@ class CSource_base {
 	// annotations
 	virtual list<SAnnotation>&
 	annotations( const char*)		      = 0;
+	virtual const list<SAnnotation>&
+	annotations( const char*) const		      = 0;
 	virtual list<SAnnotation>&
 	annotations( int)			      = 0;
+	virtual const list<SAnnotation>&
+	annotations( int) const			      = 0;
 
 	// artifacts
 	virtual SArtifacts&
diff --git a/src/libsigfile/source.cc b/src/libsigfile/source.cc
index fd94e62..c07bedf 100644
--- a/src/libsigfile/source.cc
+++ b/src/libsigfile/source.cc
@@ -14,10 +14,10 @@
 
 using namespace std;
 
-sigfile::CSource::
-CSource (const char* fname,
-	 size_t pagesize,
-	 int flags)
+sigfile::CTypedSource::
+CTypedSource (const char* fname,
+	      size_t pagesize,
+	      int flags)
       : CHypnogram (pagesize)
 {
 	switch ( _type = source_file_type(fname) ) {
@@ -51,8 +51,8 @@ CSource (const char* fname,
 
 
 
-sigfile::CSource::
-CSource (CSource&& rv)
+sigfile::CTypedSource::
+CTypedSource (CTypedSource&& rv)
       : CHypnogram (move(rv))
 {
 	switch ( _type = rv._type ) {
@@ -65,6 +65,7 @@ CSource (CSource&& rv)
 		break;
 	case TType::edfplus:
 		//_obj = new CEDFPlusFile( *static_cast<CEDFPlusFile*>(rv._obj);
+		throw invalid_argument ("Source type 'edf+' not yet supported");
 		break;
 	case TType::unrecognised:
 		throw invalid_argument ("Unrecognised source type");
@@ -76,8 +77,8 @@ CSource (CSource&& rv)
 }
 
 
-sigfile::CSource::
-~CSource ()
+sigfile::CTypedSource::
+~CTypedSource ()
 {
 	if ( _obj ) {
 		if ( not (_obj->_flags & no_ancillary_files) )
@@ -88,8 +89,8 @@ sigfile::CSource::
 
 
 
-sigfile::CSource::TType
-sigfile::CSource::source_file_type( const char* fname)
+sigfile::CTypedSource::TType
+sigfile::CTypedSource::source_file_type( const char* fname)
 {
 	if ( strlen(fname) > 4 && strcasecmp( &fname[strlen(fname)-4], ".edf") == 0 )
 		return TType::edf;
diff --git a/src/libsigfile/source.hh b/src/libsigfile/source.hh
index 24204ae..adda774 100644
--- a/src/libsigfile/source.hh
+++ b/src/libsigfile/source.hh
@@ -4,7 +4,7 @@
  *          Author:  Andrei Zavada <johnhommer at gmail.com>
  * Initial version:  2011-11-11
  *
- *         Purpose:  generic signal source
+ *         Purpose:  generic signal source wrapper/selector
  *
  *         License:  GPL
  */
@@ -28,11 +28,11 @@ namespace sigfile {
 
 
 
-class CSource
+class CTypedSource
   : public CHypnogram {
 
-	void operator=( const CSource&) = delete;
-	CSource () = delete;
+	void operator=( const CTypedSource&) = delete;
+	CTypedSource () = delete;
     public:
 	enum class TType : int {
 		unrecognised,
@@ -42,24 +42,26 @@ class CSource
 
     private:
 	TType	_type;  // rtti is evil
-	CSource_base
+	CSource
 		*_obj;
     public:
-	CSource (const CSource&)
+	CTypedSource (const CTypedSource&)
 	      : CHypnogram (-1)
 		{
 			throw invalid_argument("nono");
 		}
       // ctor
 	enum { no_ancillary_files = 1 };
-	CSource (const char* fname, size_t pagesize, int flags = 0);
-	CSource (CSource&& rv);
-       ~CSource ();
+	CTypedSource (const char* fname, size_t pagesize, int flags = 0);
+	CTypedSource (CTypedSource&& rv);
+       ~CTypedSource ();
 
 	TType type() const { return _type; }
 
       // passthrough to obj
-	CSource_base& operator()()
+	CSource& operator()()
+		{ return *_obj; }
+	const CSource& operator()() const
 		{ return *_obj; }
 
       // filenames
diff --git a/src/metrics/mc.cc b/src/metrics/mc.cc
index 39926d4..ea21ba6 100644
--- a/src/metrics/mc.cc
+++ b/src/metrics/mc.cc
@@ -54,11 +54,11 @@ reset()
 
 
 metrics::mc::CProfile::
-CProfile (const sigfile::CSource& F, int sig_no,
+CProfile (const sigfile::CTypedSource& F, int sig_no,
 	  const SPPack &params)
       : metrics::CProfile (F, sig_no,
 			   params.pagesize, // acting 'pagesize' for metrics::CProfile
-			   params.compute_n_bins(F.samplerate(sig_no))),
+			   params.compute_n_bins(F().samplerate(sig_no))),
 	Pp (params)
 	// *_filter's initialized at compute time
 {
@@ -76,8 +76,8 @@ fname_base() const
 	ASPRINTF( &_,
 		  "%s.%s-%zu"
 		  ":%lu-%g_%g" "_%g" "_%g_%g",
-		  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-		  _using_F.dirty_signature( _using_sig_no),
+		  _using_F().filename(), _using_F().channel_by_id(_using_sig_no),
+		  _using_F().dirty_signature( _using_sig_no),
 		  Pp.pagesize,
 		  Pp.scope,
 		  Pp.iir_backpolate,
@@ -92,13 +92,13 @@ metrics::mc::CProfile::
 mirror_fname() const
 {
 	DEF_UNIQUE_CHARP (_);
-	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
+	string basename_dot = agh::fs::make_fname_base (_using_F().filename(), "", true);
 	ASPRINTF( &_,
 		  "%s-%s-%zu"
 		  ":%lu-%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),
+		  basename_dot.c_str(), _using_F().channel_by_id(_using_sig_no),
+		  _using_F().dirty_signature( _using_sig_no),
 		  Pp.pagesize,
 		  Pp.scope,
 		  Pp.iir_backpolate,
@@ -115,7 +115,7 @@ metrics::mc::CProfile::
 go_compute()
 {
 	_data.resize( pages() * _bins);
-	auto S = _using_F.get_signal_filtered( _using_sig_no);
+	auto S = _using_F().get_signal_filtered( _using_sig_no);
 	for ( size_t b = 0; b < bins(); ++b ) {
 		auto su_ss = metrics::mc::do_sssu_reduction(
 			S, samplerate(),
@@ -157,14 +157,14 @@ export_tsv( const string& fname) const
 	size_t bin, p;
 	float bum = 0.;
 
-	auto sttm = _using_F.start_time();
+	auto sttm = _using_F().start_time();
 	char *asctime_ = asctime( localtime( &sttm));
 	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.subject(), _using_F.session(), _using_F.episode(),
+		 _using_F().subject(), _using_F().session(), _using_F().episode(),
 		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no),
+		 _using_F().channel_by_id(_using_sig_no),
 		 pages(), Pp.pagesize, Pp.freq_from, Pp.freq_from + Pp.bandwidth * bins(), Pp.bandwidth);
 
 	for ( bin = 0; bin < _bins; ++bin, bum += Pp.bandwidth )
@@ -191,14 +191,14 @@ export_tsv( size_t bin,
 	if ( !f )
 		return -1;
 
-	auto sttm = _using_F.start_time();
+	auto sttm = _using_F().start_time();
 	char *asctime_ = asctime( localtime( &sttm));
 	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.subject(), _using_F.session(), _using_F.episode(),
+		 _using_F().subject(), _using_F().session(), _using_F().episode(),
 		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no),
+		 _using_F().channel_by_id(_using_sig_no),
 		 pages(), Pp.pagesize, Pp.freq_from, Pp.freq_from + (bin+1) * Pp.bandwidth);
 
 	for ( size_t p = 0; p < pages(); ++p )
diff --git a/src/metrics/mc.hh b/src/metrics/mc.hh
index 296450f..7539e7f 100644
--- a/src/metrics/mc.hh
+++ b/src/metrics/mc.hh
@@ -90,7 +90,7 @@ class CProfile
   : public metrics::CProfile {
 
     public:
-	CProfile (const sigfile::CSource&, int sig_no,
+	CProfile (const sigfile::CTypedSource&, int sig_no,
 		  const SPPack&);
 
 	SPPack Pp;
diff --git a/src/metrics/page-metrics-base.cc b/src/metrics/page-metrics-base.cc
index d8e1193..5c5f165 100644
--- a/src/metrics/page-metrics-base.cc
+++ b/src/metrics/page-metrics-base.cc
@@ -29,7 +29,7 @@
 using namespace std;
 
 metrics::CProfile::
-CProfile (const sigfile::CSource& F, int sig_no,
+CProfile (const sigfile::CTypedSource& F, int sig_no,
 	  size_t pagesize, size_t bins)
       : _status (0),
 	_bins (bins),
@@ -44,14 +44,14 @@ size_t
 metrics::CProfile::
 samplerate() const
 {
-	return _using_F.samplerate( _using_sig_no);
+	return _using_F().samplerate( _using_sig_no);
 }
 
 size_t
 metrics::CProfile::
 pages() const
 {
-	return _using_F.recording_time() / Pp.pagesize;
+	return _using_F().recording_time() / Pp.pagesize;
 }
 
 
@@ -80,7 +80,7 @@ list<agh::alg::SSpan<size_t>>
 metrics::CProfile::
 artifacts_in_samples() const
 {
-	return _using_F.artifacts( _using_sig_no)();
+	return _using_F().artifacts( _using_sig_no)();
 }
 
 
@@ -90,7 +90,7 @@ artifacts_in_seconds() const
 {
 	list<agh::alg::SSpan<float>> ret;
 	auto af_ = artifacts_in_samples();
-	size_t sr = _using_F.samplerate(_using_sig_no);
+	size_t sr = _using_F().samplerate(_using_sig_no);
 	for ( auto &A : af_ )
 		ret.emplace_back( A.a / (float)sr, A.z / (float)sr);
 	return ret;
@@ -102,7 +102,7 @@ int
 metrics::CProfile::
 compute( const SPPack& req_params)
 {
-	auto req_signature = _using_F.dirty_signature( _using_sig_no);
+	auto req_signature = _using_F().dirty_signature( _using_sig_no);
 	if ( have_data()
 	     and req_signature == _signature_when_mirrored
 	     and Pp.same_as(req_params) )
@@ -193,13 +193,13 @@ export_tsv( const string& fname) const
 
 	size_t bin, p;
 
-	auto sttm = _using_F.start_time();
+	auto sttm = _using_F().start_time();
 	char *asctime_ = asctime( localtime( &sttm));
 	fprintf( f, "## Subject: %s;  Session: %s, Episode: %s recorded %.*s;  Channel: %s\n"
 		 "#Page\t",
-		 _using_F.subject(), _using_F.session(), _using_F.episode(),
+		 _using_F().subject(), _using_F().session(), _using_F().episode(),
 		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no));
+		 _using_F().channel_by_id(_using_sig_no));
 
 	for ( bin = 0; bin < _bins; ++bin )
 		fprintf( f, "%zu%c", bin, bin+1 == _bins ? '\n' : '\t');
diff --git a/src/metrics/page-metrics-base.hh b/src/metrics/page-metrics-base.hh
index 8fba436..4598e9f 100644
--- a/src/metrics/page-metrics-base.hh
+++ b/src/metrics/page-metrics-base.hh
@@ -18,7 +18,7 @@
 
 #include "common/lang.hh"
 #include "common/alg.hh"
-#include "libsigfile/forward-decls.hh"
+#include "libsigfile/source.hh"
 #include "forward-decls.hh"
 
 #if HAVE_CONFIG_H && !defined(VERSION)
@@ -78,7 +78,7 @@ struct SPPack {
 class CProfile {
 
     protected:
-	CProfile (const sigfile::CSource&, int sig_no,
+	CProfile (const sigfile::CTypedSource&, int sig_no,
 		  size_t pagesize, size_t bins);
 	CProfile (const CProfile&) = default;
     public:
@@ -88,7 +88,7 @@ class CProfile {
 
 	const sigfile::CSource& source() const
 		{
-			return _using_F;
+			return _using_F();
 		}
 	int sig_no() const
 		{
@@ -173,7 +173,7 @@ class CProfile {
 
 	hash_t	_signature_when_mirrored;
 
-	const sigfile::CSource& _using_F;
+	const sigfile::CTypedSource& _using_F;
 	int _using_sig_no;
 
 	int mirror_enable( const string&);
diff --git a/src/metrics/psd.cc b/src/metrics/psd.cc
index 7056bd2..3e35b2c 100644
--- a/src/metrics/psd.cc
+++ b/src/metrics/psd.cc
@@ -80,11 +80,11 @@ reset()
 
 
 metrics::psd::CProfile::
-CProfile (const sigfile::CSource& F, int sig_no,
+CProfile (const sigfile::CTypedSource& F, int sig_no,
 	  const SPPack &fft_params)
 	: metrics::CProfile (F, sig_no,
 			     fft_params.pagesize,
-			     fft_params.compute_n_bins(F.samplerate(sig_no))),
+			     fft_params.compute_n_bins(F().samplerate(sig_no))),
 	  Pp (fft_params)
 {
 	Pp.check();
@@ -100,8 +100,8 @@ fname_base() const
 	ASPRINTF( &_,
 		  "%s.%s-%lu"
 		  ":%zu-%g-%c%c",
-		  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-		  _using_F.dirty_signature( _using_sig_no),
+		  _using_F().filename(), _using_F().channel_by_id(_using_sig_no),
+		  _using_F().dirty_signature( _using_sig_no),
 		  Pp.pagesize, Pp.binsize,
 		  'a'+(char)Pp.welch_window_type, 'a'+(char)Pp.plan_type);
 	string ret {_};
@@ -115,13 +115,13 @@ metrics::psd::CProfile::
 mirror_fname() const
 {
 	DEF_UNIQUE_CHARP (_);
-	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
+	string basename_dot = agh::fs::make_fname_base (_using_F().filename(), "", true);
 	ASPRINTF( &_,
 		  "%s.%s-%lu"
 		  ":%zu-%g-%c%c@%zu"
 		  ".psd",
-		  basename_dot.c_str(), _using_F.channel_by_id(_using_sig_no),
-		  _using_F.dirty_signature( _using_sig_no),
+		  basename_dot.c_str(), _using_F().channel_by_id(_using_sig_no),
+		  _using_F().dirty_signature( _using_sig_no),
 		  Pp.pagesize, Pp.binsize,
 		  'a'+(char)Pp.welch_window_type, 'a'+(char)Pp.plan_type,
 		  sizeof(double));
@@ -144,7 +144,7 @@ go_compute()
 
       // 0. get signal sample; always use double not TFloat
       // so that saved power is usable irrespective of what TFloat is today
-	valarray<double> S = agh::alg::to_vad( _using_F.get_signal_filtered( _using_sig_no));
+	valarray<double> S = agh::alg::to_vad( _using_F().get_signal_filtered( _using_sig_no));
 
       // 1. dampen samples marked as artifacts
 	// already done in get_signal_filtered()
@@ -262,14 +262,14 @@ export_tsv( const string& fname) const
 	size_t bin, p;
 	float bum = 0.;
 
-	auto sttm = _using_F.start_time();
+	auto sttm = _using_F().start_time();
 	char *asctime_ = asctime( localtime( &sttm));
 	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.subject(), _using_F.session(), _using_F.episode(),
+		 _using_F().subject(), _using_F().session(), _using_F().episode(),
 		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no),
+		 _using_F().channel_by_id(_using_sig_no),
 		 pages(), Pp.pagesize, _bins*Pp.binsize, Pp.binsize);
 
 	for ( bin = 0; bin < _bins; ++bin, bum += Pp.binsize )
@@ -298,14 +298,14 @@ export_tsv( float from, float upto,
 	if ( !f )
 		return -1;
 
-	auto sttm = _using_F.start_time();
+	auto sttm = _using_F().start_time();
 	char *asctime_ = asctime( localtime( &sttm));
 	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.subject(), _using_F.session(), _using_F.episode(),
+		 _using_F().subject(), _using_F().session(), _using_F().episode(),
 		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no),
+		 _using_F().channel_by_id(_using_sig_no),
 		 pages(), Pp.pagesize, from, upto);
 
 	valarray<TFloat> crs = course( from, upto);
diff --git a/src/metrics/psd.hh b/src/metrics/psd.hh
index 01fd1a3..0aff861 100644
--- a/src/metrics/psd.hh
+++ b/src/metrics/psd.hh
@@ -113,7 +113,7 @@ class CProfile
   : public metrics::CProfile {
 
     public:
-	CProfile (const sigfile::CSource&, int sig_no,
+	CProfile (const sigfile::CTypedSource&, int sig_no,
 		  const SPPack&);
 
 	SPPack Pp;
diff --git a/src/metrics/swu.cc b/src/metrics/swu.cc
index 03147f3..36a1312 100644
--- a/src/metrics/swu.cc
+++ b/src/metrics/swu.cc
@@ -46,11 +46,11 @@ reset()
 
 
 metrics::swu::CProfile::
-CProfile (const sigfile::CSource& F, int sig_no,
+CProfile (const sigfile::CTypedSource& F, int sig_no,
 	  const SPPack &params)
       : metrics::CProfile (F, sig_no,
 			   params.pagesize,
-			   params.compute_n_bins(F.samplerate(sig_no))),
+			   params.compute_n_bins(F().samplerate(sig_no))),
 	Pp (params)
 {
 	Pp.check();
@@ -66,8 +66,8 @@ fname_base() const
 	ASPRINTF( &_,
 		  "%s.%s-%lu"
 		  ":%zu-%g",
-		  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-		  _using_F.dirty_signature( _using_sig_no),
+		  _using_F().filename(), _using_F().channel_by_id(_using_sig_no),
+		  _using_F().dirty_signature( _using_sig_no),
 		  Pp.pagesize, Pp.min_upswing_duration);
 	string ret {_};
 	return ret;
@@ -79,13 +79,13 @@ metrics::swu::CProfile::
 mirror_fname() const
 {
 	DEF_UNIQUE_CHARP (_);
-	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
+	string basename_dot = agh::fs::make_fname_base (_using_F().filename(), "", true);
 	ASPRINTF( &_,
 		  "%s.%s-%lu"
 		  ":%zu-%g@%zu"
 		  ".swu",
-		  basename_dot.c_str(), _using_F.channel_by_id(_using_sig_no),
-		  _using_F.dirty_signature( _using_sig_no),
+		  basename_dot.c_str(), _using_F().channel_by_id(_using_sig_no),
+		  _using_F().dirty_signature( _using_sig_no),
 		  Pp.pagesize, Pp.min_upswing_duration,
 		  sizeof(TFloat));
 	string ret {_};
@@ -100,13 +100,14 @@ go_compute()
 	_data.resize( pages() * _bins);
 
 	auto dS = sigproc::derivative(
-		_using_F.get_signal_filtered( _using_sig_no));
+		_using_F().get_signal_filtered( _using_sig_no));
 
 	for ( size_t p = 0; p < pages(); ++p ) {
 		auto	a =  p    * (samplerate() * Pp.pagesize),
 			z = (p+1) * (samplerate() * Pp.pagesize);
 		auto	la = a, lz = a;
 		double	Q = 0.;
+	      // 1. upswing proper
 		// find a stretch of uninterrupted positive values
 		for ( auto i = a; i < z; ++i ) {
 			double q = 0.;
@@ -122,10 +123,14 @@ go_compute()
 			if ( upswing_duration > Pp.min_upswing_duration )
 				Q += q;
 		}
+	      // 2. clean peaks
+		
+
 		nmth_bin(p, 0) =
 			Q / Pp.pagesize;
 	}
 
+
 	return 0;
 }
 
@@ -145,14 +150,14 @@ export_tsv( const string& fname) const
 	if ( !f )
 		return -1;
 
-	auto sttm = _using_F.start_time();
+	auto sttm = _using_F().start_time();
 	char *asctime_ = asctime( localtime( &sttm));
 	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.subject(), _using_F.session(), _using_F.episode(),
+		 _using_F().subject(), _using_F().session(), _using_F().episode(),
 		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no),
+		 _using_F().channel_by_id(_using_sig_no),
 		 pages(), Pp.pagesize);
 
 	for ( size_t p = 0; p < pages(); ++p )
diff --git a/src/metrics/swu.hh b/src/metrics/swu.hh
index ebd2051..c708a61 100644
--- a/src/metrics/swu.hh
+++ b/src/metrics/swu.hh
@@ -50,7 +50,7 @@ class CProfile
   : public metrics::CProfile {
 
     public:
-	CProfile (const sigfile::CSource&, int sig_no,
+	CProfile (const sigfile::CTypedSource&, int sig_no,
 		  const SPPack&);
 
 	SPPack Pp;
diff --git a/src/tools/edfcat.cc b/src/tools/edfcat.cc
index e5e0715..c22981f 100644
--- a/src/tools/edfcat.cc
+++ b/src/tools/edfcat.cc
@@ -341,7 +341,7 @@ exec_convert( const SOperation::SObject& obj)
 		grand_min, grand_max);
 
 	sigfile::CEDFFile F ((obj + ".edf").c_str(),
-			     sigfile::CSource::no_ancillary_files,
+			     sigfile::CTypedSource::no_ancillary_files,
 			     make_channel_headers_for_CEDFFile( Hh.size(), "channel%zu", obj.samplerate),
 			     obj.record_size,
 			     ceilf(duration / obj.record_size));
@@ -364,7 +364,7 @@ exec_convert( const SOperation::SObject& obj)
 int
 exec_prune( const SOperation::SObject& obj)
 {
-	sigfile::CEDFFile F (obj.c_str(), sigfile::CSource::no_ancillary_files);
+	sigfile::CEDFFile F (obj.c_str(), sigfile::CTypedSource::no_ancillary_files);
 
 	list<pair<string, size_t>> selected_channels;
 	for ( auto& select_this : obj.channels ) {
@@ -383,7 +383,7 @@ exec_prune( const SOperation::SObject& obj)
 	printf( "Keeping %zu channel(s)\n", selected_channels.size());
 
 	sigfile::CEDFFile G ((agh::fs::make_fname_base( obj, ".edf", false) + "-mod.edf").c_str(),
-			     sigfile::CSource::no_ancillary_files,
+			     sigfile::CTypedSource::no_ancillary_files,
 			     selected_channels,
 			     F.data_record_size,
 			     F.n_data_records);
diff --git a/src/tools/edfhed-gtk.cc b/src/tools/edfhed-gtk.cc
index 92229cb..0ff0c3f 100644
--- a/src/tools/edfhed-gtk.cc
+++ b/src/tools/edfhed-gtk.cc
@@ -175,7 +175,7 @@ main( int argc, char **argv)
 
 	try {
 		auto F = sigfile::CEDFFile (fname,
-					    sigfile::CSource::no_ancillary_files |
+					    sigfile::CTypedSource::no_ancillary_files |
 					    sigfile::CEDFFile::no_field_consistency_check);
 
 		channel_no = 0;
diff --git a/src/tools/edfhed.cc b/src/tools/edfhed.cc
index bb6b887..9bdf83b 100644
--- a/src/tools/edfhed.cc
+++ b/src/tools/edfhed.cc
@@ -308,7 +308,7 @@ main( int argc, char **argv)
 	for ( auto &fname : Opts.files )
 		try {
 			auto F = sigfile::CEDFFile (fname,
-						    sigfile::CSource::no_ancillary_files |
+						    sigfile::CTypedSource::no_ancillary_files |
 						    sigfile::CEDFFile::no_field_consistency_check);
 			if ( Opts.settables.empty() &&
 			     not Opts.from_timestamp && not Opts.from_tree && not Opts.to_timestamp ) {
diff --git a/src/ui/mw/admit-one.cc b/src/ui/mw/admit-one.cc
index 649fc80..db595fa 100644
--- a/src/ui/mw/admit-one.cc
+++ b/src/ui/mw/admit-one.cc
@@ -23,19 +23,20 @@ aghui::SExpDesignUI::
 dnd_maybe_admit_one( const char* fname)
 {
 	using namespace sigfile;
-	CSource *F;
+	CTypedSource *Fp;
+
 	string info;
 	try {
-		F = new CSource (fname, ED->fft_params.pagesize);
-		if ( F->type() == CSource::TType::edf && F->status() & CEDFFile::TStatus::inoperable ) {
+		Fp = new CTypedSource (fname, ED->fft_params.pagesize);
+		if ( Fp->type() == CTypedSource::TType::edf && (*Fp)().status() & CEDFFile::TStatus::inoperable ) {
 			pop_ok_message( wMainWindow, "Bad EDF file", "The file <i>%s</i> doesn't appear to be a valid EDF file", fname);
 			return 0;
 		}
-		info = F->details();
+		info = (*Fp)().details();
 
 		snprintf_buf( "File: <i>%s</i>", fname);
 		gtk_label_set_markup( lEdfImportCaption, __buf__);
-		snprintf_buf( "<b>%s</b>", F->subject());
+		snprintf_buf( "<b>%s</b>", (*Fp)().subject());
 		gtk_label_set_markup( lEdfImportSubject, __buf__);
 
 	} catch ( exception& ex) {
@@ -54,7 +55,7 @@ dnd_maybe_admit_one( const char* fname)
 	try {
 		gtk_entry_set_text(
 			eEdfImportGroupEntry,
-			ED->group_of( F->subject()));
+			ED->group_of( (*Fp)().subject()));
 		gtk_widget_set_sensitive( (GtkWidget*)eEdfImportGroup, FALSE);
 	} catch (invalid_argument ex) {
 		for ( auto &i : AghGG ) {
@@ -108,7 +109,7 @@ dnd_maybe_admit_one( const char* fname)
 		dest_path = g_strdup_printf( "%s/%s/%s/%s",
 					     ED->session_dir().c_str(),
 					     selected_group,
-					     F->subject(),
+					     (*Fp)().subject(),
 					     selected_session);
 		dest = g_strdup_printf( "%s/%s.edf",
 					dest_path,
diff --git a/src/ui/mw/mainmenu_cb.cc b/src/ui/mw/mainmenu_cb.cc
index d254865..58b6d57 100644
--- a/src/ui/mw/mainmenu_cb.cc
+++ b/src/ui/mw/mainmenu_cb.cc
@@ -174,9 +174,9 @@ iExpGloballyDetectArtifacts_activate_cb( GtkMenuItem*, gpointer userdata)
 	SBusyBlock bb (ED.wMainWindow);
 
 	using namespace agh;
-	CExpDesign::TRecordingOpFun F;
+	CExpDesign::TRecordingOpFun op;
 	CExpDesign::TRecordingFilterFun filter;
-	CExpDesign::TRecordingReportFun G =
+	CExpDesign::TRecordingReportFun reporter =
 		[&]( const CJGroup&, const CSubject& J, const string& D, const CSubject::SEpisode& E, const CRecording& R,
 		     size_t i, size_t total)
 		{
@@ -188,19 +188,17 @@ iExpGloballyDetectArtifacts_activate_cb( GtkMenuItem*, gpointer userdata)
 		};
 	switch ( response ) {
 	case GTK_RESPONSE_OK:
-		F =
+		op =
 		[&]( CRecording& R)
 		{
 			auto	sr = R.F().samplerate(R.h());
 			auto&	af = R.F().artifacts(R.h());
 
-			auto	signal_original
-				= R.F().get_signal_original(R.h());
+			auto	signal_original = R.F().get_signal_original(R.h());
 
 			if ( not keep_existing )
 				af.clear_all();
-			auto	marked
-				= metrics::mc::detect_artifacts( signal_original, sr, P);
+			auto	marked = metrics::mc::detect_artifacts( signal_original, sr, P);
 			for ( size_t p = 0; p < marked.size(); ++p )
 				af.mark_artifact(
 					marked[p] * P.scope * sr,
@@ -213,11 +211,11 @@ iExpGloballyDetectArtifacts_activate_cb( GtkMenuItem*, gpointer userdata)
 		};
 	    break;
 	case 1: // "Clear All"
-		F =
+		op =
 		[&]( CRecording& R)
 		{
 			auto& F = R.F();
-			for ( auto& H : R.F().channel_list() ) {
+			for ( auto& H : F.channel_list() ) {
 				auto&	af = F.artifacts(H.c_str());
 				af.clear_all();
 			}
@@ -236,7 +234,7 @@ iExpGloballyDetectArtifacts_activate_cb( GtkMenuItem*, gpointer userdata)
 	for ( auto& SFp : ED.open_scoring_facilities )
 		bbl.push_front( new aghui::SBusyBlock (SFp->wSF));
 
-	ED.ED -> for_all_recordings( F, G, filter);
+	ED.ED -> for_all_recordings( op, reporter, filter);
 
 	for ( auto& SF : ED.open_scoring_facilities ) {
 		for ( auto& H : SF->channels )
@@ -289,8 +287,8 @@ iExpGloballySetFilters_activate_cb( GtkMenuItem*, gpointer userdata)
 				for ( auto &D : J.measurements )
 					for ( auto &E : D.second.episodes )
 						for ( auto &F : E.sources )
-							for ( auto &H : F.channel_list() ) {
-								auto& ff = F.filters(H.c_str());
+							for ( auto &H : F().channel_list() ) {
+								auto& ff = F().filters(H.c_str());
 								ff.low_pass_cutoff = LPC;
 								ff.low_pass_order = LPO;
 								ff.high_pass_cutoff = HPC;
diff --git a/src/ui/mw/measurements_cb.cc b/src/ui/mw/measurements_cb.cc
index 0bf9495..288fca9 100644
--- a/src/ui/mw/measurements_cb.cc
+++ b/src/ui/mw/measurements_cb.cc
@@ -168,8 +168,8 @@ iSubjectTimelineEDFInfo_activate_cb( GtkMenuItem*, gpointer userdata)
 	auto J = ED.using_subject;
 
 	const auto& F = J->using_episode->sources.front();
-	gtk_text_buffer_set_text( ED.tEDFFileDetailsReport, F.details().c_str(), -1);
-	snprintf_buf( "%s header", F.filename());
+	gtk_text_buffer_set_text( ED.tEDFFileDetailsReport, F().details().c_str(), -1);
+	snprintf_buf( "%s header", F().filename());
 	gtk_window_set_title( (GtkWindow*)ED.wEDFFileDetails,
 			      __buf__);
 	gtk_widget_show_all( (GtkWidget*)ED.wEDFFileDetails);
diff --git a/src/ui/sf/d/phasediff.cc b/src/ui/sf/d/phasediff.cc
index 4f9ab0d..471bb60 100644
--- a/src/ui/sf/d/phasediff.cc
+++ b/src/ui/sf/d/phasediff.cc
@@ -178,7 +178,7 @@ draw( cairo_t* cr, int wd, int ht)
 		cairo_stroke( cr);
 
 		cairo_set_font_size( cr, 10);
-		float	hours4 = channel1->crecording.F().length_in_seconds() / 3600. * 4;
+		float	hours4 = channel1->crecording.F().recording_time() / 3600. * 4;
 		for ( size_t i = 1; i < hours4; ++i ) {
 			unsigned tick_pos = (float)i / hours4 * wd;
 			cairo_move_to( cr, tick_pos, 0);
diff --git a/src/ui/sf/montage_cb.cc b/src/ui/sf/montage_cb.cc
index a5ae6eb..afa1fbb 100644
--- a/src/ui/sf/montage_cb.cc
+++ b/src/ui/sf/montage_cb.cc
@@ -154,7 +154,7 @@ daSFMontage_button_press_event_cb( GtkWidget *wid, GdkEventButton *event, gpoint
 			Ch->signal_display_scale =
 				agh::alg::calibrate_display_scale(
 					Ch->draw_filtered_signal ? Ch->signal_filtered : Ch->signal_original,
-					SF.vpagesize() * Ch->samplerate() * min (Ch->crecording.F().pages(), (size_t)10),
+					SF.vpagesize() * Ch->samplerate() * min (Ch->crecording.total_pages(), (size_t)10),
 					SF.interchannel_gap / 2);
 			if ( event->state & GDK_CONTROL_MASK )
 				for ( auto& H : SF.channels )
diff --git a/src/ui/sf/sf.cc b/src/ui/sf/sf.cc
index 13bca70..27478fc 100644
--- a/src/ui/sf/sf.cc
+++ b/src/ui/sf/sf.cc
@@ -154,7 +154,7 @@ SScoringFacility (agh::CSubject& J,
 			h.signal_display_scale =
 				agh::alg::calibrate_display_scale(
 					h.signal_filtered,
-					vpagesize() * h.samplerate() * min (h.crecording.F().pages(), (size_t)10),
+					vpagesize() * h.samplerate() * min (h.crecording.total_pages(), (size_t)10),
 					interchannel_gap / 2);
 		if ( h.type == sigfile::SChannel::TType::eeg ) {
 		      // calibrate profile display scales

-- 
Sleep experiment manager



More information about the debian-med-commit mailing list