The following commit has been merged in the master branch:
commit 26716231d8817e5b42bdc1bb5757e05dd537ab97
Author: Andrei Zavada <[email protected]>
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 <[email protected]>
  * 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

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

Reply via email to