The following commit has been merged in the master branch:
commit e59fec066d5fbde2e51c75435f172a4ada47c104
Author: Andrei Zavada <[email protected]>
Date:   Fri Jan 4 18:36:03 2013 +0200

    split sf::draw_overlays into own file, and phasic events stubs

diff --git a/src/metrics/phasic-events.hh b/src/metrics/phasic-events.hh
index f71e0ab..172ecce 100644
--- a/src/metrics/phasic-events.hh
+++ b/src/metrics/phasic-events.hh
@@ -29,6 +29,11 @@ using namespace std;
 namespace metrics {
 namespace phasic {
 
+enum TEventTypes {
+       spindle,
+       K_complex
+};
+
 template <typename T>
 list<agh::alg::SSpan<double>>
 detect_spindles( const sigfile::SNamedChannel<T>&);
diff --git a/src/ui/mw/mw-loadsave.cc b/src/ui/mw/mw-loadsave.cc
index cb67060..4ae10d9 100644
--- a/src/ui/mw/mw-loadsave.cc
+++ b/src/ui/mw/mw-loadsave.cc
@@ -47,6 +47,10 @@ saving_colors()
                        {"SFProfilePSD",  
SExpDesignUI::TColour::sf_profile_psd},
                        {"SFProfileSWU",  
SExpDesignUI::TColour::sf_profile_swu},
                        {"SFProfileMC",   SExpDesignUI::TColour::sf_profile_mc 
},
+
+                       {"SFPhasicSpindle",  
SExpDesignUI::TColour::sf_phasic_spindle},
+                       {"SFPhasicKComplex", 
SExpDesignUI::TColour::sf_phasic_Kcomplex},
+
                        {"SFEMG",         SExpDesignUI::TColour::sf_emg        
},
                        {"SFHypnogram",   SExpDesignUI::TColour::sf_hypnogram  
},
                        {"SFArtifacts",   SExpDesignUI::TColour::sf_artifact   
},
diff --git a/src/ui/mw/mw-widgets.hh b/src/ui/mw/mw-widgets.hh
index 86b02be..f7a0b69 100644
--- a/src/ui/mw/mw-widgets.hh
+++ b/src/ui/mw/mw-widgets.hh
@@ -345,6 +345,7 @@ struct SExpDesignUIWidgets {
                sf_annotations,
                sf_selection,
                sf_profile_psd, sf_profile_mc, sf_profile_swu,
+               sf_phasic_spindle, sf_phasic_Kcomplex,
                sf_hypnogram,
                sf_cursor,
                sf_emg,
diff --git a/src/ui/sf/Makefile.am b/src/ui/sf/Makefile.am
index 0e17eee..9c47b04 100644
--- a/src/ui/sf/Makefile.am
+++ b/src/ui/sf/Makefile.am
@@ -19,11 +19,13 @@ liba_a_SOURCES := \
        sf-ica.cc \
        sf-ica_cb.cc \
        sf-montage.cc \
+       sf-montage-overlays.cc \
        sf-montage_cb.cc \
        sf-patterns.cc \
        sf-patterns_cb.cc \
        sf-phasediff.cc \
        sf-phasediff_cb.cc \
+       sf-phasic-events.cc \
        sf-widgets.hh \
        sf.cc \
        sf.hh \
diff --git a/src/ui/sf/sf-channel.cc b/src/ui/sf/sf-channel.cc
index ea2f233..5e43bc2 100644
--- a/src/ui/sf/sf-channel.cc
+++ b/src/ui/sf/sf-channel.cc
@@ -53,6 +53,8 @@ SChannel( agh::CRecording& r,
        draw_selection_course (false),
        draw_selection_envelope (true),
        draw_selection_dzcdf (false),
+       draw_phasic_spindle (true),
+       draw_phasic_Kcomplex (true),
        apply_reconstituted (false),
        config_keys_b ({
                confval::SValidator<bool>( string(1, seq) + ".hidden",          
        &hidden),
@@ -65,6 +67,8 @@ SChannel( agh::CRecording& r,
                confval::SValidator<bool>( string(1, seq) + ".draw_bands",      
        &draw_bands),
                confval::SValidator<bool>( string(1, seq) + ".draw_spectrum",   
        &draw_spectrum),
                confval::SValidator<bool>( string(1, seq) + ".draw_mc",         
        &draw_mc),
+               confval::SValidator<bool>( string(1, seq) + 
".draw_phasic_spindle",     &draw_phasic_spindle),
+               confval::SValidator<bool>( string(1, seq) + 
".draw_phasic_Kcomplex",    &draw_phasic_Kcomplex),
                confval::SValidator<bool>( string(1, seq) + 
".autoscale_profile",       &autoscale_profile),
                confval::SValidator<bool>( string(1, seq) + ".resample_signal", 
        &resample_signal),
                confval::SValidator<bool>( string(1, seq) + ".resample_power",  
        &resample_power),
@@ -136,6 +140,10 @@ SChannel( agh::CRecording& r,
                emg_profile = env_u - env_l;
        }
 
+      // prevent exceptions from phasic_events.at
+       phasic_events[metrics::phasic::TEventTypes::spindle].clear();
+       phasic_events[metrics::phasic::TEventTypes::K_complex].clear();
+
       // let it be so to avoid libconfig::readFile throwing exceptions
        psd.display_scale = mc.display_scale =
                emg_display_scale = DBL_MIN;
diff --git a/src/ui/sf/sf-montage-overlays.cc b/src/ui/sf/sf-montage-overlays.cc
new file mode 100644
index 0000000..e03f4c2
--- /dev/null
+++ b/src/ui/sf/sf-montage-overlays.cc
@@ -0,0 +1,373 @@
+// ;-*-C++-*-
+/*
+ *       File name:  ui/sf/sf-montage-overlays.cc
+ *         Project:  Aghermann
+ *          Author:  Andrei Zavada <[email protected]>
+ * Initial version:  2013-01-04
+ *
+ *         Purpose:  scoring facility: montage drawing area (profile overlays)
+ *
+ *         License:  GPL
+ */
+
+#include <cairo/cairo-svg.h>
+
+#include "common/lang.hh"
+#include "ui/misc.hh"
+#include "sf.hh"
+
+using namespace std;
+
+
+void
+aghui::SScoringFacility::SChannel::
+draw_overlays( cairo_t* cr,
+              int wd, float zeroy) const
+{
+       float   pbot = zeroy + _p.interchannel_gap / 2.2,
+               ptop = zeroy - _p.interchannel_gap / 2.2;
+       bool    overlay = false;
+
+       // PSD profile
+       if ( _p.mode == TMode::scoring and
+            draw_psd and type == sigfile::SChannel::TType::eeg ) {
+               overlay = true;
+
+               cairo_set_line_width( cr, 1.);
+               cairo_set_font_size( cr, 10);
+               guint i;
+
+               if ( draw_bands ) {
+                       for ( size_t b = metrics::psd::TBand::delta; b <= 
psd.uppermost_band; ++b ) {
+                               auto& P = psd.course_in_bands[b];
+                               
_p._p.CwB[SExpDesignUI::band2colour((metrics::psd::TBand)b)].set_source_rgba( 
cr, .5);
+                               double zero = 0.5 / P.size() * _p.da_wd;
+                               cairo_move_to( cr, zero,
+                                              - P[0] * psd.display_scale + 
pbot);
+                               for ( i = 1; i < P.size(); ++i )
+                                       cairo_line_to( cr, ((double)i+0.5) / 
P.size() * _p.da_wd,
+                                                      - P[i] * 
psd.display_scale + pbot);
+                               if ( b == psd.focused_band ) {
+                                       cairo_line_to( cr, _p.da_wd, pbot);
+                                       cairo_line_to( cr,     zero, pbot);
+                                       cairo_fill( cr);
+                               }
+                               cairo_stroke( cr);
+
+                               if ( b == psd.focused_band ) {
+                                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+                                       snprintf_buf( "%s %g–%g",
+                                                     
_p._p.FreqBandNames[(unsigned)b],
+                                                     
_p._p.freq_bands[(unsigned)b][0], _p._p.freq_bands[(unsigned)b][1]);
+                               } else {
+                                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+                                       snprintf_buf( "%s", 
_p._p.FreqBandNames[(unsigned)b]);
+                               }
+                               cairo_move_to( cr, _p.da_wd - 170,
+                                              ptop + psd.uppermost_band*12 - 
12*(unsigned)b + 12);
+                               cairo_show_text( cr, __buf__);
+                               cairo_stroke( cr);
+                       }
+               } else {
+                       
_p._p.CwB[SExpDesignUI::TColour::sf_profile_psd].set_source_rgba( cr, .5);
+                       double zero = 0.5 / psd.course.size() * _p.da_wd;
+                       cairo_move_to( cr, zero,
+                                      psd.course[0]);
+                       for ( i = 0; i < psd.course.size(); ++i )
+                               cairo_line_to( cr, ((double)i+.5) / 
psd.course.size() * _p.da_wd,
+                                              - psd.course[i] * 
psd.display_scale + pbot);
+                       cairo_line_to( cr, _p.da_wd, pbot);
+                       cairo_line_to( cr,     zero, pbot);
+                       cairo_fill( cr);
+                       cairo_stroke( cr);
+
+                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+                       snprintf_buf( "%g–%g Hz", psd.from, psd.upto);
+                       cairo_move_to( cr, _p.da_wd - 170, pbot - 15);
+                       cairo_show_text( cr, __buf__);
+                       cairo_stroke( cr);
+               }
+
+             // scale
+               {
+                       cairo_set_source_rgb( cr, 0., 0., 0.);
+                       cairo_set_line_width( cr, 1.5);
+                       double dpuf =
+                               agh::alg::sensible_scale_reduction_factor(
+                                       1e6 * psd.display_scale, 
_p.interchannel_gap/2);
+                       int x = 30;
+                       cairo_move_to( cr, x, pbot - 5);
+                       cairo_rel_line_to( cr, 0, -dpuf * (1e6 * 
psd.display_scale));
+                       cairo_stroke( cr);
+
+                       cairo_set_font_size( cr, 9);
+                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+                       cairo_move_to( cr, x + 5, pbot - 20);
+                       snprintf_buf( "%g uV2", dpuf);
+                       cairo_show_text( cr, __buf__);
+                       cairo_stroke( cr);
+               }
+
+               if ( draw_spectrum and _p.pagesize_is_right() ) {
+                       guint   gx = 120,
+                               gy = ptop + 25,
+                               gh = min( 60.f, pbot - ptop - 5),
+                               gw  = 80;
+                       size_t  m;
+
+                       cairo_set_source_rgba( cr, 1., 1., 1., .8);
+                       cairo_rectangle( cr, gx-15, gy-5, gw+15+5, gh+5+5);
+                       cairo_fill( cr);
+
+                       // grid lines
+                       
_p._p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgba( cr, .1);
+                       cairo_set_line_width( cr, .3);
+                       for ( size_t i = 1; i < last_spectrum_bin; ++i ) {
+                               cairo_move_to( cr, gx + 
(float)i/last_spectrum_bin * gw, gy);
+                               cairo_rel_line_to( cr, 0, gh);
+                       }
+                       cairo_stroke( cr);
+
+                       // spectrum
+                       
_p._p.CwB[SExpDesignUI::TColour::sf_ticks].set_source_rgba( cr, .8);
+                       cairo_set_line_width( cr, 2);
+                       float factor = psd.display_scale / 
crecording.psd_profile.Pp.binsize;
+                       cairo_move_to( cr,
+                                      gx, gy + gh - (2 + spectrum[0] * 
factor));
+                       for ( m = 1; m < last_spectrum_bin; ++m ) {
+                               cairo_line_to( cr,
+                                              gx + (float)m / 
last_spectrum_bin * gw,
+                                              gy + gh - spectrum[m] * factor);
+                       }
+                       cairo_stroke( cr);
+
+                       // axes
+                       
_p._p.CwB[SExpDesignUI::TColour::sf_ticks].set_source_rgba( cr, .5);
+                       cairo_set_line_width( cr, .5);
+                       cairo_move_to( cr, gx, gy);
+                       cairo_rel_line_to( cr, 0, gh);
+                       cairo_rel_line_to( cr, gw, 0);
+
+                       // y ticks
+                       m = 0;
+                       while ( (++m * 1e6) < gh / factor ) {
+                               cairo_move_to( cr, gx-3,  gy + gh - (2 + 
(float)m*1e6 * factor));
+                               cairo_rel_line_to( cr, 3, 0);
+                       }
+                       cairo_stroke( cr);
+
+                       // labels
+                       cairo_text_extents_t extents;
+                       
_p._p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgba( cr);
+                       cairo_set_font_size( cr, 8);
+
+                       snprintf_buf( "%g Hz",
+                                     last_spectrum_bin * 
crecording.psd_profile.Pp.binsize);
+//                                   draw_spectrum_absolute ? 'A' : 'R');
+                       cairo_text_extents( cr, __buf__, &extents);
+                       cairo_move_to( cr,
+                                      gx + gw - extents.width - 5,
+                                      gy + 4);
+                       cairo_show_text( cr, __buf__);
+                       cairo_stroke( cr);
+               }
+       }
+
+       if ( _p.mode == TMode::scoring and
+            draw_mc and type == sigfile::SChannel::TType::eeg ) {
+               overlay = true;
+
+               cairo_set_line_width( cr, 1.);
+               cairo_set_font_size( cr, 10);
+               guint i;
+
+               
_p._p.CwB[SExpDesignUI::TColour::sf_profile_mc].set_source_rgba( cr, .5);
+               double zero = 0.5 / mc.course.size() * _p.da_wd;
+               cairo_move_to( cr, zero,
+                              mc.course[0]);
+               for ( i = 0; i < mc.course.size(); ++i )
+                       cairo_line_to( cr, ((double)i+.5) / mc.course.size() * 
_p.da_wd,
+                                      - mc.course[i] * mc.display_scale + 
pbot);
+               cairo_line_to( cr, _p.da_wd, pbot);
+               cairo_line_to( cr,     zero, pbot);
+               cairo_fill( cr);
+               cairo_stroke( cr);
+
+               cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_NORMAL, 
CAIRO_FONT_WEIGHT_BOLD);
+               snprintf_buf( "f0:%g", mc.f0);
+               cairo_move_to( cr, _p.da_wd - 70, pbot - 30);
+               cairo_show_text( cr, __buf__);
+               cairo_stroke( cr);
+
+             // scale
+               {
+                       cairo_set_source_rgb( cr, 0., 0., 0.);
+                       cairo_set_line_width( cr, 1.5);
+                       double dpuf =
+                               agh::alg::sensible_scale_reduction_factor(
+                                       mc.display_scale, 
_p.interchannel_gap/2);
+                       int x = 80;
+                       cairo_move_to( cr, x, pbot - 5);
+                       cairo_rel_line_to( cr, 0, -dpuf * mc.display_scale);
+                       cairo_stroke( cr);
+
+                       cairo_set_font_size( cr, 9);
+                       //cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+                       cairo_move_to( cr, x + 5, pbot - 20);
+                       snprintf_buf( "%g a.u.", dpuf);
+                       cairo_show_text( cr, __buf__);
+                       cairo_stroke( cr);
+               }
+
+       }
+
+       if ( _p.mode == TMode::scoring and
+            draw_swu and type == sigfile::SChannel::TType::eeg ) {
+               overlay = true;
+
+               cairo_set_line_width( cr, 1.);
+               cairo_set_font_size( cr, 10);
+               guint i;
+
+               
_p._p.CwB[SExpDesignUI::TColour::sf_profile_swu].set_source_rgba( cr, .5);
+               double zero = 0.5 / swu.course.size() * _p.da_wd;
+               cairo_move_to( cr, zero,
+                              swu.course[0]);
+               for ( i = 0; i < swu.course.size(); ++i )
+                       cairo_line_to( cr, ((double)i+.5) / swu.course.size() * 
_p.da_wd,
+                                      - swu.course[i] * swu.display_scale + 
pbot);
+               cairo_line_to( cr, _p.da_wd, pbot);
+               cairo_line_to( cr,     zero, pbot);
+               cairo_fill( cr);
+               cairo_stroke( cr);
+
+             // scale
+               {
+                       cairo_set_source_rgb( cr, 0., 0., 0.);
+                       cairo_set_line_width( cr, 1.5);
+                       double dpuf =
+                               agh::alg::sensible_scale_reduction_factor(
+                                       swu.display_scale, 
_p.interchannel_gap/2);
+                       int x = 140;
+                       cairo_move_to( cr, x, pbot - 5);
+                       cairo_rel_line_to( cr, 0, -dpuf * swu.display_scale);
+                       cairo_stroke( cr);
+
+                       cairo_set_font_size( cr, 9);
+                       //cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+                       cairo_move_to( cr, x + 5, pbot - 20);
+                       snprintf_buf( "%g a.u.", dpuf);
+                       cairo_show_text( cr, __buf__);
+                       cairo_stroke( cr);
+               }
+
+       }
+
+      // phasic events
+       if ( _p.mode == TMode::scoring and
+            draw_phasic_spindle and
+            not 
phasic_events.at(metrics::phasic::TEventTypes::spindle).empty() ) {
+               
+       }
+       if ( _p.mode == TMode::scoring and
+            draw_phasic_Kcomplex and
+            not 
phasic_events.at(metrics::phasic::TEventTypes::K_complex).empty() ) {
+               
+       }
+
+      // EMG profile
+       if ( _p.mode == TMode::scoring and draw_emg and
+            type == sigfile::SChannel::TType::emg ) {
+               overlay = true;
+
+               _p._p.CwB[SExpDesignUI::TColour::sf_emg].set_source_rgba( cr);
+               cairo_set_line_width( cr, .3);
+               double dps = (double)emg_profile.size() / _p.da_wd;
+               cairo_move_to( cr, 0., pbot - EMGProfileHeight/2);
+               size_t i = 0;
+               for ( ; i < emg_profile.size(); ++i )
+                       cairo_line_to( cr, i / dps,
+                                      pbot - EMGProfileHeight/2 - 
emg_profile[i] * signal_display_scale/2);
+               for ( --i; i > 0; --i )
+                       cairo_line_to( cr, i / dps,
+                                      pbot - EMGProfileHeight/2 + 
emg_profile[i] * signal_display_scale/2);
+               cairo_fill( cr);
+               cairo_stroke( cr);
+       }
+
+       if ( overlay )
+               _p._draw_hour_ticks( cr, zeroy, pbot);
+
+      // crosshair (is drawn once in SScoringFacility::draw_montage), voltage 
at
+       if ( _p.draw_crosshair ) {
+               cairo_set_font_size( cr, 10);
+               cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_NORMAL, 
CAIRO_FONT_WEIGHT_BOLD);
+               _p._p.CwB[SExpDesignUI::TColour::sf_cursor].set_source_rgb( cr);
+               if ( this == &_p.channels.front() )
+                       snprintf_buf( "%4.2f (%5.2fs)",
+                                     (draw_filtered_signal ? signal_filtered : 
signal_original)
+                                     [ (size_t)(_p.crosshair_at_time * 
samplerate()) ],
+                                     _p.crosshair_at_time - 
_p.cur_xvpage_start() - _p.skirting_run_per1 * _p.vpagesize());
+               else
+                       snprintf_buf( "%4.2f",
+                                     (draw_filtered_signal ? signal_filtered : 
signal_original)
+                                     [ (size_t)(_p.crosshair_at_time * 
samplerate()) ]);
+
+               cairo_move_to( cr, _p.crosshair_at+2, ptop + 22);
+               cairo_show_text( cr, __buf__);
+               cairo_stroke( cr);
+       }
+
+      // samples per pixel
+       if ( _p.mode == TMode::scoring and resample_signal ) {
+               _p._p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgb( cr);
+               cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_ITALIC, 
CAIRO_FONT_WEIGHT_BOLD);
+               cairo_set_font_size( cr, 8);
+               cairo_move_to( cr, _p.da_wd-40, ptop + 11);
+               snprintf_buf( "%4.2f spp", spp());
+               cairo_show_text( cr, __buf__);
+               cairo_stroke( cr);
+       }
+}
+
+
+
+
+
+
+void
+aghui::SScoringFacility::
+_draw_hour_ticks( cairo_t *cr, int htop, int hbot, bool with_cursor)
+{
+       cairo_set_line_width( cr, 1);
+       cairo_set_font_size( cr, 10);
+       float   hours4 = (float)total_pages() * pagesize() / 3600 * 4;
+       for ( size_t i = 1; i < hours4; ++i ) {
+               guint tick_pos = (float)i / hours4 * da_wd;
+               _p.CwB[SExpDesignUI::TColour::sf_ticks].set_source_rgba( cr);
+               cairo_move_to( cr, tick_pos, hbot);
+               cairo_rel_line_to( cr, 0, -((i%4 == 0) ? 20 : (i%2 == 0) ? 12 : 
5));
+               if ( i % 4 == 0 ) {
+                       snprintf_buf( "%2zuh", i/4);
+                       
_p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgba( cr);
+                       cairo_move_to( cr, tick_pos+5, hbot - 2);
+                       cairo_show_text( cr, __buf__);
+               }
+       }
+       cairo_stroke( cr);
+
+       if ( with_cursor ) {
+               _p.CwB[SExpDesignUI::TColour::sf_cursor].set_source_rgba( cr);
+               cairo_rectangle( cr,
+                                (double)cur_vpage() / total_vpages() * da_wd, 
htop,
+                                max( .5, 1. / total_vpages() * da_wd), hbot - 
htop);
+               cairo_fill( cr);
+               cairo_stroke( cr);
+       }
+}
+
+
+
+
+// eof
+
diff --git a/src/ui/sf/sf-montage.cc b/src/ui/sf/sf-montage.cc
index d9a75b2..6931ff9 100644
--- a/src/ui/sf/sf-montage.cc
+++ b/src/ui/sf/sf-montage.cc
@@ -17,8 +17,6 @@
 #include "sf.hh"
 
 using namespace std;
-using namespace aghui;
-
 
 inline namespace {
 
@@ -479,6 +477,39 @@ draw_page( cairo_t *cr,
                }
        }
 
+      // phasic events
+       if ( _p.mode == TMode::scoring and
+            draw_phasic_spindle and
+            not 
phasic_events.at(metrics::phasic::TEventTypes::spindle).empty() ) {
+               cairo_pattern_t *cp = cairo_pattern_create_linear( 0., ptop+10, 
0., ptop+30);
+               for ( auto &cA : 
phasic_events.at(metrics::phasic::TEventTypes::spindle) ) {
+                       agh::alg::SSpan<size_t> A = cA * samplerate();
+                       if ( agh::alg::overlap( (int)A.a, (int)A.z, cvpa, cvpe) 
) {
+                               
_p._p.CwB[SExpDesignUI::TColour::sf_phasic_spindle].pattern_add_color_stop_rgba(
 cp, 0., 1.);
+                               
_p._p.CwB[SExpDesignUI::TColour::sf_phasic_spindle].pattern_add_color_stop_rgba(
 cp, .1, 0.3);
+                               
_p._p.CwB[SExpDesignUI::TColour::sf_phasic_spindle].pattern_add_color_stop_rgba(
 cp, 1., 0.);
+                               cairo_set_source( cr, cp);
+
+                               int     aa = (int)A.a - cvpa,
+                                       ae = (int)A.z - cvpa;
+                               if ( aa < 0 )    aa = 0;
+                               if ( ae > evpz ) ae = evpz;
+                               cairo_rectangle( cr,
+                                                (float)(aa % evpz) / evpz * 
wd, ptop+10,
+                                                (float)(ae - aa) / evpz * wd, 
ptop+30);
+                               cairo_fill( cr);
+                               cairo_stroke( cr);
+                       } else if ( (int)A.a > cvpe )  // no more artifacts up 
to and on current page
+                               break;
+               }
+               cairo_pattern_destroy( cp);
+       }
+       if ( _p.mode == TMode::scoring and
+            draw_phasic_Kcomplex and
+            not 
phasic_events.at(metrics::phasic::TEventTypes::K_complex).empty() ) {
+               
+       }
+
       // annotations
        {
                auto& Aa = crecording.F().annotations(name);
@@ -584,337 +615,18 @@ draw_page( cairo_t *cr,
 
 
 void
-aghui::SScoringFacility::SChannel::
-draw_overlays( cairo_t* cr,
-              int wd, float zeroy) const
-{
-       float   pbot = zeroy + _p.interchannel_gap / 2.2,
-               ptop = zeroy - _p.interchannel_gap / 2.2;
-       bool    overlay = false;
-
-       // PSD profile
-       if ( _p.mode == TMode::scoring and
-            draw_psd and type == sigfile::SChannel::TType::eeg ) {
-               overlay = true;
-
-               cairo_set_line_width( cr, 1.);
-               cairo_set_font_size( cr, 10);
-               guint i;
-
-               if ( draw_bands ) {
-                       for ( size_t b = metrics::psd::TBand::delta; b <= 
psd.uppermost_band; ++b ) {
-                               auto& P = psd.course_in_bands[b];
-                               
_p._p.CwB[SExpDesignUI::band2colour((metrics::psd::TBand)b)].set_source_rgba( 
cr, .5);
-                               double zero = 0.5 / P.size() * _p.da_wd;
-                               cairo_move_to( cr, zero,
-                                              - P[0] * psd.display_scale + 
pbot);
-                               for ( i = 1; i < P.size(); ++i )
-                                       cairo_line_to( cr, ((double)i+0.5) / 
P.size() * _p.da_wd,
-                                                      - P[i] * 
psd.display_scale + pbot);
-                               if ( b == psd.focused_band ) {
-                                       cairo_line_to( cr, _p.da_wd, pbot);
-                                       cairo_line_to( cr,     zero, pbot);
-                                       cairo_fill( cr);
-                               }
-                               cairo_stroke( cr);
-
-                               if ( b == psd.focused_band ) {
-                                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-                                       snprintf_buf( "%s %g–%g",
-                                                     
_p._p.FreqBandNames[(unsigned)b],
-                                                     
_p._p.freq_bands[(unsigned)b][0], _p._p.freq_bands[(unsigned)b][1]);
-                               } else {
-                                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-                                       snprintf_buf( "%s", 
_p._p.FreqBandNames[(unsigned)b]);
-                               }
-                               cairo_move_to( cr, _p.da_wd - 170,
-                                              ptop + psd.uppermost_band*12 - 
12*(unsigned)b + 12);
-                               cairo_show_text( cr, __buf__);
-                               cairo_stroke( cr);
-                       }
-               } else {
-                       
_p._p.CwB[SExpDesignUI::TColour::sf_profile_psd].set_source_rgba( cr, .5);
-                       double zero = 0.5 / psd.course.size() * _p.da_wd;
-                       cairo_move_to( cr, zero,
-                                      psd.course[0]);
-                       for ( i = 0; i < psd.course.size(); ++i )
-                               cairo_line_to( cr, ((double)i+.5) / 
psd.course.size() * _p.da_wd,
-                                              - psd.course[i] * 
psd.display_scale + pbot);
-                       cairo_line_to( cr, _p.da_wd, pbot);
-                       cairo_line_to( cr,     zero, pbot);
-                       cairo_fill( cr);
-                       cairo_stroke( cr);
-
-                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-                       snprintf_buf( "%g–%g Hz", psd.from, psd.upto);
-                       cairo_move_to( cr, _p.da_wd - 170, pbot - 15);
-                       cairo_show_text( cr, __buf__);
-                       cairo_stroke( cr);
-               }
-
-             // scale
-               {
-                       cairo_set_source_rgb( cr, 0., 0., 0.);
-                       cairo_set_line_width( cr, 1.5);
-                       double dpuf =
-                               agh::alg::sensible_scale_reduction_factor(
-                                       1e6 * psd.display_scale, 
_p.interchannel_gap/2);
-                       int x = 30;
-                       cairo_move_to( cr, x, pbot - 5);
-                       cairo_rel_line_to( cr, 0, -dpuf * (1e6 * 
psd.display_scale));
-                       cairo_stroke( cr);
-
-                       cairo_set_font_size( cr, 9);
-                       cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-                       cairo_move_to( cr, x + 5, pbot - 20);
-                       snprintf_buf( "%g uV2", dpuf);
-                       cairo_show_text( cr, __buf__);
-                       cairo_stroke( cr);
-               }
-
-               if ( draw_spectrum and _p.pagesize_is_right() ) {
-                       guint   gx = 120,
-                               gy = ptop + 25,
-                               gh = min( 60.f, pbot - ptop - 5),
-                               gw  = 80;
-                       size_t  m;
-
-                       cairo_set_source_rgba( cr, 1., 1., 1., .8);
-                       cairo_rectangle( cr, gx-15, gy-5, gw+15+5, gh+5+5);
-                       cairo_fill( cr);
-
-                       // grid lines
-                       
_p._p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgba( cr, .1);
-                       cairo_set_line_width( cr, .3);
-                       for ( size_t i = 1; i < last_spectrum_bin; ++i ) {
-                               cairo_move_to( cr, gx + 
(float)i/last_spectrum_bin * gw, gy);
-                               cairo_rel_line_to( cr, 0, gh);
-                       }
-                       cairo_stroke( cr);
-
-                       // spectrum
-                       
_p._p.CwB[SExpDesignUI::TColour::sf_ticks].set_source_rgba( cr, .8);
-                       cairo_set_line_width( cr, 2);
-                       float factor = psd.display_scale / 
crecording.psd_profile.Pp.binsize;
-                       cairo_move_to( cr,
-                                      gx, gy + gh - (2 + spectrum[0] * 
factor));
-                       for ( m = 1; m < last_spectrum_bin; ++m ) {
-                               cairo_line_to( cr,
-                                              gx + (float)m / 
last_spectrum_bin * gw,
-                                              gy + gh - spectrum[m] * factor);
-                       }
-                       cairo_stroke( cr);
-
-                       // axes
-                       
_p._p.CwB[SExpDesignUI::TColour::sf_ticks].set_source_rgba( cr, .5);
-                       cairo_set_line_width( cr, .5);
-                       cairo_move_to( cr, gx, gy);
-                       cairo_rel_line_to( cr, 0, gh);
-                       cairo_rel_line_to( cr, gw, 0);
-
-                       // y ticks
-                       m = 0;
-                       while ( (++m * 1e6) < gh / factor ) {
-                               cairo_move_to( cr, gx-3,  gy + gh - (2 + 
(float)m*1e6 * factor));
-                               cairo_rel_line_to( cr, 3, 0);
-                       }
-                       cairo_stroke( cr);
-
-                       // labels
-                       cairo_text_extents_t extents;
-                       
_p._p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgba( cr);
-                       cairo_set_font_size( cr, 8);
-
-                       snprintf_buf( "%g Hz",
-                                     last_spectrum_bin * 
crecording.psd_profile.Pp.binsize);
-//                                   draw_spectrum_absolute ? 'A' : 'R');
-                       cairo_text_extents( cr, __buf__, &extents);
-                       cairo_move_to( cr,
-                                      gx + gw - extents.width - 5,
-                                      gy + 4);
-                       cairo_show_text( cr, __buf__);
-                       cairo_stroke( cr);
-               }
-       }
-
-       if ( _p.mode == TMode::scoring and
-            draw_mc and type == sigfile::SChannel::TType::eeg ) {
-               overlay = true;
-
-               cairo_set_line_width( cr, 1.);
-               cairo_set_font_size( cr, 10);
-               guint i;
-
-               
_p._p.CwB[SExpDesignUI::TColour::sf_profile_mc].set_source_rgba( cr, .5);
-               double zero = 0.5 / mc.course.size() * _p.da_wd;
-               cairo_move_to( cr, zero,
-                              mc.course[0]);
-               for ( i = 0; i < mc.course.size(); ++i )
-                       cairo_line_to( cr, ((double)i+.5) / mc.course.size() * 
_p.da_wd,
-                                      - mc.course[i] * mc.display_scale + 
pbot);
-               cairo_line_to( cr, _p.da_wd, pbot);
-               cairo_line_to( cr,     zero, pbot);
-               cairo_fill( cr);
-               cairo_stroke( cr);
-
-               cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_NORMAL, 
CAIRO_FONT_WEIGHT_BOLD);
-               snprintf_buf( "f0:%g", mc.f0);
-               cairo_move_to( cr, _p.da_wd - 70, pbot - 30);
-               cairo_show_text( cr, __buf__);
-               cairo_stroke( cr);
-
-             // scale
-               {
-                       cairo_set_source_rgb( cr, 0., 0., 0.);
-                       cairo_set_line_width( cr, 1.5);
-                       double dpuf =
-                               agh::alg::sensible_scale_reduction_factor(
-                                       mc.display_scale, 
_p.interchannel_gap/2);
-                       int x = 80;
-                       cairo_move_to( cr, x, pbot - 5);
-                       cairo_rel_line_to( cr, 0, -dpuf * mc.display_scale);
-                       cairo_stroke( cr);
-
-                       cairo_set_font_size( cr, 9);
-                       //cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-                       cairo_move_to( cr, x + 5, pbot - 20);
-                       snprintf_buf( "%g a.u.", dpuf);
-                       cairo_show_text( cr, __buf__);
-                       cairo_stroke( cr);
-               }
-
-       }
-
-       if ( _p.mode == TMode::scoring and
-            draw_swu and type == sigfile::SChannel::TType::eeg ) {
-               overlay = true;
-
-               cairo_set_line_width( cr, 1.);
-               cairo_set_font_size( cr, 10);
-               guint i;
-
-               
_p._p.CwB[SExpDesignUI::TColour::sf_profile_swu].set_source_rgba( cr, .5);
-               double zero = 0.5 / swu.course.size() * _p.da_wd;
-               cairo_move_to( cr, zero,
-                              swu.course[0]);
-               for ( i = 0; i < swu.course.size(); ++i )
-                       cairo_line_to( cr, ((double)i+.5) / swu.course.size() * 
_p.da_wd,
-                                      - swu.course[i] * swu.display_scale + 
pbot);
-               cairo_line_to( cr, _p.da_wd, pbot);
-               cairo_line_to( cr,     zero, pbot);
-               cairo_fill( cr);
-               cairo_stroke( cr);
-
-             // scale
-               {
-                       cairo_set_source_rgb( cr, 0., 0., 0.);
-                       cairo_set_line_width( cr, 1.5);
-                       double dpuf =
-                               agh::alg::sensible_scale_reduction_factor(
-                                       swu.display_scale, 
_p.interchannel_gap/2);
-                       int x = 140;
-                       cairo_move_to( cr, x, pbot - 5);
-                       cairo_rel_line_to( cr, 0, -dpuf * swu.display_scale);
-                       cairo_stroke( cr);
-
-                       cairo_set_font_size( cr, 9);
-                       //cairo_select_font_face( cr, "sans", 
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-                       cairo_move_to( cr, x + 5, pbot - 20);
-                       snprintf_buf( "%g a.u.", dpuf);
-                       cairo_show_text( cr, __buf__);
-                       cairo_stroke( cr);
-               }
-
-       }
-
-      // EMG profile
-       if ( _p.mode == TMode::scoring and draw_emg and
-            type == sigfile::SChannel::TType::emg ) {
-               overlay = true;
-
-               _p._p.CwB[SExpDesignUI::TColour::sf_emg].set_source_rgba( cr);
-               cairo_set_line_width( cr, .3);
-               double dps = (double)emg_profile.size() / _p.da_wd;
-               cairo_move_to( cr, 0., pbot - EMGProfileHeight/2);
-               size_t i = 0;
-               for ( ; i < emg_profile.size(); ++i )
-                       cairo_line_to( cr, i / dps,
-                                      pbot - EMGProfileHeight/2 - 
emg_profile[i] * signal_display_scale/2);
-               for ( --i; i > 0; --i )
-                       cairo_line_to( cr, i / dps,
-                                      pbot - EMGProfileHeight/2 + 
emg_profile[i] * signal_display_scale/2);
-               cairo_fill( cr);
-               cairo_stroke( cr);
-       }
-
-       if ( overlay )
-               _p._draw_hour_ticks( cr, zeroy, pbot);
-
-      // crosshair (is drawn once in SScoringFacility::draw_montage), voltage 
at
-       if ( _p.draw_crosshair ) {
-               cairo_set_font_size( cr, 10);
-               cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_NORMAL, 
CAIRO_FONT_WEIGHT_BOLD);
-               _p._p.CwB[SExpDesignUI::TColour::sf_cursor].set_source_rgb( cr);
-               if ( this == &_p.channels.front() )
-                       snprintf_buf( "%4.2f (%5.2fs)",
-                                     (draw_filtered_signal ? signal_filtered : 
signal_original)
-                                     [ (size_t)(_p.crosshair_at_time * 
samplerate()) ],
-                                     _p.crosshair_at_time - 
_p.cur_xvpage_start() - _p.skirting_run_per1 * _p.vpagesize());
-               else
-                       snprintf_buf( "%4.2f",
-                                     (draw_filtered_signal ? signal_filtered : 
signal_original)
-                                     [ (size_t)(_p.crosshair_at_time * 
samplerate()) ]);
-
-               cairo_move_to( cr, _p.crosshair_at+2, ptop + 22);
-               cairo_show_text( cr, __buf__);
-               cairo_stroke( cr);
-       }
-
-      // samples per pixel
-       if ( _p.mode == TMode::scoring and resample_signal ) {
-               _p._p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgb( cr);
-               cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_ITALIC, 
CAIRO_FONT_WEIGHT_BOLD);
-               cairo_set_font_size( cr, 8);
-               cairo_move_to( cr, _p.da_wd-40, ptop + 11);
-               snprintf_buf( "%4.2f spp", spp());
-               cairo_show_text( cr, __buf__);
-               cairo_stroke( cr);
-       }
-}
-
-
-void
 aghui::SScoringFacility::
-_draw_hour_ticks( cairo_t *cr, int htop, int hbot, bool with_cursor)
+draw_montage( const char *fname) // to a file
 {
-       cairo_set_line_width( cr, 1);
-       cairo_set_font_size( cr, 10);
-       float   hours4 = (float)total_pages() * pagesize() / 3600 * 4;
-       for ( size_t i = 1; i < hours4; ++i ) {
-               guint tick_pos = (float)i / hours4 * da_wd;
-               _p.CwB[SExpDesignUI::TColour::sf_ticks].set_source_rgba( cr);
-               cairo_move_to( cr, tick_pos, hbot);
-               cairo_rel_line_to( cr, 0, -((i%4 == 0) ? 20 : (i%2 == 0) ? 12 : 
5));
-               if ( i % 4 == 0 ) {
-                       snprintf_buf( "%2zuh", i/4);
-                       
_p.CwB[SExpDesignUI::TColour::sf_labels].set_source_rgba( cr);
-                       cairo_move_to( cr, tick_pos+5, hbot - 2);
-                       cairo_show_text( cr, __buf__);
-               }
-       }
-       cairo_stroke( cr);
-
-       if ( with_cursor ) {
-               _p.CwB[SExpDesignUI::TColour::sf_cursor].set_source_rgba( cr);
-               cairo_rectangle( cr,
-                                (double)cur_vpage() / total_vpages() * da_wd, 
htop,
-                                max( .5, 1. / total_vpages() * da_wd), hbot - 
htop);
-               cairo_fill( cr);
-               cairo_stroke( cr);
-       }
+       cairo_surface_t *cs = cairo_svg_surface_create( fname, da_wd, da_ht);
+       cairo_t *cr = cairo_create( cs);
+       draw_montage( cr);
+       cairo_destroy( cr);
+       cairo_surface_destroy( cs);
 }
 
 
+
 template <class T>
 void
 aghui::SScoringFacility::
@@ -984,16 +696,6 @@ _draw_matrix_to_montage( cairo_t *cr, const itpp::Mat<T>& 
mat)
        }
 }
 
-void
-aghui::SScoringFacility::
-draw_montage( const char *fname) // to a file
-{
-       cairo_surface_t *cs = cairo_svg_surface_create( fname, da_wd, da_ht);
-       cairo_t *cr = cairo_create( cs);
-       draw_montage( cr);
-       cairo_destroy( cr);
-       cairo_surface_destroy( cs);
-}
 
 void
 aghui::SScoringFacility::
@@ -1031,15 +733,17 @@ draw_montage( cairo_t* cr)
        switch ( mode ) {
        case TMode::showing_ics:
                if ( ica_components.size() == 0 ) {
-                       ::cairo_put_banner( cr, da_wd, da_ht,
-                                           "Now set up ICA parameters, then 
press [Compute ICs]");
+                       aghui::cairo_put_banner(
+                               cr, da_wd, da_ht,
+                               "Now set up ICA parameters, then press [Compute 
ICs]");
                } else
                        _draw_matrix_to_montage( cr, ica_components);
                        // draw ignoring channels' zeroy
            break;
        case TMode::separating:
-               ::cairo_put_banner( cr, da_wd, da_ht,
-                                   "Separating...");
+               aghui::cairo_put_banner(
+                       cr, da_wd, da_ht,
+                       "Separating...");
            break;
        case TMode::showing_remixed:
        case TMode::scoring:
diff --git a/src/ui/sf/sf-phasic-events.cc b/src/ui/sf/sf-phasic-events.cc
new file mode 100644
index 0000000..1328424
--- /dev/null
+++ b/src/ui/sf/sf-phasic-events.cc
@@ -0,0 +1,30 @@
+// ;-*-C++-*-
+/*
+ *       File name:  ui/sf/sf-phasic-events.cc
+ *         Project:  Aghermann
+ *          Author:  Andrei Zavada <[email protected]>
+ * Initial version:  2013-01-04
+ *
+ *         Purpose:  scoring facility: phasic events
+ *
+ *         License:  GPL
+ */
+
+#include "metrics/phasic-events.hh"
+#include "sf.hh"
+
+using namespace std;
+
+void
+aghui::SScoringFacility::SChannel::
+get_phasic_events()
+{
+       using namespace metrics::phasic;
+       auto H = sigfile::SNamedChannel<int> (crecording.F(), _h);
+       phasic_events[TEventTypes::spindle] =
+               detect_spindles( H);
+       phasic_events[TEventTypes::K_complex] =
+               detect_Kcomplexes( H);
+}
+
+// eof
diff --git a/src/ui/sf/sf.cc b/src/ui/sf/sf.cc
index 0dac616..9556f8b 100644
--- a/src/ui/sf/sf.cc
+++ b/src/ui/sf/sf.cc
@@ -319,6 +319,31 @@ channel_by_idx( size_t i)
 }
 
 
+aghui::SScoringFacility::SChannel*
+__attribute__ ((pure))
+aghui::SScoringFacility::
+channel_near( int y)
+{
+       int nearest = INT_MAX, thisy;
+       auto nearest_h = &channels.front();
+       for ( auto &H : channels ) {
+               if ( H.hidden )
+                       continue;
+               thisy = (y > H.zeroy) ? y - H.zeroy : H.zeroy - y;
+                       // if ( thisy < nearest )
+                       //      return &const_cast<SChannel&>(H);
+                       // else
+                       //      return nearest_h;
+               if ( thisy < nearest ) {
+                       nearest = thisy;
+                       nearest_h = &H;
+               }
+       }
+       return nearest_h;
+}
+
+
+
 
 
 void
@@ -573,31 +598,6 @@ queue_redraw_all() const
 
 
 
-aghui::SScoringFacility::SChannel*
-__attribute__ ((pure))
-aghui::SScoringFacility::
-channel_near( int y)
-{
-       int nearest = INT_MAX, thisy;
-       SChannel* nearest_h = &channels.front();
-       for ( auto &H : channels ) {
-               if ( H.hidden )
-                       continue;
-               thisy = (y > H.zeroy) ? y - H.zeroy : H.zeroy - y;
-                       // if ( thisy < nearest )
-                       //      return &const_cast<SChannel&>(H);
-                       // else
-                       //      return nearest_h;
-               if ( thisy < nearest ) {
-                       nearest = thisy;
-                       nearest_h = &H;
-               }
-       }
-       return nearest_h;
-}
-
-
-
 
 
 
diff --git a/src/ui/sf/sf.hh b/src/ui/sf/sf.hh
index 4a24f01..3455572 100644
--- a/src/ui/sf/sf.hh
+++ b/src/ui/sf/sf.hh
@@ -13,13 +13,17 @@
 #ifndef _AGH_UI_SCORING_FACILITY_H
 #define _AGH_UI_SCORING_FACILITY_H
 
+#include <map>
+#include <list>
+
 #include <cairo/cairo.h>
 #include <cairo/cairo-svg.h>
 #include <gtk/gtk.h>
 
+#include "common/alg.hh"
 #include "common/config-validate.hh"
 #include "sigproc/winfun.hh"
-#include "metrics/page-metrics-base.hh"
+#include "metrics/phasic-events.hh"
 #include "expdesign/primaries.hh"
 #include "ica/ica.hh"
 #include "ui/globals.hh"
@@ -59,9 +63,9 @@ class SScoringFacility
        agh::CSubject::SEpisode&
                _sepisode;
     public:
-       agh::CSubject&                  csubject() const        {       return 
_csubject;       }
-       agh::CSubject::SEpisode&        sepisode() const        {       return 
_sepisode;       }
-       const string&                   session()  const        {       return 
_session;        }
+       agh::CSubject&                  csubject() const { return _csubject; }
+       agh::CSubject::SEpisode&        sepisode() const { return _sepisode; }
+       const string&                   session()  const { return _session;  }
 
       // channels
        struct SChannel {
@@ -205,6 +209,12 @@ class SScoringFacility
                        emg_profile;
                double  emg_display_scale;
 
+             // phasic events
+               map<metrics::phasic::TEventTypes, list<agh::alg::SSpan<double>>>
+                       phasic_events;
+               void
+               get_phasic_events();
+
              // region
                void mark_region_as_artifact( bool do_mark);
                void mark_region_as_annotation( const char*);
@@ -241,7 +251,9 @@ class SScoringFacility
                        resample_power,
                        draw_selection_course,
                        draw_selection_envelope,
-                       draw_selection_dzcdf;
+                       draw_selection_dzcdf,
+                       draw_phasic_spindle,
+                       draw_phasic_Kcomplex;
                bool    discard_marked,
                        apply_reconstituted;
 

-- 
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