[med-svn] [SCM] aghermann branch, master, updated. 83bfc7bafe1055d29be61afe3e8ec4482539aa1d

Andrei Zavada johnhommer at gmail.com
Thu Nov 22 23:45:49 UTC 2012


The following commit has been merged in the master branch:
commit 83bfc7bafe1055d29be61afe3e8ec4482539aa1d
Author: Andrei Zavada <johnhommer at gmail.com>
Date:   Fri Nov 23 01:44:53 2012 +0200

    profile metrics overhaul part 1/2

diff --git a/data/main.glade b/data/main.glade
index 4cf9721..9b24e11 100644
--- a/data/main.glade
+++ b/data/main.glade
@@ -348,13 +348,13 @@
     <property name="step_increment">0.10000000000000001</property>
     <property name="page_increment">0.5</property>
   </object>
-  <object class="GtkAdjustment" id="jMsmtOpFreqFrom">
+  <object class="GtkAdjustment" id="jMsmtProfileParamsPSDFreqFrom">
     <property name="upper">60</property>
     <property name="value">2</property>
     <property name="step_increment">0.25</property>
     <property name="page_increment">2</property>
   </object>
-  <object class="GtkAdjustment" id="jMsmtOpFreqWidth">
+  <object class="GtkAdjustment" id="jMsmtProfileParamsPSDFreqWidth">
     <property name="lower">0.25</property>
     <property name="upper">8</property>
     <property name="value">1</property>
@@ -822,130 +822,7 @@ rm */*/*/.*.{psd,mc}</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkBox" id="cMsmtCommonProfileParams">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="valign">center</property>
-                                <child>
-                                  <object class="GtkLabel" id="label117">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="valign">center</property>
-                                    <property name="xalign">1</property>
-                                    <property name="label" translatable="yes">@ </property>
-                                    <property name="use_underline">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSpinButton" id="eMsmtOpFreqFrom">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="valign">center</property>
-                                    <property name="has_frame">False</property>
-                                    <property name="invisible_char">•</property>
-                                    <property name="width_chars">5</property>
-                                    <property name="xalign">1</property>
-                                    <property name="invisible_char_set">True</property>
-                                    <property name="primary_icon_activatable">False</property>
-                                    <property name="secondary_icon_activatable">False</property>
-                                    <property name="adjustment">jMsmtOpFreqFrom</property>
-                                    <property name="digits">2</property>
-                                    <property name="numeric">True</property>
-                                    <property name="update_policy">if-valid</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label120">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="valign">center</property>
-                                    <property name="label" translatable="yes">Hz, </property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSpinButton" id="eMsmtOpFreqWidth">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="valign">center</property>
-                                    <property name="has_frame">False</property>
-                                    <property name="invisible_char">•</property>
-                                    <property name="xalign">1</property>
-                                    <property name="invisible_char_set">True</property>
-                                    <property name="primary_icon_activatable">False</property>
-                                    <property name="secondary_icon_activatable">False</property>
-                                    <property name="adjustment">jMsmtOpFreqWidth</property>
-                                    <property name="digits">2</property>
-                                    <property name="numeric">True</property>
-                                    <property name="update_policy">if-valid</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label134">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="valign">center</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes"> wide</property>
-                                    <property name="use_markup">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">4</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSeparator" id="separator11">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">5</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="lMsmtPSDInfo1">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="halign">end</property>
-                                    <property name="valign">center</property>
-                                    <property name="xalign">0.89999997615814209</property>
-                                    <property name="xpad">5</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">6</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
+                              <placeholder/>
                             </child>
                             <child>
                               <object class="GtkBox" id="cMsmtProfileParamsContainer">
@@ -954,24 +831,99 @@ rm */*/*/.*.{psd,mc}</property>
                                 <property name="valign">center</property>
                                 <property name="orientation">vertical</property>
                                 <child>
-                                  <object class="GtkBox" id="cMsmtProfileParams2">
-                                    <property name="visible">True</property>
+                                  <object class="GtkBox" id="cMsmtProfileParamsPSD">
                                     <property name="can_focus">False</property>
                                     <property name="valign">center</property>
                                     <child>
-                                      <placeholder/>
+                                      <object class="GtkLabel" id="label117">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="valign">center</property>
+                                        <property name="xalign">1</property>
+                                        <property name="label" translatable="yes">@ </property>
+                                        <property name="use_underline">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
                                     </child>
                                     <child>
-                                      <placeholder/>
+                                      <object class="GtkSpinButton" id="eMsmtProfileParamsPSDFreqFrom">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="valign">center</property>
+                                        <property name="has_frame">False</property>
+                                        <property name="invisible_char">•</property>
+                                        <property name="width_chars">5</property>
+                                        <property name="xalign">1</property>
+                                        <property name="invisible_char_set">True</property>
+                                        <property name="primary_icon_activatable">False</property>
+                                        <property name="secondary_icon_activatable">False</property>
+                                        <property name="adjustment">jMsmtProfileParamsPSDFreqFrom</property>
+                                        <property name="digits">2</property>
+                                        <property name="numeric">True</property>
+                                        <property name="update_policy">if-valid</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                      </packing>
                                     </child>
                                     <child>
-                                      <placeholder/>
+                                      <object class="GtkLabel" id="label120">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="valign">center</property>
+                                        <property name="label" translatable="yes">Hz, </property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
                                     </child>
                                     <child>
-                                      <placeholder/>
+                                      <object class="GtkSpinButton" id="eMsmtProfileParamsPSDFreqWidth">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="valign">center</property>
+                                        <property name="has_frame">False</property>
+                                        <property name="invisible_char">•</property>
+                                        <property name="xalign">1</property>
+                                        <property name="invisible_char_set">True</property>
+                                        <property name="primary_icon_activatable">False</property>
+                                        <property name="secondary_icon_activatable">False</property>
+                                        <property name="adjustment">jMsmtProfileParamsPSDFreqWidth</property>
+                                        <property name="digits">2</property>
+                                        <property name="numeric">True</property>
+                                        <property name="update_policy">if-valid</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel" id="label134">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="valign">center</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes"> wide</property>
+                                        <property name="use_markup">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">4</property>
+                                      </packing>
                                     </child>
                                     <child>
-                                      <object class="GtkLabel" id="lMsmtMCInfo">
+                                      <object class="GtkLabel" id="lMsmtProfilePSDExtra">
                                         <property name="visible">True</property>
                                         <property name="can_focus">False</property>
                                         <property name="halign">end</property>
@@ -982,7 +934,7 @@ rm */*/*/.*.{psd,mc}</property>
                                       <packing>
                                         <property name="expand">False</property>
                                         <property name="fill">True</property>
-                                        <property name="position">4</property>
+                                        <property name="position">5</property>
                                       </packing>
                                     </child>
                                   </object>
@@ -993,8 +945,7 @@ rm */*/*/.*.{psd,mc}</property>
                                   </packing>
                                 </child>
                                 <child>
-                                  <object class="GtkBox" id="cMsmtProfileParams1">
-                                    <property name="visible">True</property>
+                                  <object class="GtkBox" id="cMsmtProfileParamsMC">
                                     <property name="can_focus">False</property>
                                     <property name="valign">center</property>
                                     <child>
@@ -1016,7 +967,7 @@ rm */*/*/.*.{psd,mc}</property>
                                       <placeholder/>
                                     </child>
                                     <child>
-                                      <object class="GtkLabel" id="lMsmtPSDInfo">
+                                      <object class="GtkLabel" id="lMsmtProfileMCExtra">
                                         <property name="visible">True</property>
                                         <property name="can_focus">False</property>
                                         <property name="halign">end</property>
@@ -1038,8 +989,7 @@ rm */*/*/.*.{psd,mc}</property>
                                   </packing>
                                 </child>
                                 <child>
-                                  <object class="GtkBox" id="cMsmtProfileParams3">
-                                    <property name="visible">True</property>
+                                  <object class="GtkBox" id="cMsmtProfileParamsSWU">
                                     <property name="can_focus">False</property>
                                     <property name="valign">center</property>
                                     <child>
@@ -1061,7 +1011,7 @@ rm */*/*/.*.{psd,mc}</property>
                                       <placeholder/>
                                     </child>
                                     <child>
-                                      <object class="GtkLabel" id="lMsmtPSDInfo2">
+                                      <object class="GtkLabel" id="lMsmtProfileSWUExtra">
                                         <property name="visible">True</property>
                                         <property name="can_focus">False</property>
                                         <property name="halign">end</property>
@@ -1485,18 +1435,6 @@ rm */*/*/.*.{psd,mc}</property>
                                   <placeholder/>
                                 </child>
                                 <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
                                   <object class="GtkFrame" id="fFreqConventionalRanges">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
@@ -6750,6 +6688,12 @@ dragging individual signals with <i>Alt</i>.</small></property
                                     <child>
                                       <placeholder/>
                                     </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
                                   </object>
                                 </child>
                                 <child>
@@ -7274,8 +7218,8 @@ dragging individual signals with <i>Alt</i>.</small></property
   </object>
   <object class="GtkSizeGroup" id="zMsmtParams">
     <widgets>
-      <widget name="cMsmtProfileParams2"/>
-      <widget name="cMsmtProfileParams1"/>
+      <widget name="cMsmtProfileParamsPSD"/>
+      <widget name="cMsmtProfileParamsMC"/>
     </widgets>
   </object>
 </interface>
diff --git a/data/session-chooser.glade b/data/session-chooser.glade
index 4c12e0d..5149b10 100644
--- a/data/session-chooser.glade
+++ b/data/session-chooser.glade
@@ -7,7 +7,7 @@
     <property name="title" translatable="yes">Select Experiment</property>
     <property name="window_position">center</property>
     <property name="default_width">577</property>
-    <property name="default_height">180</property>
+    <property name="default_height">271</property>
     <property name="icon">aghermann.png</property>
     <property name="type_hint">normal</property>
     <child internal-child="vbox">
diff --git a/doc/org/aghermann.org.in b/doc/org/aghermann.org.in
index 9c625ee..82c658b 100644
--- a/doc/org/aghermann.org.in
+++ b/doc/org/aghermann.org.in
@@ -28,8 +28,8 @@ long sleepers, early /vs/ late, etc.
   The project’s public Git repositories are hosted on [[https://github.com/hmmr/aghermann][GitHub]] and,
   historically, also at [[http://sourceforge.net/projects/aghermann][SourceForge]].
 
-* Features
 
+* Features
 ** Sleep experiment recording manager
 
 | Aghermann keeps the recordings in an organized fashion in a tree following an experimental design commonly used in sleep research i.e. groups of subjects sleeping several (timed) episoded per session with recordings from a number of channels. | [[file:img/measurements.png][img/measurements-t.png]]  |
@@ -105,16 +105,19 @@ long sleepers, early /vs/ late, etc.
 
 ** SWA profiles
 
-   Two kinds of SWA profiles available for Achermann model simulations:
+   Three kinds of SWA profiles available for Achermann model simulations:
 
     + *Power spectrum density* (PSD), which can be obtained in bins of
       0.25, 0.5 and 1 Hz and combined into larger frequency ranges, or
       conventional bands (delta, gamma etc).
 
-    + [[http://www.ncbi.nlm.nih.gov/pubmed/11008419][EEG Microcontinuity]] [[file:mc.org]["lite"]].
+    + *Slow Wave Upswing* (SWU), an experimental metric representing
+      a measure of uniformity/simultaneity of neurons generating a
+      slow wave front.
 
+    + [[http://www.ncbi.nlm.nih.gov/pubmed/11008419][*EEG Microcontinuity*]] [[file:mc.org]["lite"]].
 
-** Basic sleep metrics
+** Basic sleep analysis
    | For individual episodes, ultradian (NREM-REM) cycle period can be estimated, by fitting a function of the form:                                                                                                     | [[file:img/overview-single-episode-with-uc.png][img/overview-single-episode-with-uc-t.png]] |
    | [[file:img/equation-uc.png]]                                                                                                                                                                                            |                                           |
    | (with negative values clamped at 0) which produces a period, /T/, as well as a decay rate, /r/, the latter being a good equivalent of the classic Process S decay rate from seminal Borbély, Daan & Beersma papers. |                                           |
@@ -132,9 +135,14 @@ long sleepers, early /vs/ late, etc.
 
    + All graphic presentations can be saved in SVG format.
 
+
+* Accessory utilities to handle EDF files
+Included as separate programs are companion utilities to view/modify
+EDF header and create EDF files from plain ASCII tsv files.
+
 ** EDF header viewer/editor
 
-   | Included as separate programs are two companion utilities, *edfhed* and *edfhed-gtk*, to view and modify the header of edf files. |  [[file:img/edfhed-gtk.png][img/edfhed-gtk-t.png]] |
+   | *edfhed* and *edfhed-gtk*, to view and modify the header of edf files. |  [[file:img/edfhed-gtk.png][img/edfhed-gtk-t.png]] |
 
 ** EDF channel converter/mixer
 
@@ -143,6 +151,7 @@ long sleepers, early /vs/ late, etc.
    drop channels from an edf file.  Refer to its man page for
    details.  More operations are planned.
 
+
 * Notes on security and accessibility
 
    + There is no consideration specially given to potential security
@@ -169,6 +178,7 @@ long sleepers, early /vs/ late, etc.
      on the item or pressing Enter.  This saved me a few dialog boxes
      along the way.)
 
+
 * Feedback/bugreports
 
   Should you find Aghermann useful (in its scoring capacity only, or
diff --git a/src/common/lang.hh b/src/common/lang.hh
index b9b6e93..eb0e204 100644
--- a/src/common/lang.hh
+++ b/src/common/lang.hh
@@ -10,8 +10,8 @@
  *         License:  GPL
  */
 
-#ifndef _AGH_COMMON_LANG_H_
-#define _AGH_COMMON_LANG_H_
+#ifndef _AGH_COMMON_LANG_H
+#define _AGH_COMMON_LANG_H
 
 #if HAVE_CONFIG_H && !defined(VERSION)
 #  include "config.h"
@@ -44,6 +44,8 @@ using namespace std;
 	T (const T&) = delete;			\
 	void operator=( const T&) = delete;
 
+typedef unsigned long hash_t;
+
 #endif
 
 // eof
diff --git a/src/expdesign/loadsave.cc b/src/expdesign/loadsave.cc
index d90570b..e297e8c 100644
--- a/src/expdesign/loadsave.cc
+++ b/src/expdesign/loadsave.cc
@@ -82,7 +82,7 @@ agh::CExpDesign::load_settings()
 		fprintf( stderr, "agh::CExpDesign::load_settings(): Invalid fft params (%s); assigned defaults\n", ex.what());
 	}
 
-	try { mc_params.check( fft_params.pagesize); }
+	try { mc_params.check(); }
 	catch (invalid_argument ex) {
 		mc_params.reset();
 		fprintf( stderr, "agh::CExpDesign::load_settings(): Invalid mc params (%s); assigned defaults\n", ex.what());
diff --git a/src/expdesign/recording.cc b/src/expdesign/recording.cc
index a958039..fc9ff7c 100644
--- a/src/expdesign/recording.cc
+++ b/src/expdesign/recording.cc
@@ -24,10 +24,9 @@ CRecording (sigfile::CSource& F, int sig_no,
 	    const metrics::psd::SPPack& fft_params,
 	    const metrics::swu::SPPack& swu_params,
 	    const metrics::mc::SPPack& mc_params)
-      : metrics::psd::CProfile (F, sig_no, fft_params),
-        metrics::swu::CProfile (F, sig_no, swu_params),
-	metrics::mc::CProfile  (F, sig_no, mc_params,
-			        fft_params.pagesize),
+      : psd_profile (F, sig_no, fft_params),
+        swu_profile (F, sig_no, swu_params),
+	mc_profile  (F, sig_no, mc_params),
 	uc_params {NAN, NAN, NAN, NAN},
 	_status (0), // not computed
 	_source (F), _sig_no (sig_no)
@@ -91,7 +90,7 @@ CSCourse (CSubject& J, const string& d, const sigfile::SChannel& h,
 
 		if ( Mi == _mm_list.begin() ) {
 			_0at = F.start_time();
-			_pagesize = M.metrics::psd::SPPack::pagesize;
+			_pagesize = M.psd_profile.Pp.pagesize;
 			_pages_in_bed = 0;
 		} else
 			if ( _pagesize != F.pagesize() ) {
@@ -152,7 +151,7 @@ CSCourse (CRecording& M,
 	_mm_list.push_back( &M);
 
 	_0at = M.F().start_time();
-	_pagesize = M.metrics::psd::SPPack::pagesize;
+	_pagesize = M.psd_profile.Pp.pagesize;
 	_pages_in_bed = 0;
 
 	int	pa = (size_t)difftime( M.F().start_time(), _0at) / _pagesize,
diff --git a/src/expdesign/recording.hh b/src/expdesign/recording.hh
index ea47f21..9d1d1c1 100644
--- a/src/expdesign/recording.hh
+++ b/src/expdesign/recording.hh
@@ -25,17 +25,22 @@ namespace agh {
 
 using namespace std;
 
-class CRecording
-  : public metrics::psd::CProfile,
-    public metrics::swu::CProfile,
-    public metrics::mc::CProfile {
-
-    friend class CExpDesign;
+class CRecording {
 
 	CRecording () = delete;
 	void operator=( const CRecording&) = delete;
 
     public:
+	CRecording (const CRecording& rv) // needed for map
+	      : psd_profile (rv.psd_profile),
+		swu_profile (rv.swu_profile),
+		mc_profile  (rv.mc_profile),
+		uc_params (rv.uc_params),
+		uc_cf (rv.uc_cf),
+		_status (rv._status),
+		_source (rv._source),
+		_sig_no (rv._sig_no)
+		{}
 	CRecording (sigfile::CSource& F, int sig_no,
 		    const metrics::psd::SPPack&,
 		    const metrics::swu::SPPack&,
@@ -80,7 +85,7 @@ class CRecording
 	// this one damn identical in two bases
 	size_t pagesize() const
 		{
-			return ((metrics::psd::CProfile*)this) -> metrics::CProfile_base::pagesize();
+			return ((metrics::psd::CProfile*)this) -> Pp.pagesize;
 		}
 
 	size_t total_pages() const
@@ -99,7 +104,11 @@ class CRecording
 	template <typename T>
 	valarray<T>
 	course( metrics::TType metric,
-		double freq_from, double freq_upto) const;
+		double freq_from, double freq_upto);
+
+	metrics::psd::CProfile psd_profile;
+	metrics::swu::CProfile swu_profile;
+	metrics::mc::CProfile	mc_profile;
 
 	bool have_uc_determined() const
 		{
@@ -247,21 +256,21 @@ template <typename T>
 valarray<T>
 CRecording::
 course( metrics::TType metric,
-	double freq_from, double freq_upto) const
+	double freq_from, double freq_upto)
 {
 	using namespace metrics;
 	switch ( metric ) {
 	case TType::psd:
-		return (((psd::CProfile*)this)->compute(),
-			psd::CProfile::course<T>( freq_from, freq_upto));
+		return (psd_profile.compute(),
+			psd_profile.course<T>( freq_from, freq_upto));
 	case TType::swu:
-		return (((swu::CProfile*)this)->compute(),
-			swu::CProfile::course<T>( freq_from, freq_upto));
+		return (swu_profile.compute(),
+			swu_profile.course<T>());
 	case TType::mc:
-		return (((mc::CProfile*)this)->compute(),
-			mc::CProfile::course<T>(
-			min( (size_t)((freq_from) / bandwidth),
-			     mc::CProfile::bins()-1)));
+		return (mc_profile.compute(),
+			mc_profile.course<T>(
+				min( (size_t)((freq_from) / mc_profile.Pp.bandwidth),
+				     mc_profile.bins()-1)));
 	default:
 		throw invalid_argument ("CRecording::course: bad metric");
 	}
diff --git a/src/expdesign/tree-scanner.cc b/src/expdesign/tree-scanner.cc
index 902930e..02f4446 100644
--- a/src/expdesign/tree-scanner.cc
+++ b/src/expdesign/tree-scanner.cc
@@ -353,9 +353,9 @@ compute_profiles()
 	TRecordingOpFun F =
 		[&]( CRecording& R)
 		{
-			R.metrics::psd::CProfile::compute();
-			R.metrics::swu::CProfile::compute();
-			R.metrics::mc::CProfile::compute();
+			R.psd_profile.compute();
+			R.swu_profile.compute();
+			R.mc_profile.compute();
 		};
 	TRecordingReportFun G =
 		[&]( const CJGroup&, const CSubject&, const string&, const CSubject::SEpisode&, const CRecording& R,
diff --git a/src/metrics/mc.cc b/src/metrics/mc.cc
index ce37278..ef2bcf0 100644
--- a/src/metrics/mc.cc
+++ b/src/metrics/mc.cc
@@ -22,33 +22,9 @@
 using namespace std;
 
 
-string
-metrics::mc::CProfile::
-fname_base() const
-{
-	DEF_UNIQUE_CHARP (_);
-	assert (asprintf( &_,
-			  "%s-%s-%zu-%zu",
-			  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-			  _using_F.pagesize(),
-			  _signature) > 1);
-	string ret {_};
-	return ret;
-}
-
-
-inline int
-heaviside( TFloat x)
-{
-	return x > 0.;
-}
-
-
-
-
 void
 metrics::mc::SPPack::
-check( size_t) const
+check() const
 {
         if ( mc_gain < 1.0 )
 		throw invalid_argument ("mc_gain must be >= 1.0");
@@ -77,103 +53,80 @@ reset()
 
 metrics::mc::CProfile::
 CProfile (const sigfile::CSource& F, int sig_no,
-	  const SPPack &params,
-	  size_t pagesize)
-      : CProfile_base (F, sig_no,
-		       pagesize, // acting 'pagesize' for CPageMetrics_base
-		       params.compute_n_bins(F.samplerate(sig_no))),
-	SPPack (params)
+	  const SPPack &params)
+      : metrics::CProfile (F, sig_no,
+			   params.pagesize, // acting 'pagesize' for metrics::CProfile
+			   params.compute_n_bins(F.samplerate(sig_no))),
+	Pp (params)
 	// *_filter's initialized at compute time
 {
-	SPPack::check( pagesize); // throw if not ok
+	Pp.check(); // throw if not ok
 }
 
 
 
 
-int
+string
 metrics::mc::CProfile::
-compute( const SPPack& req_params,
-	 bool force)
+fname_base() const
 {
-	auto req_signature = _using_F.dirty_signature( _using_sig_no);
-	if ( have_data()
-	     && not force
-	     && (*this) == req_params
-	     && _signature == req_signature )
-		return 0;
-
-	_data.resize( pages() * _bins);
-
-	DEF_UNIQUE_CHARP (old_mirror_fname);
-	DEF_UNIQUE_CHARP (new_mirror_fname);
-
-	// insert a .
-	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
-
-	assert (asprintf( &old_mirror_fname,
-			  "%s-%s-%zu:"
-			  "_%g_%g" "_%g" "_%g_%g"
-			  ":%zu.mc",
-			  basename_dot.c_str(),
-			  _using_F.channel_by_id(_using_sig_no), _pagesize, scope,
-			  iir_backpolate,
-			  mc_gain,
-			  f0fc, bandwidth,
-			  _signature)
+	DEF_UNIQUE_CHARP (_);
+	assert (asprintf( &_,
+			  "%s.%s-%zu"
+			  ":%zu-%g_%g" "_%g" "_%g_%g",
+			  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
+			  _using_F.dirty_signature( _using_sig_no),
+			  Pp.pagesize,
+			  Pp.scope,
+			  Pp.iir_backpolate,
+			  Pp.mc_gain,
+			  Pp.f0fc, Pp.bandwidth)
 		> 1);
+	string ret {_};
+	return ret;
+}
 
-      // update signature
-	*(SPPack*)this = req_params;
-	_signature = req_signature;
-
-	printf( "CBinnedMC::compute( %s, %s): %g sec (%zu pp @%zu + %zu sec last incomplete page), scope %g sec",
-		_using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-		_using_F.recording_time(),
-		pages(), _pagesize, (size_t)_using_F.recording_time() - (pages() * _pagesize), scope);
-
-
-	assert (asprintf( &new_mirror_fname,
-			  "%s-%s-%zu:"
-			  "_%g_%g" "_%g" "_%g_%g"
-			  ":%zu.mc",
-			  basename_dot.c_str(),
-			  _using_F.channel_by_id(_using_sig_no), _pagesize, scope,
-			  iir_backpolate,
-			  mc_gain,
-			  f0fc, bandwidth,
-			  _signature)
+string
+metrics::mc::CProfile::
+mirror_fname() const
+{
+	DEF_UNIQUE_CHARP (_);
+	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
+	assert (asprintf( &_,
+			  "%s-%s-%zu"
+			  ":%zu-%g_%g" "_%g" "_%g_%g"
+			  ".mc",
+			  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,
+			  Pp.mc_gain,
+			  Pp.f0fc, Pp.bandwidth)
 		> 1);
+	string ret {_};
+	return ret;
+}
 
-	bool got_it = (_mirror_back( new_mirror_fname) == 0);
-
-      // remove previously saved power
-	if ( strcmp( old_mirror_fname, new_mirror_fname) )
-		if ( unlink( old_mirror_fname) ) {}
-
-	if ( got_it and not force ) {
-		printf( " (cached)\n");
-		_status |= TFlags::computed;
-		return 0;
-	}
-	printf( "\n");
+int
+metrics::mc::CProfile::
+go_compute()
+{
+	_data.resize( pages() * _bins);
 
-	auto signal = _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 suss = do_sssu_reduction(
-			signal, samplerate(), scope,
-			mc_gain, iir_backpolate,
-			freq_from + b * bandwidth,
-			freq_from + b * bandwidth + f0fc,
-			bandwidth);
+			S, samplerate(),
+			Pp.scope,
+			Pp.mc_gain, Pp.iir_backpolate,
+			Pp.freq_from + b * Pp.bandwidth,
+			Pp.freq_from + b * Pp.bandwidth + Pp.f0fc,
+			Pp.bandwidth);
 		for ( size_t p = 0; p < pages(); ++p )
 			nmth_bin(p, b) = (suss.first[p] - suss.second[p]); // make it positive
 	}
 
-	if ( _mirror_enable( new_mirror_fname) ) {}
-
-	_status |= TFlags::computed;
-
 	return 0;
 }
 
@@ -184,7 +137,7 @@ compute( const SPPack& req_params,
 
 metrics::mc::CProfile::TSSSU
 metrics::mc::CProfile::
-do_sssu_reduction( const valarray<TFloat>& signal,
+do_sssu_reduction( const valarray<TFloat>& S,
 		   size_t samplerate, double scope,
 		   double mc_gain, double iir_backpolate,
 		   double f0, double fc,
@@ -201,10 +154,10 @@ do_sssu_reduction( const valarray<TFloat>& signal,
 			   bandwidth);
 
 	size_t	integrate_samples = scope * samplerate,
-		pages = signal.size() / integrate_samples;
+		pages = S.size() / integrate_samples;
 	valarray<TFloat>
-		due_filtered = due_filter.apply( signal, false),
-		se_filtered  =  se_filter.apply( signal, false);
+		due_filtered = due_filter.apply( S, false),
+		se_filtered  =  se_filter.apply( S, false);
 
 	valarray<TFloat>
 		ss (pages),
@@ -254,9 +207,9 @@ export_tsv( const string& fname) const
 		 _using_F.subject(), _using_F.session(), _using_F.episode(),
 		 (int)strlen(asctime_)-1, asctime_,
 		 _using_F.channel_by_id(_using_sig_no),
-		 pages(), _pagesize, freq_from, freq_from + bandwidth * bins(), bandwidth);
+		 pages(), Pp.pagesize, Pp.freq_from, Pp.freq_from + Pp.bandwidth * bins(), Pp.bandwidth);
 
-	for ( bin = 0; bin < _bins; ++bin, bum += bandwidth )
+	for ( bin = 0; bin < _bins; ++bin, bum += Pp.bandwidth )
 		fprintf( f, "%g%c", bum, bin+1 == _bins ? '\n' : '\t');
 
 	for ( p = 0; p < pages(); ++p ) {
@@ -288,7 +241,7 @@ export_tsv( size_t bin,
 		 _using_F.subject(), _using_F.session(), _using_F.episode(),
 		 (int)strlen(asctime_)-1, asctime_,
 		 _using_F.channel_by_id(_using_sig_no),
-		 pages(), _pagesize, freq_from, freq_from + (bin+1) * bandwidth);
+		 pages(), Pp.pagesize, Pp.freq_from, Pp.freq_from + (bin+1) * Pp.bandwidth);
 
 	for ( size_t p = 0; p < pages(); ++p )
 		fprintf( f, "%zu\t%g\n", p, nmth_bin(p, bin));
diff --git a/src/metrics/mc.hh b/src/metrics/mc.hh
index f64288c..b29a4b6 100644
--- a/src/metrics/mc.hh
+++ b/src/metrics/mc.hh
@@ -28,7 +28,8 @@ using namespace std;
 namespace metrics {
 namespace mc {
 
-struct SPPack {
+struct SPPack
+  : public metrics::SPPack {
 	double	scope,
 		f0fc,//f0, // = 1.,
 		//fc, // = 1.8;
@@ -44,17 +45,28 @@ struct SPPack {
 			reset();
 		}
 
-	SPPack& operator=( const SPPack&) = default;
-	bool operator==( const SPPack& rv) const
+	bool same_as( const SPPack& rv) const
 		{
-			return	scope == rv.scope &&
+			return	metrics::SPPack::same_as(rv) &&
+				scope == rv.scope &&
 				iir_backpolate == rv.iir_backpolate &&
 				mc_gain == rv.mc_gain &&
 				f0fc == rv.f0fc &&
 				bandwidth == rv.bandwidth &&
 				smooth_side == rv.smooth_side;
 		}
-	void check( size_t pagesize) const; // throws
+	void make_same( const SPPack& rv)
+		{
+			metrics::SPPack::make_same(rv);
+			scope = rv.scope;
+			iir_backpolate = rv.iir_backpolate;
+			mc_gain = rv.mc_gain;
+			f0fc = rv.f0fc;
+			bandwidth = rv.bandwidth;
+			smooth_side = rv.smooth_side;
+		}
+
+	void check() const; // throws
 	void reset();
 
 	size_t
@@ -68,31 +80,21 @@ struct SPPack {
 
 
 class CProfile
-  : public CProfile_base,
-    public SPPack {
+  : public metrics::CProfile {
 
-	CProfile() = delete;
-	void operator=( const CProfile&) = delete;
-
-    protected:
+    public:
 	CProfile (const sigfile::CSource&, int sig_no,
-		  const SPPack&,
-		  size_t pagesize);
+		  const SPPack&);
+
+	SPPack Pp;
 
-    public:
 	const char* method() const
 		{
 			return metric_method( TType::mc);
 		}
 
-	int
-	compute( const SPPack& req_params,
-		 bool force = false);
-	int
-	compute( bool force = false)
-		{
-			return compute( *this, force);
-		}
+	int go_compute();
+	string mirror_fname() const;
 
 	string fname_base() const;
 	int export_tsv( const string& fname) const;
@@ -110,6 +112,11 @@ class CProfile
 			   double bandwidth);
 
 	static const size_t sssu_hist_size = 100;
+
+	// to enable use as mapped type
+	CProfile (const CProfile& rv)
+	      : metrics::CProfile (rv)
+		{}
 };
 
 
diff --git a/src/metrics/page-metrics-base.cc b/src/metrics/page-metrics-base.cc
index 0a2dec8..98b39b9 100644
--- a/src/metrics/page-metrics-base.cc
+++ b/src/metrics/page-metrics-base.cc
@@ -29,37 +29,56 @@
 
 using namespace std;
 
-metrics::CProfile_base::
-CProfile_base (const sigfile::CSource& F, int sig_no,
-		   size_t pagesize, size_t bins)
-	: _status (0),
-	  _bins (bins),
-	  _pagesize (pagesize),
-	  _signature (0),
-	  _using_F (F),
-	  _using_sig_no (sig_no)
+metrics::CProfile::
+CProfile (const sigfile::CSource& F, int sig_no,
+	  size_t pagesize, size_t bins)
+      : _status (0),
+	_bins (bins),
+	_signature_when_mirrored (0),
+	_using_F (F),
+	_using_sig_no (sig_no)
 {
-	_data.resize( pages() * bins);
+	Pp.pagesize = pagesize;
 }
 
 size_t
-metrics::CProfile_base::
+metrics::CProfile::
 samplerate() const
 {
 	return _using_F.samplerate( _using_sig_no);
 }
 
 size_t
-metrics::CProfile_base::
+metrics::CProfile::
 pages() const
 {
-	return _using_F.recording_time() / _pagesize;
+	return _using_F.recording_time() / Pp.pagesize;
 }
 
 
+void
+metrics::SPPack::
+check() const
+{
+	for ( auto c : {4u, 20u, 30u, 60u} )
+		if ( pagesize == c )
+			return;
+#ifdef _OPENMP
+#pragma omp critical
+#endif
+	throw invalid_argument (string ("Invalid pagesize: ") + to_string(pagesize));
+}
+
+void
+metrics::SPPack::
+reset()
+{
+	pagesize = 30;
+}
+
 
 list<agh::alg::SSpan<size_t>>
-metrics::CProfile_base::
+metrics::CProfile::
 artifacts_in_samples() const
 {
 	return _using_F.artifacts( _using_sig_no)();
@@ -67,7 +86,7 @@ artifacts_in_samples() const
 
 
 list<agh::alg::SSpan<float>>
-metrics::CProfile_base::
+metrics::CProfile::
 artifacts_in_seconds() const
 {
 	list<agh::alg::SSpan<float>> ret;
@@ -80,13 +99,53 @@ artifacts_in_seconds() const
 
 
 
+int
+metrics::CProfile::
+compute( const SPPack& req_params)
+{
+	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) )
+		return 0;
+
+	auto old_mirror = mirror_fname();
+	Pp.make_same( req_params);
+	_signature_when_mirrored = req_signature;
+	auto new_mirror = mirror_fname();
+
+	bool got_it = (mirror_back( new_mirror) == 0);
+
+	if ( old_mirror != new_mirror )
+#pragma GCC diagnostic ignored "-Wunused-value"
+#pragma GCC diagnostic push
+		unlink( old_mirror.c_str());
+#pragma GCC diagnostic pop
+
+	if ( got_it )
+		return 0;
+
+	// printf( "CProfile::compute( %s, %s): %g sec (%zu pp @%zu + %zu sec last incomplete page); bins/size/freq_max = %zu/%g/%g",
+	// 	_using_F.filename(), _using_F.channel_by_id(_using_sig_no),
+	// 	_using_F.recording_time(),
+	// 	pages(), _pagesize, (size_t)_using_F.recording_time() - (pages() * _pagesize),
+	// 	_bins, binsize, freq_max);
+
+	auto retval = go_compute();
+
+	mirror_enable( new_mirror) or true;
+
+	return retval;
+}
+
+
 
 int
-metrics::CProfile_base::
-_mirror_enable( const char *fname)
+metrics::CProfile::
+mirror_enable( const string& fname)
 {
 	int fd, retval = 0;
-	if ( (fd = open( fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1 ||
+	if ( (fd = open( fname.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1 ||
 	     write( fd, &_data[0], _data.size() * sizeof(double)) == -1 )
 	     retval = -1;
 	close( fd);
@@ -95,13 +154,14 @@ _mirror_enable( const char *fname)
 
 
 int
-metrics::CProfile_base::
-_mirror_back( const char *fname)
+metrics::CProfile::
+mirror_back( const string& fname)
 {
 	int fd = -1;
 	try {
-		if ( (fd = open( fname, O_RDONLY)) == -1 )
+		if ( (fd = open( fname.c_str(), O_RDONLY)) == -1 )
 			throw -1;
+		_data.resize( pages() * _bins);
 		if ( read( fd, &_data[0], _data.size() * sizeof(double))
 		     != (ssize_t)(_data.size() * sizeof(double)) )
 			throw -2;
@@ -110,7 +170,10 @@ _mirror_back( const char *fname)
 	} catch (int ex) {
 		if ( fd != -1 ) {
 			close( fd);
-			if ( unlink( fname) ) {}
+#pragma GCC diagnostic ignored "-Wunused-value"
+#pragma GCC diagnostic push
+			unlink( fname.c_str());
+#pragma GCC diagnostic pop
 		}
 		return ex;
 	}
@@ -122,7 +185,7 @@ _mirror_back( const char *fname)
 
 
 int
-metrics::CProfile_base::
+metrics::CProfile::
 export_tsv( const string& fname) const
 {
 	FILE *f = fopen( fname.c_str(), "w");
diff --git a/src/metrics/page-metrics-base.hh b/src/metrics/page-metrics-base.hh
index a71388a..07f21aa 100644
--- a/src/metrics/page-metrics-base.hh
+++ b/src/metrics/page-metrics-base.hh
@@ -50,27 +50,57 @@ metric_method( TType t)
 
 
 
+struct SPPack {
+	size_t	pagesize;
+
+	SPPack ()
+		{
+			reset();
+		}
+
+	virtual bool same_as( const SPPack& rv) const
+		{
+			return pagesize == rv.pagesize;
+		}
+	virtual void make_same( const SPPack& rv)
+		{
+			pagesize = rv.pagesize;
+		}
+
+	void check() const; // throws
+	void reset();
+};
+
+
+
 // We better keep the internal storage as valarray<double> regardless
 // of what TFloat today is, because the computed data are written/read
 // to files (else, we'd need to mark files as holding double data, not float).
-class CProfile_base {
+class CProfile {
 
     protected:
-	CProfile_base (const sigfile::CSource& F, int sig_no,
-		       size_t pagesize, size_t bins);
-	CProfile_base (const CProfile_base& rv) = default;
+	CProfile (const sigfile::CSource&, int sig_no,
+		  size_t pagesize, size_t bins);
+	CProfile (const CProfile&) = default;
     public:
+	SPPack	Pp;
+
 	virtual const char* method() const = 0;
 
-	bool have_data() const
+	const sigfile::CSource& source() const
 		{
-			return _status & TFlags::computed;
+			return _using_F;
+		}
+	int sig_no() const
+		{
+			return _using_sig_no;
 		}
 
-	size_t pagesize() const
+	bool have_data() const
 		{
-			return _pagesize;
+			return _status & TFlags::computed;
 		}
+
 	size_t bins() const
 		{
 			return _bins;
@@ -114,18 +144,17 @@ class CProfile_base {
 
 	virtual int export_tsv( const string& fname) const;
 
-	const sigfile::CSource& source() const
+	int compute( const SPPack&);
+	int compute()
 		{
-			return _using_F;
-		}
-	int sig_no() const
-		{
-			return _using_sig_no;
+			return compute( Pp);
 		}
-      // filenames
-	virtual string fname_base() const = 0;
 
     protected:
+	virtual int go_compute() = 0;
+	virtual string fname_base() const = 0;
+	virtual string mirror_fname() const = 0;
+
 	enum TFlags : int {
 		computed = (1<<0),
 		computable = (1<<1)
@@ -134,24 +163,22 @@ class CProfile_base {
 
 	valarray<double>  // arrays in a given bin extracted by slices
 		_data;    // it is always double because it is saved/loaded in this form
-	size_t	_bins,
-		_pagesize;
+	size_t	_bins;
 
-	size_t  // hash
-		_signature;
+	hash_t	_signature_when_mirrored;
 
 	const sigfile::CSource& _using_F;
 	int _using_sig_no;
 
-	int _mirror_enable( const char*);
-	int _mirror_back( const char*);
+	int mirror_enable( const string&);
+	int mirror_back( const string&);
 };
 
 
 
 template <>
 inline valarray<double>
-CProfile_base::course() const
+CProfile::course() const
 {
 	return _data;
 }
@@ -159,7 +186,7 @@ CProfile_base::course() const
 
 template <>
 inline valarray<float>
-CProfile_base::course() const
+CProfile::course() const
 {
 	valarray<float> coursef (_data.size());
 	for ( size_t i = 0; i < _data.size(); ++i )
@@ -170,7 +197,7 @@ CProfile_base::course() const
 
 template <>
 inline valarray<double>
-CProfile_base::course( size_t m) const
+CProfile::course( size_t m) const
 {
 	return _data[ slice(m, pages(), _bins) ];
 }
@@ -178,7 +205,7 @@ CProfile_base::course( size_t m) const
 
 template <>
 inline valarray<float>
-CProfile_base::course( size_t m) const
+CProfile::course( size_t m) const
 {
 	valarray<double> course = _data[ slice(m, pages(), _bins) ];
 	valarray<float> coursef (0., course.size());
@@ -190,14 +217,14 @@ CProfile_base::course( size_t m) const
 
 template <>
 inline valarray<double>
-CProfile_base::spectrum( size_t p) const
+CProfile::spectrum( size_t p) const
 {
 	return _data[ slice(p * _bins, _bins, 1) ];
 }
 
 template <>
 inline valarray<float>
-CProfile_base::spectrum( size_t p) const
+CProfile::spectrum( size_t p) const
 {
 	valarray<double> dps = spectrum<double>(p);
 	valarray<float> ps (dps.size());
diff --git a/src/metrics/psd.cc b/src/metrics/psd.cc
index ad5d057..32e6ec9 100644
--- a/src/metrics/psd.cc
+++ b/src/metrics/psd.cc
@@ -38,24 +38,24 @@ void
 metrics::psd::SPPack::
 check() const
 {
-	if ( pagesize != 4  && pagesize != 20 &&
-	     pagesize != 30 && pagesize != 60 )
-		throw invalid_argument ("Invalid pagesize");
+	metrics::SPPack::check();
 
 	if ( welch_window_type > sigproc::TWinType::_total )
 		throw invalid_argument ("Invalid window type");
 
-	if ( binsize != .1 && binsize != .25 && binsize != .5 )
-		throw invalid_argument ("Invalid binsize");
+	for ( auto c : {.1, .25, .5} )
+		if ( binsize == c )
+			return;
+	throw invalid_argument ("Invalid binsize");
 }
 
 void
 metrics::psd::SPPack::
 reset()
 {
-	pagesize = 30;
-	welch_window_type = sigproc::TWinType::welch;
+	metrics::SPPack::reset();
 	binsize = .25;
+	welch_window_type = sigproc::TWinType::welch;
 }
 
 
@@ -67,11 +67,12 @@ reset()
 metrics::psd::CProfile::
 CProfile (const sigfile::CSource& F, int sig_no,
 	  const SPPack &fft_params)
-	: CProfile_base (F, sig_no,
-			 fft_params.pagesize,
-			 fft_params.compute_n_bins(F.samplerate(sig_no))),
-	  SPPack (fft_params)
+	: metrics::CProfile (F, sig_no,
+			     fft_params.pagesize,
+			     fft_params.compute_n_bins(F.samplerate(sig_no))),
+	  Pp (fft_params)
 {
+	Pp.check();
 }
 
 
@@ -82,79 +83,50 @@ fname_base() const
 {
 	DEF_UNIQUE_CHARP (_);
 	assert (asprintf( &_,
-			  "%s-%s-%zu-%c-%zu",
+			  "%s.%s-%zu"
+			  ":%zu-%g-%c",
 			  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-			  SPPack::pagesize, //freq_trunc,
-			  'a'+(char)welch_window_type,
-			  _signature) > 1);
+			  _using_F.dirty_signature( _using_sig_no),
+			  Pp.pagesize, Pp.binsize,
+			  'a'+(char)Pp.welch_window_type)
+		> 1);
 	string ret {_};
 	return ret;
 }
 
 
 
-
-
-int
+string
 metrics::psd::CProfile::
-compute( const SPPack& req_params,
-	 bool force)
+mirror_fname() const
 {
-      // check if we have it already
-	auto req_signature = _using_F.dirty_signature( _using_sig_no);
-	if ( have_data()
-	     && not force
-	     && (*this) == req_params
-	     && _signature == req_signature )
-		return 0;
-
-	size_t	sr = samplerate();
-	size_t	spp = sr * _pagesize;
-	TFloat	freq_max = (TFloat)(spp+1)/2 / sr;
-	_data.resize( pages() * _bins);
-	printf( "CBinnedPower::compute( %s, %s): %g sec (%zu pp @%zu + %zu sec last incomplete page); bins/size/freq_max = %zu/%g/%g",
-		_using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-		_using_F.recording_time(),
-		pages(), _pagesize, (size_t)_using_F.recording_time() - (pages() * _pagesize),
-		_bins, binsize, freq_max);
-
-	DEF_UNIQUE_CHARP (old_mirror_fname);
-	DEF_UNIQUE_CHARP (new_mirror_fname);
-
-	// insert a .
+	DEF_UNIQUE_CHARP (_);
 	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
-
-	assert (asprintf( &old_mirror_fname,
-			  "%s-%s-%zu-%g:%c-%zu.psd",
-			  basename_dot.c_str(),
-			  _using_F.channel_by_id(_using_sig_no), _pagesize, binsize,
-			  'a'+(char)welch_window_type,
-			  _signature)
+	assert (asprintf( &_,
+			  "%s.%s-%zu"
+			  ":%zu-%g-%c"
+			  ".psd",
+			  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)
 		> 1);
+	string ret {_};
+	return ret;
+}
 
-      // update signature
-	*(SPPack*)this = req_params;
-	_signature = req_signature;
-	assert (asprintf( &new_mirror_fname,
-			  "%s-%s-%zu-%g:%c-%zu.psd",
-			  basename_dot.c_str(),
-			  _using_F.channel_by_id(_using_sig_no), _pagesize, binsize,
-			  'a'+(char)welch_window_type,
-			  _signature)
-		> 1);
 
-	bool got_it = (_mirror_back( new_mirror_fname) == 0);
 
-      // remove previously saved power
-	if ( strcmp( old_mirror_fname, new_mirror_fname) )
-		if ( unlink( old_mirror_fname) ) {}
 
-	if ( got_it and not force ) {
-		printf( " (cached)\n");
-		_status |= TFlags::computed;
-		return 0;
-	}
-	printf( "\n");
+int
+metrics::psd::CProfile::
+go_compute()
+{
+	_data.resize( pages() * _bins);
+
+	size_t	sr = samplerate();
+	size_t	spp = sr * Pp.pagesize;
+//	double	freq_max = (spp+1)/2 / sr;
 
       // 0. get signal sample; always use double not TFloat
       // so that saved power is usable irrespective of what TFloat is today
@@ -211,7 +183,7 @@ compute( const SPPack& req_params,
 	{
 		size_t	t9 = spp - window,   // start of the last window but one
 			t;
-		auto wfun = sigproc::winf[sigproc::TWinType::welch];
+		auto wfun = sigproc::winf[Pp.welch_window_type];
 		for ( t = 0; t < window/2; ++t )
 			W[t] = wfun( t, window);
 		for ( t = window/2; t < window; ++t )
@@ -239,21 +211,18 @@ compute( const SPPack& req_params,
 		// the frequency resolution in P is (1/samplerate) Hz, right?
 		////memcpy( &_data[p*bins], &P[ThId][0], bins * sizeof(TFloat));
 		///printf( "n_bins = %zu, max_freq = %g\n", n_bins(), max_freq);
-		for ( f = 0., b = 0; b < _bins; (f += binsize), ++b ) {
+		for ( f = 0., b = 0; b < _bins; (f += Pp.binsize), ++b ) {
 			//printf( "b = %zu, f = %g\n", b, f);
 			nmth_bin(p, b) =
 				valarray<double>
-				(P[ slice( f*sr, (f + binsize)*sr, 1) ]) . sum();
+				(P[ slice( f*sr, (f + Pp.binsize)*sr, 1) ]) . sum();
 		}
 		/// / (bin_size * sr) // don't; power is cumulative
 	}
 
-	if ( _mirror_enable( new_mirror_fname) ) {}
-
 	fftw_free( fft_Ti);
 	fftw_free( fft_To);
 
-	_status |= TFlags::computed;
 	return 0;
 }
 
@@ -284,9 +253,9 @@ export_tsv( const string& fname) const
 		 _using_F.subject(), _using_F.session(), _using_F.episode(),
 		 (int)strlen(asctime_)-1, asctime_,
 		 _using_F.channel_by_id(_using_sig_no),
-		 pages(), _pagesize, _bins*binsize, binsize);
+		 pages(), Pp.pagesize, _bins*Pp.binsize, Pp.binsize);
 
-	for ( bin = 0; bin < _bins; ++bin, bum += binsize )
+	for ( bin = 0; bin < _bins; ++bin, bum += Pp.binsize )
 		fprintf( f, "%g%c", bum, bin+1 == _bins ? '\n' : '\t');
 
 	for ( p = 0; p < pages(); ++p ) {
@@ -320,7 +289,7 @@ export_tsv( float from, float upto,
 		 _using_F.subject(), _using_F.session(), _using_F.episode(),
 		 (int)strlen(asctime_)-1, asctime_,
 		 _using_F.channel_by_id(_using_sig_no),
-		 pages(), _pagesize, from, upto);
+		 pages(), Pp.pagesize, from, upto);
 
 	valarray<TFloat> crs = course<TFloat>( from, upto);
 	for ( size_t p = 0; p < pages(); ++p )
diff --git a/src/metrics/psd.hh b/src/metrics/psd.hh
index b69a9e4..68887d6 100644
--- a/src/metrics/psd.hh
+++ b/src/metrics/psd.hh
@@ -33,7 +33,7 @@ namespace psd {
 
 
 // this is an odd bit never used in libagh
-enum TBand : unsigned short {
+enum TBand {
 	delta,
 	theta,
 	alpha,
@@ -44,24 +44,26 @@ enum TBand : unsigned short {
 
 
 
-struct SPPack {
-	size_t	pagesize;
+struct SPPack
+  : public metrics::SPPack {
+	double	binsize;
 	sigproc::TWinType
 		welch_window_type;
-	double	binsize;
 
-	SPPack (const SPPack& rv) = default;
 	SPPack ()
 		{
 			reset();
 		}
 
-	SPPack& operator=( const SPPack& rv) = default;
-	bool operator==( const SPPack& rv) const
+	bool same_as( const SPPack& rv) const
 		{
-			return	pagesize == rv.pagesize &&
-				welch_window_type == rv.welch_window_type &&
-				binsize == rv.binsize;
+			return	metrics::SPPack::same_as(rv) &&
+				welch_window_type == rv.welch_window_type;
+		}
+	void make_same( const SPPack& rv)
+		{
+			metrics::SPPack::make_same(rv);
+			welch_window_type = rv.welch_window_type;
 		}
 
 	size_t
@@ -79,14 +81,14 @@ struct SPPack {
 
 
 class CProfile
-  : public CProfile_base,
-    public SPPack {
+  : public metrics::CProfile {
 
-    protected:
+    public:
 	CProfile (const sigfile::CSource&, int sig_no,
 		  const SPPack&);
 
-    public:
+	SPPack Pp;
+
 	const char* method() const
 		{
 			return metric_method( TType::psd);
@@ -97,27 +99,26 @@ class CProfile
 	valarray<T> course( float from, float upto) const
 		{
 			valarray<T> acc (0., pages());
-			size_t	bin_a = min( (size_t)(from / binsize), _bins),
-				bin_z = min( (size_t)(upto / binsize), _bins);
+			size_t	bin_a = min( (size_t)(from / Pp.binsize), _bins),
+				bin_z = min( (size_t)(upto / Pp.binsize), _bins);
 			for ( size_t b = bin_a; b < bin_z; ++b )
-				acc += CProfile_base::course<T>(b);
+				acc += metrics::CProfile::course<T>(b);
 			return acc;
 		}
 
-      // obtain
-	int compute( const SPPack& req_params,
-		     bool force = false);
-	int compute( bool force = false)
-	// possibly reuse that already obtained unless factors affecting signal or fft are different
-		{
-			return compute( *this, force);
-		}
+	int go_compute();
+	string mirror_fname() const;
 
 	string fname_base() const;
 
-	int export_tsv( const string& fname) const;
-	int export_tsv( float from, float upto,
-			const string& fname) const;
+	int export_tsv( const string&) const;
+	int export_tsv( float, float,
+			const string&) const;
+
+	// to enable use as mapped type
+	CProfile (const CProfile& rv)
+	      : metrics::CProfile (rv)
+		{}
 };
 
 } // namespace psd
diff --git a/src/metrics/swu.cc b/src/metrics/swu.cc
index b24bcc4..51257db 100644
--- a/src/metrics/swu.cc
+++ b/src/metrics/swu.cc
@@ -29,20 +29,14 @@ void
 metrics::swu::SPPack::
 check() const
 {
-	if ( pagesize != 4  && pagesize != 20 &&
-	     pagesize != 30 && pagesize != 60 )
-		throw invalid_argument ("Invalid pagesize");
-
-	if ( binsize != .1 && binsize != .25 && binsize != .5 )
-		throw invalid_argument ("Invalid binsize");
+	metrics::SPPack::check();
 }
 
 void
 metrics::swu::SPPack::
 reset()
 {
-	pagesize = 30;
-	binsize = .25;
+	metrics::SPPack::reset();
 }
 
 
@@ -54,11 +48,12 @@ reset()
 metrics::swu::CProfile::
 CProfile (const sigfile::CSource& F, int sig_no,
 	  const SPPack &params)
-	: CProfile_base (F, sig_no,
-			 params.pagesize,
-			 params.compute_n_bins(F.samplerate(sig_no))),
-	  SPPack (params)
+	: metrics::CProfile (F, sig_no,
+			     params.pagesize,
+			     params.compute_n_bins(F.samplerate(sig_no))),
+	  Pp (params)
 {
+	Pp.check();
 }
 
 
@@ -69,89 +64,51 @@ fname_base() const
 {
 	DEF_UNIQUE_CHARP (_);
 	assert (asprintf( &_,
-			  "%s-%s-%zu-%zu",
+			  "%s.%s-%zu"
+			  ":%zu",
 			  _using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-			  SPPack::pagesize, //freq_trunc,
-			  _signature) > 1);
+			  _using_F.dirty_signature( _using_sig_no),
+			  Pp.pagesize)
+		> 1);
 	string ret {_};
 	return ret;
 }
 
 
-
-
-
-int
+string
 metrics::swu::CProfile::
-compute( const SPPack& req_params,
-	 bool force)
+mirror_fname() const
 {
-      // check if we have it already
-	auto req_signature = _using_F.dirty_signature( _using_sig_no);
-	if ( have_data()
-	     && not force
-	     && (*this) == req_params
-	     && _signature == req_signature )
-		return 0;
-
-	size_t	sr = samplerate();
-	size_t	spp = sr * _pagesize;
-	TFloat	freq_max = (TFloat)(spp+1)/2 / sr;
-	_data.resize( pages() * _bins);
-	printf( "CBinnedSWU::compute( %s, %s): %g sec (%zu pp @%zu + %zu sec last incomplete page); bins/size/freq_max = %zu/%g/%g",
-		_using_F.filename(), _using_F.channel_by_id(_using_sig_no),
-		_using_F.recording_time(),
-		pages(), _pagesize, (size_t)_using_F.recording_time() - (pages() * _pagesize),
-		_bins, binsize, freq_max);
-
-	DEF_UNIQUE_CHARP (old_mirror_fname);
-	DEF_UNIQUE_CHARP (new_mirror_fname);
-
-	// insert a .
+	DEF_UNIQUE_CHARP (_);
 	string basename_dot = agh::fs::make_fname_base (_using_F.filename(), "", true);
-
-	assert (asprintf( &old_mirror_fname,
-			  "%s-%s-%zu-%g-%zu.psd",
-			  basename_dot.c_str(),
-			  _using_F.channel_by_id(_using_sig_no), _pagesize, binsize,
-			  _signature)
-		> 1);
-
-      // update signature
-	*(SPPack*)this = req_params;
-	_signature = req_signature;
-	assert (asprintf( &new_mirror_fname,
-			  "%s-%s-%zu-%g-%zu.psd",
-			  basename_dot.c_str(),
-			  _using_F.channel_by_id(_using_sig_no), _pagesize, binsize,
-			  _signature)
+	assert (asprintf( &_,
+			  "%s.%s-%zu"
+			  ":%zu"
+			  ".swu",
+			  basename_dot.c_str(), _using_F.channel_by_id(_using_sig_no),
+			  _using_F.dirty_signature( _using_sig_no),
+			  Pp.pagesize)
 		> 1);
+	string ret {_};
+	return ret;
+}
 
-	bool got_it = (_mirror_back( new_mirror_fname) == 0);
-
-      // remove previously saved power
-	if ( strcmp( old_mirror_fname, new_mirror_fname) )
-		if ( unlink( old_mirror_fname) ) {}
 
-	if ( got_it and not force ) {
-		printf( " (cached)\n");
-		_status |= TFlags::computed;
-		return 0;
-	}
-	printf( "\n");
+int
+metrics::swu::CProfile::
+go_compute()
+{
+	_data.resize( pages() * _bins);
 
       // 0. get signal sample; always use double not TFloat
       // so that saved power is usable irrespective of what TFloat is today
-	valarray<double> S = to_vad( _using_F.get_signal_filtered( _using_sig_no));
+	auto S = _using_F.get_signal_filtered( _using_sig_no);
 
 	for ( size_t p = 0; p < pages(); ++p ) {
 		nmth_bin(p, 0) =
 			sin(p * M_PI);
 	}
 
-	if ( _mirror_enable( new_mirror_fname) ) {}
-
-	_status |= TFlags::computed;
 	return 0;
 }
 
@@ -171,58 +128,18 @@ export_tsv( const string& fname) const
 	if ( !f )
 		return -1;
 
-	size_t bin, p;
-	float bum = 0.;
-
 	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",
+		 "## SWU course (%zu %zu-sec pages)\n"
+		 "#Page\tSWU\n",
 		 _using_F.subject(), _using_F.session(), _using_F.episode(),
 		 (int)strlen(asctime_)-1, asctime_,
 		 _using_F.channel_by_id(_using_sig_no),
-		 pages(), _pagesize, _bins*binsize, binsize);
-
-	for ( bin = 0; bin < _bins; ++bin, bum += binsize )
-		fprintf( f, "%g%c", bum, bin+1 == _bins ? '\n' : '\t');
-
-	for ( p = 0; p < pages(); ++p ) {
-		fprintf( f, "%zu", p);
-		for ( bin = 0; bin < _bins; ++bin )
-			fprintf( f, "\t%g", nmth_bin( p, bin));
-		fprintf( f, "\n");
-	}
+		 pages(), Pp.pagesize);
 
-	fclose( f);
-	return 0;
-}
-
-
-
-
-int
-metrics::swu::CProfile::
-export_tsv( float from, float upto,
-	    const string& fname) const
-{
-	FILE *f = fopen( fname.c_str(), "w");
-	if ( !f )
-		return -1;
-
-	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(),
-		 (int)strlen(asctime_)-1, asctime_,
-		 _using_F.channel_by_id(_using_sig_no),
-		 pages(), _pagesize, from, upto);
-
-	valarray<TFloat> crs = course<TFloat>( from, upto);
 	for ( size_t p = 0; p < pages(); ++p )
-		fprintf( f, "%zu\t%g\n", p, crs[p]);
+		fprintf( f, "%zu\t%g\n", p, nmth_bin( p, 0));
 
 	fclose( f);
 	return 0;
@@ -230,4 +147,5 @@ export_tsv( float from, float upto,
 
 
 
+
 // eof
diff --git a/src/metrics/swu.hh b/src/metrics/swu.hh
index a3bd467..67ab9fd 100644
--- a/src/metrics/swu.hh
+++ b/src/metrics/swu.hh
@@ -31,27 +31,13 @@ namespace metrics {
 namespace swu {
 
 
-struct SPPack {
-	size_t	pagesize;
-	double	binsize;
-
-	SPPack (const SPPack&) = default;
-	SPPack ()
-		{
-			reset();
-		}
-
-	SPPack& operator=( const SPPack&) = default;
-	bool operator==( const SPPack& rv) const
-		{
-			return	pagesize == rv.pagesize &&
-				binsize == rv.binsize;
-		}
+struct SPPack
+  : public metrics:: SPPack {
 
 	size_t
-	compute_n_bins( size_t samplerate) const
+	compute_n_bins( size_t _samplerate) const
 		{
-			return (samplerate * pagesize + 1) / 2 / samplerate / binsize;
+			return 1;
 		}
 
 	void check() const;  // throws if not ok
@@ -60,48 +46,33 @@ struct SPPack {
 
 
 
-
-
-
 class CProfile
-  : public CProfile_base,
-    public SPPack {
+  : public metrics::CProfile {
 
-    protected:
+    public:
 	CProfile (const sigfile::CSource&, int sig_no,
 		  const SPPack&);
 
-    public:
+	SPPack Pp;
+
 	const char* method() const
 		{
 			return metric_method( TType::swu);
 		}
 
-	// in a frequency range
-	template <class T>
-	valarray<T> course( float from, float upto) const
-		{
-			valarray<T> acc (0., pages());
-			size_t	bin_a = min( (size_t)(from / binsize), _bins),
-				bin_z = min( (size_t)(upto / binsize), _bins);
-			for ( size_t b = bin_a; b < bin_z; ++b )
-				acc += CProfile_base::course<T>(b);
-			return acc;
-		}
-
-      // obtain
-	int compute( const SPPack& req_params,
-		     bool force = false);
-	int compute( bool force = false)
-		{
-			return compute( *this, force);
-		}
+	int go_compute();
 
 	string fname_base() const;
+	string mirror_fname() const;
+
+	int export_tsv( const string&) const;
+	int export_tsv( float, float,
+			const string&) const;
 
-	int export_tsv( const string& fname) const;
-	int export_tsv( float from, float upto,
-			const string& fname) const;
+	// to enable use as mapped type
+	CProfile (const CProfile& rv)
+	      : metrics::CProfile (rv)
+		{}
 };
 
 } // namespace swu
diff --git a/src/model/assisted-score.cc b/src/model/assisted-score.cc
index e88b84e..112fe6a 100644
--- a/src/model/assisted-score.cc
+++ b/src/model/assisted-score.cc
@@ -28,15 +28,15 @@ assisted_score( agh::CSubject::SEpisode& E)
 {
 	forward_list<agh::CRecording*> HH;
 	for ( auto &R : E.recordings )
-		if ( R.second.metrics::psd::CProfile::have_data() )
+		if ( R.second.psd_profile.have_data() )
 			HH.push_front( &R.second);
 
 	forward_list<valarray<TFloat>>
 		courses_delta,
 		courses_theta;
 	for ( auto &H : HH ) {
-		courses_delta.emplace_front( H->metrics::psd::CProfile::course<TFloat>( 2., 3.));
-		courses_theta.emplace_front( H->metrics::psd::CProfile::course<TFloat>( 5., 8.));
+		courses_delta.emplace_front( H->psd_profile.course<TFloat>( 2., 3.));
+		courses_theta.emplace_front( H->psd_profile.course<TFloat>( 5., 8.));
 	}
 
 	auto& firstsource = E.sources.front();
diff --git a/src/model/ultradian-cycle.cc b/src/model/ultradian-cycle.cc
index 3f5cccc..10b15a5 100644
--- a/src/model/ultradian-cycle.cc
+++ b/src/model/ultradian-cycle.cc
@@ -162,7 +162,7 @@ ultradian_cycles( agh::CRecording& M,
 {
 	// normalize please
 	auto course = M.course<TFloat>( C.metric, C.freq_from, C.freq_upto);
-	sigproc::smooth( course, (size_t)5);
+	sigproc::smooth( course, 5u);
 	//auto avg = course.sum()/course.size();
 	course /= course.max() / 2; // because ultradian cycle function has a range of 2
 
diff --git a/src/ui/mw/mw-admit-one.cc b/src/ui/mw/mw-admit-one.cc
index 21b1e0a..e4e9b36 100644
--- a/src/ui/mw/mw-admit-one.cc
+++ b/src/ui/mw/mw-admit-one.cc
@@ -192,14 +192,14 @@ check_gtk_entry_nonempty_cb( GtkEditable *ignored,
 
 
 void
-common_drag_data_received_cb( GtkWidget        *widget,
-			      GdkDragContext   *context,
-			      gint              x,
-			      gint              y,
-			      GtkSelectionData *selection_data,
-			      guint             info,
-			      guint             time,
-			      gpointer          userdata)
+cMeasurements_drag_data_received_cb( GtkWidget        *widget,
+				     GdkDragContext   *context,
+				     gint              x,
+				     gint              y,
+				     GtkSelectionData *selection_data,
+				     guint             info,
+				     guint             time,
+				     gpointer          userdata)
 {
 	auto& ED = *(SExpDesignUI*)userdata;
 
@@ -231,12 +231,12 @@ common_drag_data_received_cb( GtkWidget        *widget,
 
 gboolean
 __attribute__ ((const))
-common_drag_drop_cb( GtkWidget      *widget,
-		     GdkDragContext *context,
-		     gint            x,
-		     gint            y,
-		     guint           time,
-		     gpointer        userdata)
+cMeasurements_drag_drop_cb( GtkWidget      *widget,
+			    GdkDragContext *context,
+			    gint            x,
+			    gint            y,
+			    guint           time,
+			    gpointer        userdata)
 {
 		//auto& ED = *(SExpDesignUI*)userdata;
 //	GdkAtom         target_type;
diff --git a/src/ui/mw/mw-construct.cc b/src/ui/mw/mw-construct.cc
index ccc936e..0e96aed 100644
--- a/src/ui/mw/mw-construct.cc
+++ b/src/ui/mw/mw-construct.cc
@@ -78,6 +78,21 @@ SExpDesignUIWidgets ()
 
       // =========== 1. Measurements
       // ------------- cMeasurements
+	if ( !AGH_GBGETOBJ (GtkWindow,		wMainWindow) ||
+	     !AGH_GBGETOBJ (GtkVBox,		cMeasurements) )
+		throw runtime_error ("Failed to construct widgets");
+
+	wMainWindow_delete_event_cb_handler_id =
+		G_CONNECT_2 (wMainWindow, delete, event);
+	G_CONNECT_2 (wMainWindow, configure, event);
+
+	G_CONNECT_3 (cMeasurements, drag, data, received);
+	G_CONNECT_2 (cMeasurements, drag, drop);
+
+	gtk_drag_dest_set( (GtkWidget*)cMeasurements, GTK_DEST_DEFAULT_ALL,
+			   NULL, 0, GDK_ACTION_COPY);
+	gtk_drag_dest_add_uri_targets( (GtkWidget*)(cMeasurements));
+
 	if ( !AGH_GBGETOBJ (GtkMenuItem,	iiMainMenu) ||
 	     !AGH_GBGETOBJ (GtkMenuItem,	iExpRefresh) ||
 	     !AGH_GBGETOBJ (GtkMenuItem,	iExpPurgeComputed) ||
@@ -93,65 +108,20 @@ SExpDesignUIWidgets ()
 	     !AGH_GBGETOBJ (GtkMenuItem,	iHelpUsage) )
 		throw runtime_error ("Failed to construct widgets");
 
-	g_signal_connect( iExpClose, "activate",
-			  (GCallback)iExpClose_activate_cb,
-			  this);
-	g_signal_connect( iExpRefresh, "activate",
-			  (GCallback)iExpRefresh_activate_cb,
-			  this);
-	g_signal_connect( iExpPurgeComputed, "activate",
-			  (GCallback)iExpPurgeComputed_activate_cb,
-			  this);
-	g_signal_connect( iExpAnnotations, "activate",
-			  (GCallback)iExpAnnotations_activate_cb,
-			  this);
-	g_signal_connect( iExpBasicSADetectUltradianCycles, "activate",
-			  (GCallback)iExpBasicSADetectUltradianCycles_activate_cb,
-			  this);
-	g_signal_connect( iExpGloballyDetectArtifacts, "activate",
-			  (GCallback)iExpGloballyDetectArtifacts_activate_cb,
-			  this);
-	g_signal_connect( iExpGloballySetFilters, "activate",
-			  (GCallback)iExpGloballySetFilters_activate_cb,
-			  this);
-	// g_signal_connect( iMontageSetDefaults, "activate",
-	// 		  (GCallback)iMontageSetDefaults_activate_cb,
+	G_CONNECT_1 (iExpClose, activate);
+	// g_signal_connect( iExpClose, "activate",
+	// 		  (GCallback)iExpClose_activate_cb,
 	// 		  this);
-	g_signal_connect( iExpQuit, "activate",
-			  (GCallback)iExpQuit_activate_cb,
-			  this);
-	g_signal_connect( iHelpAbout, "activate",
-			  (GCallback)iHelpAbout_activate_cb,
-			  this);
-	g_signal_connect( iHelpUsage, "activate",
-			  (GCallback)iHelpUsage_activate_cb,
-			  this);
-
-	if ( !AGH_GBGETOBJ (GtkWindow,		wMainWindow) ||
-	     !AGH_GBGETOBJ (GtkVBox,		cMeasurements) ||
-	     !AGH_GBGETOBJ (GtkLabel,		lMsmtPSDInfo) ||
-	     !AGH_GBGETOBJ (GtkLabel,		lMsmtMCInfo) )
-		throw runtime_error ("Failed to construct widgets");
-
-	wMainWindow_delete_event_cb_handler_id =
-		g_signal_connect( wMainWindow, "delete-event",
-				  (GCallback)wMainWindow_delete_event_cb,
-				  this);
-	g_signal_connect( wMainWindow, "configure-event",
-			  (GCallback)wMainWindow_configure_event_cb,
-			  this);
-
-	g_signal_connect( cMeasurements, "drag-data-received",
-			  (GCallback)common_drag_data_received_cb,
-			  this);
-	g_signal_connect( cMeasurements, "drag-drop",
-			  (GCallback)common_drag_drop_cb,
-			  this);
-
-	gtk_drag_dest_set( (GtkWidget*)cMeasurements, GTK_DEST_DEFAULT_ALL,
-			   NULL, 0, GDK_ACTION_COPY);
-	gtk_drag_dest_add_uri_targets( (GtkWidget*)(cMeasurements));
-
+	G_CONNECT_1 (iExpRefresh, activate);
+	G_CONNECT_1 (iExpPurgeComputed, activate);
+	G_CONNECT_1 (iExpAnnotations, activate);
+	G_CONNECT_1 (iExpBasicSADetectUltradianCycles, activate);
+	G_CONNECT_1 (iExpGloballyDetectArtifacts, activate);
+	G_CONNECT_1 (iExpGloballySetFilters, activate);
+	// G_CONNECT_1 (iMontageSetDefaults, activate);
+	G_CONNECT_1 (iExpQuit, activate);
+	G_CONNECT_1 (iHelpAbout, activate);
+	G_CONNECT_1 (iHelpUsage, activate);
 
      // --------- tabs
 	if ( !AGH_GBGETOBJ (GtkNotebook,	tTaskSelector) ||
@@ -163,15 +133,9 @@ SExpDesignUIWidgets ()
 	     !AGH_GBGETOBJ (GtkLabel,		lSettings) )
 		throw runtime_error ("Failed to construct widgets");
 
-	g_signal_connect( tTaskSelector, "switch-page",
-			  (GCallback)tTaskSelector_switch_page_cb,
-			  this);
-	g_signal_connect( tDesign, "switch-page",
-			  (GCallback)tDesign_switch_page_cb,
-			  this);
-	g_signal_connect( tSimulations, "switch-page",
-			  (GCallback)tSimulations_switch_page_cb,
-			  this);
+	G_CONNECT_2 (tTaskSelector, switch, page);
+	G_CONNECT_2 (tDesign, switch, page);
+	G_CONNECT_2 (tSimulations, switch, page);
 
 
      // ------------- eMsmtSession, eMsmtChannel
@@ -182,32 +146,34 @@ SExpDesignUIWidgets ()
 	gtk_combo_box_set_model_properly(
 		eMsmtSession, mSessions);
 	eMsmtSession_changed_cb_handler_id =
-		g_signal_connect( eMsmtSession, "changed",
-				  (GCallback)eMsmtSession_changed_cb,
-				  this);
+		G_CONNECT_1 (eMsmtSession, changed);
 
 	gtk_combo_box_set_model_properly(
 		eMsmtChannel, mEEGChannels);
 	eMsmtChannel_changed_cb_handler_id =
-		g_signal_connect( eMsmtChannel, "changed",
-				  (GCallback)eMsmtChannel_changed_cb,
-				  this);
+		G_CONNECT_1 (eMsmtChannel, changed);
 
      // ------------- eMsmtProfile*
 	if ( !AGH_GBGETOBJ (GtkToggleButton,	eMsmtProfileAutoscale) ||
 	     !AGH_GBGETOBJ (GtkScaleButton,	eMsmtProfileSmooth) ||
+
 	     !AGH_GBGETOBJ (GtkListStore,	mMsmtProfileType) ||
 	     !AGH_GBGETOBJ (GtkComboBox,	eMsmtProfileType) ||
-	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParams1) ||
-	     !AGH_GBGETOBJ (GtkSpinButton,	eMsmtOpFreqFrom)  ||
-	     !AGH_GBGETOBJ (GtkSpinButton,	eMsmtOpFreqWidth) ||
-	     !AGH_GBGETOBJ (GtkAdjustment,	jMsmtOpFreqFrom)  ||
-	     !AGH_GBGETOBJ (GtkAdjustment,	jMsmtOpFreqWidth) ||
-	     !AGH_GBGETOBJ (GtkBox,		cMsmtMainToolbar) ||
-	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParams1) ||
-	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParams2) ||
-	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParams3) ||
-	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParamsContainer) )
+	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParamsContainer) ||
+	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParamsPSD) ||
+	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParamsSWU) ||
+	     !AGH_GBGETOBJ (GtkBox,		cMsmtProfileParamsMC) ||
+
+	     !AGH_GBGETOBJ (GtkSpinButton,	eMsmtProfileParamsPSDFreqFrom)  ||
+	     !AGH_GBGETOBJ (GtkSpinButton,	eMsmtProfileParamsPSDFreqWidth) ||
+	     !AGH_GBGETOBJ (GtkAdjustment,	jMsmtProfileParamsPSDFreqFrom)  ||
+	     !AGH_GBGETOBJ (GtkAdjustment,	jMsmtProfileParamsPSDFreqWidth) ||
+
+	     !AGH_GBGETOBJ (GtkLabel,		lMsmtProfilePSDExtra) ||
+	     !AGH_GBGETOBJ (GtkLabel,		lMsmtProfileSWUExtra) ||
+	     !AGH_GBGETOBJ (GtkLabel,		lMsmtProfileMCExtra) ||
+
+	     !AGH_GBGETOBJ (GtkBox,		cMsmtMainToolbar) )
 		throw runtime_error ("Failed to construct widgets");
 
 	renderer = gtk_cell_renderer_text_new();
@@ -217,23 +183,12 @@ SExpDesignUIWidgets ()
 					NULL);
 	// and when was the list store attached to it, eh?
 
-	g_signal_connect( eMsmtProfileType, "changed",
-			  (GCallback)eMsmtProfileType_changed_cb,
-			  this);
-
-	g_signal_connect( eMsmtProfileAutoscale, "toggled",
-			  (GCallback)eMsmtProfileAutoscale_toggled_cb,
-			  this);
-	g_signal_connect( eMsmtProfileSmooth, "value-changed",
-			  (GCallback)eMsmtProfileSmooth_value_changed_cb,
-			  this);
+	G_CONNECT_1 (eMsmtProfileType, changed);
+	G_CONNECT_1 (eMsmtProfileAutoscale, toggled);
+	G_CONNECT_2 (eMsmtProfileSmooth, value, changed);
 
-	g_signal_connect( eMsmtOpFreqFrom, "value-changed",
-			  (GCallback)eMsmtOpFreqFrom_value_changed_cb,
-			  this);
-	g_signal_connect( eMsmtOpFreqWidth, "value-changed",
-			  (GCallback)eMsmtOpFreqWidth_value_changed_cb,
-			  this);
+	G_CONNECT_2 (eMsmtProfileParamsPSDFreqFrom, value, changed);
+	G_CONNECT_2 (eMsmtProfileParamsPSDFreqWidth, value, changed);
 
       // ------------ menus
 	if ( !(AGH_GBGETOBJ (GtkMenu,		iiSubjectTimeline)) ||
@@ -255,35 +210,19 @@ SExpDesignUIWidgets ()
 	g_object_ref( (GObject*)iSubjectTimelineResetMontage);
 	g_object_ref( (GObject*)iSubjectTimelineBrowse);
 
-	g_signal_connect( iSubjectTimelineScore, "activate",
-			  (GCallback)iSubjectTimelineScore_activate_cb,
-			  this);
-	g_signal_connect( iSubjectTimelineDetectUltradianCycle, "activate",
-			  (GCallback)iSubjectTimelineDetectUltradianCycle_activate_cb,
-			  this);
-	g_signal_connect( iSubjectTimelineSubjectInfo, "activate",
-			  (GCallback)iSubjectTimelineSubjectInfo_activate_cb,
-			  this);
-	g_signal_connect( iSubjectTimelineEDFInfo, "activate",
-			  (GCallback)iSubjectTimelineEDFInfo_activate_cb,
-			  this);
-	g_signal_connect( iSubjectTimelineSaveAsSVG, "activate",
-			  (GCallback)iSubjectTimelineSaveAsSVG_activate_cb,
-			  this);
-	g_signal_connect( iSubjectTimelineBrowse, "activate",
-			  (GCallback)iSubjectTimelineBrowse_activate_cb,
-			  this);
-	g_signal_connect( iSubjectTimelineResetMontage, "activate",
-			  (GCallback)iSubjectTimelineResetMontage_activate_cb,
-			  this);
+	G_CONNECT_1 (iSubjectTimelineScore, activate);
+	G_CONNECT_1 (iSubjectTimelineDetectUltradianCycle, activate);
+	G_CONNECT_1 (iSubjectTimelineSubjectInfo, activate);
+	G_CONNECT_1 (iSubjectTimelineEDFInfo, activate);
+	G_CONNECT_1 (iSubjectTimelineSaveAsSVG, activate);
+	G_CONNECT_1 (iSubjectTimelineBrowse, activate);
+	G_CONNECT_1 (iSubjectTimelineResetMontage, activate);
 
       // ------------ actions
 	if ( !(AGH_GBGETOBJ (GtkButton,		bMainCloseThatSF)) )
 		throw runtime_error ("Failed to construct widgets");
 
-	g_signal_connect( bMainCloseThatSF, "clicked",
-			  (GCallback)bMainCloseThatSF_clicked_cb,
-			  this);
+	G_CONNECT_1 (bMainCloseThatSF, clicked);
 
    // ================ 2. Simulations
      // ------------- tvSimulations & controls
@@ -301,9 +240,7 @@ SExpDesignUIWidgets ()
 	g_signal_connect( tvSimulations, "map",
 			  (GCallback)gtk_tree_view_expand_all,
 			  NULL);
-	g_signal_connect( tvSimulations, "row-activated",
-			  (GCallback)tvSimulations_row_activated_cb,
-			  this);
+	G_CONNECT_2 (tvSimulations, row, activated);
 
 	for ( auto c = 0; c < msimulations_visibility_switch_col; ++c ) {
 		renderer = gtk_cell_renderer_text_new();
@@ -340,15 +277,9 @@ SExpDesignUIWidgets ()
 	     !(AGH_GBGETOBJ (GtkMenuItem, iSimulationsReportGenerate)) )
 		throw runtime_error ("Failed to construct widgets");
 
-	g_signal_connect( iSimulationsRunBatch, "activate",
-			  (GCallback)iSimulationsRunBatch_activate_cb,
-			  this);
-	g_signal_connect( iSimulationsRunClearAll, "activate",
-			  (GCallback)iSimulationsRunClearAll_activate_cb,
-			  this);
-	g_signal_connect( iSimulationsReportGenerate, "activate",
-			  (GCallback)iSimulationsReportGenerate_activate_cb,
-			  this);
+	G_CONNECT_1 (iSimulationsRunBatch, activate);
+	G_CONNECT_1 (iSimulationsRunClearAll, activate);
+	G_CONNECT_1 (iSimulationsReportGenerate, activate);
 
       // ------------- lSimulations{Session,Channel}
 	if ( !AGH_GBGETOBJ (GtkLabel, lSimulationsProfile) ||
@@ -467,15 +398,9 @@ SExpDesignUIWidgets ()
 	     !AGH_GBGETOBJ (GtkSpinButton,	eCtlParamReqScoredPercent) )
 		throw runtime_error ("Failed to construct widgets");
 
-	g_signal_connect( eCtlParamDBAmendment1, "toggled",
-			  (GCallback)eCtlParamDBAmendment1_toggled_cb,
-			  this);
-	g_signal_connect( eCtlParamDBAmendment2, "toggled",
-			  (GCallback)eCtlParamDBAmendment2_toggled_cb,
-			  this);
-	g_signal_connect( eCtlParamAZAmendment1, "toggled",
-			  (GCallback)eCtlParamAZAmendment1_toggled_cb,
-			  this);
+	G_CONNECT_1 (eCtlParamDBAmendment1, toggled);
+	G_CONNECT_1 (eCtlParamDBAmendment2, toggled);
+	G_CONNECT_1 (eCtlParamAZAmendment1, toggled);
 
       // ------------- eTunable_*
 	using namespace agh::ach;
@@ -532,9 +457,7 @@ SExpDesignUIWidgets ()
 
 	if ( !AGH_GBGETOBJ (GtkButton,	bSimParamRevertTunables) )
 		throw runtime_error ("Failed to construct widgets");
-	g_signal_connect( bSimParamRevertTunables, "clicked",
-			  (GCallback)bSimParamRevertTunables_clicked_cb,
-			  this);
+	G_CONNECT_1 (bSimParamRevertTunables, clicked);
 
       // ------ colours
 	if ( !(CwB[TColour::night	  ].btn = (GtkColorButton*)gtk_builder_get_object( builder, "bColourNight")) ||
@@ -699,9 +622,7 @@ SExpDesignUIWidgets ()
 	g_signal_connect( tvGlobalAnnotations, "map",
 			  (GCallback)gtk_tree_view_expand_all,
 			  NULL);
-	g_signal_connect( tvGlobalAnnotations, "row-activated",
-			  (GCallback)tvGlobalAnnotations_row_activated_cb,
-			  this);
+	G_CONNECT_2 (tvGlobalAnnotations, row, activated);
 
 	renderer = gtk_cell_renderer_text_new();
 	int c = 0;
@@ -733,9 +654,7 @@ SExpDesignUIWidgets ()
 
 	gtk_combo_box_set_model_properly(
 		eGlobalADProfiles, mGlobalADProfiles);
-	g_signal_connect( eGlobalADProfiles, "changed",
-			  (GCallback)eGlobalADProfiles_changed_cb,
-			  this);
+	G_CONNECT_1 (eGlobalADProfiles, changed);
 
 	pango_font_description_free( font_desc);
 }
diff --git a/src/ui/mw/mw-populate.cc b/src/ui/mw/mw-populate.cc
index 6714d71..fdc6e2e 100644
--- a/src/ui/mw/mw-populate.cc
+++ b/src/ui/mw/mw-populate.cc
@@ -100,23 +100,23 @@ populate( bool do_load)
 		switch ( display_profile_type ) {
 		case metrics::TType::psd:
 			gtk_combo_box_set_active( eMsmtProfileType, 0);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams1, TRUE);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams2, FALSE);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams3, FALSE);
-			gtk_widget_grab_focus( (GtkWidget*)eMsmtOpFreqFrom);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsPSD, TRUE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsSWU, FALSE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsMC, FALSE);
+			gtk_widget_grab_focus( (GtkWidget*)eMsmtProfileParamsPSDFreqFrom);
 		    break;
 		case metrics::TType::swu:
 			gtk_combo_box_set_active( eMsmtProfileType, 1);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams1, FALSE);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams2, TRUE);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams3, FALSE);
-			gtk_widget_grab_focus( (GtkWidget*)eMsmtOpFreqFrom);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsPSD, FALSE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsSWU, TRUE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsMC, FALSE);
+			gtk_widget_grab_focus( (GtkWidget*)eMsmtProfileParamsPSDFreqFrom);
 		    break;
 		case metrics::TType::mc:
 			gtk_combo_box_set_active( eMsmtProfileType, 2);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams1, FALSE);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams2, FALSE);
-			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParams3, TRUE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsPSD, FALSE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsSWU, FALSE);
+			gtk_widget_set_visible( (GtkWidget*)cMsmtProfileParamsMC, TRUE);
 		    break;
 		default:
 			// throw something
@@ -364,8 +364,8 @@ populate_1()
 
       // touch toolbar controls
 	suppress_redraw = true;
-	gtk_spin_button_set_value( eMsmtOpFreqFrom, operating_range_from);
-	gtk_spin_button_set_value( eMsmtOpFreqWidth, operating_range_upto - operating_range_from);
+	gtk_spin_button_set_value( eMsmtProfileParamsPSDFreqFrom, operating_range_from);
+	gtk_spin_button_set_value( eMsmtProfileParamsPSDFreqWidth, operating_range_upto - operating_range_from);
 
       // deal with the main drawing area
 	groups.clear();
@@ -505,10 +505,10 @@ populate_1()
 					  &J);
 
 			g_signal_connect( J.da, "drag-data-received",
-					  (GCallback)common_drag_data_received_cb,
+					  (GCallback)cMeasurements_drag_data_received_cb,
 					  this);
 			g_signal_connect( J.da, "drag-drop",
-					  (GCallback)common_drag_drop_cb,
+					  (GCallback)cMeasurements_drag_drop_cb,
 					  this);
 			gtk_drag_dest_set( J.da, GTK_DEST_DEFAULT_ALL,
 					   NULL, 0, GDK_ACTION_COPY);
@@ -531,13 +531,13 @@ populate_1()
 		      ED->fft_params.pagesize,
 		      ED->fft_params.binsize,
 		      sigproc::welch_window_type_names[ED->fft_params.welch_window_type]);
-	gtk_label_set_markup( lMsmtPSDInfo, __buf__);
+	gtk_label_set_markup( lMsmtProfilePSDExtra, __buf__);
 
 	snprintf_buf( "<small>%gHz/%g/%g</small>",
 		      ED->mc_params.bandwidth,
 		      ED->mc_params.iir_backpolate,
 		      ED->mc_params.mc_gain);
-	gtk_label_set_markup( lMsmtMCInfo, __buf__);
+	gtk_label_set_markup( lMsmtProfileMCExtra, __buf__);
 
 	suppress_redraw = false;
 //	set_cursor_busy( false, (GtkWidget*)wMainWindow);
diff --git a/src/ui/mw/mw-settings_cb.cc b/src/ui/mw/mw-settings_cb.cc
index 8377c08..ecd0582 100644
--- a/src/ui/mw/mw-settings_cb.cc
+++ b/src/ui/mw/mw-settings_cb.cc
@@ -51,7 +51,7 @@ tDesign_switch_page_cb( GtkNotebook*, gpointer, guint page_num, gpointer userdat
 		}
 
 		try {
-			ED.ED->mc_params.check( ED.ED->fft_params.pagesize);
+			ED.ED->mc_params.check();
 		} catch (invalid_argument ex) {
 			pop_ok_message( ED.wMainWindow, "Invalid uC parameters", "Resetting to defaults.");
 			ED.ED->mc_params.reset();
@@ -69,7 +69,7 @@ tDesign_switch_page_cb( GtkNotebook*, gpointer, guint page_num, gpointer userdat
 		     ED.fft_params_welch_window_type_saved  	!= ED.ED->fft_params.welch_window_type ||
 		     ED.af_dampen_window_type_saved  		!= ED.ED->af_dampen_window_type ||
 		     ED.af_dampen_factor_saved	  		!= ED.ED->af_dampen_factor ||
-		     !(ED.ED->mc_params				== ED.mc_params_saved) ) {
+		     !ED.ED->mc_params.same_as( ED.mc_params_saved) ) {
 		      // rescan tree
 			ED.do_rescan_tree(); // with populate
 		} else if ( ED.timeline_height_saved			!= ED.timeline_height ||
diff --git a/src/ui/mw/mw-widgets.hh b/src/ui/mw/mw-widgets.hh
index 1792e37..f4c902f 100644
--- a/src/ui/mw/mw-widgets.hh
+++ b/src/ui/mw/mw-widgets.hh
@@ -103,27 +103,29 @@ struct SExpDesignUIWidgets {
 		*iHelpUsage;
 
 	// profile mode & parameters
+	GtkBox	*cMsmtMainToolbar,
+		*cMsmtProfileParamsContainer;
 	GtkComboBox
 		*eMsmtProfileType;
-	GtkToggleButton
-		*eMsmtProfileAutoscale;
-	GtkScaleButton
-		*eMsmtProfileSmooth;
-	GtkBox	*cMsmtProfileParams1,
-		*cMsmtProfileParams2,
-		*cMsmtProfileParams3;
+	GtkBox	*cMsmtProfileParamsPSD,
+		*cMsmtProfileParamsSWU,
+		*cMsmtProfileParamsMC;
 	GtkSpinButton
-		*eMsmtOpFreqFrom,
-		*eMsmtOpFreqWidth;
+		*eMsmtProfileParamsPSDFreqFrom,
+		*eMsmtProfileParamsPSDFreqWidth;
 	GtkAdjustment
-		*jMsmtOpFreqFrom,
-		*jMsmtOpFreqWidth;
-	GtkBox	*cMsmtMainToolbar,
-		*cMsmtProfileParamsContainer;
+		*jMsmtProfileParamsPSDFreqFrom,
+		*jMsmtProfileParamsPSDFreqWidth;
+
 	GtkLabel
-		*lMsmtPSDInfo,
-		*lMsmtMCInfo;
+		*lMsmtProfilePSDExtra,
+		*lMsmtProfileSWUExtra,
+		*lMsmtProfileMCExtra;
 
+	GtkScaleButton
+		*eMsmtProfileSmooth;
+	GtkToggleButton
+		*eMsmtProfileAutoscale;
 	// view selectors
 	GtkComboBox
 		*eMsmtChannel,
diff --git a/src/ui/mw/mw.cc b/src/ui/mw/mw.cc
index e603cc9..41e117b 100644
--- a/src/ui/mw/mw.cc
+++ b/src/ui/mw/mw.cc
@@ -436,32 +436,16 @@ adjust_op_freq_spinbuttons()
 
 	switch ( display_profile_type ) {
 	case metrics::TType::psd:
-		gtk_adjustment_set_step_increment( jMsmtOpFreqFrom,  ED->fft_params.binsize);
-		gtk_adjustment_set_step_increment( jMsmtOpFreqWidth, ED->fft_params.binsize);
+		gtk_adjustment_set_step_increment( jMsmtProfileParamsPSDFreqFrom,  ED->fft_params.binsize);
+		gtk_adjustment_set_step_increment( jMsmtProfileParamsPSDFreqWidth, ED->fft_params.binsize);
 		if ( not used_eeg_samplerates.empty() )
 			gtk_adjustment_set_upper(
-				jMsmtOpFreqFrom,
+				jMsmtProfileParamsPSDFreqFrom,
 				ED->fft_params.binsize * (ED->fft_params.compute_n_bins( used_eeg_samplerates.back()) - 1));
-		gtk_widget_set_sensitive( (GtkWidget*)eMsmtOpFreqWidth, TRUE);
 	    break;
 	case metrics::TType::swu:
-		gtk_adjustment_set_step_increment( jMsmtOpFreqFrom,  ED->swu_params.binsize);
-		gtk_adjustment_set_step_increment( jMsmtOpFreqWidth, ED->swu_params.binsize);
-		if ( not used_eeg_samplerates.empty() )
-			gtk_adjustment_set_upper(
-				jMsmtOpFreqFrom,
-				ED->swu_params.binsize * (ED->swu_params.compute_n_bins( used_eeg_samplerates.back()) - 1));
-		gtk_widget_set_sensitive( (GtkWidget*)eMsmtOpFreqWidth, TRUE);
 	    break;
 	case metrics::TType::mc:
-		gtk_adjustment_set_step_increment( jMsmtOpFreqFrom, ED->mc_params.bandwidth);
-		gtk_spin_button_set_value( eMsmtOpFreqWidth, ED->mc_params.bandwidth);
-		if ( not used_eeg_samplerates.empty() )
-			gtk_adjustment_set_upper(
-				jMsmtOpFreqFrom,
-				ED->mc_params.freq_from
-				+ ED->mc_params.bandwidth * (ED->mc_params.compute_n_bins( used_eeg_samplerates.back()) - 1));
-		gtk_widget_set_sensitive( (GtkWidget*)eMsmtOpFreqWidth, FALSE);
 	    break;
 	default:
 	    break;
diff --git a/src/ui/mw/mw_cb.cc b/src/ui/mw/mw_cb.cc
index 92c0b98..18868f7 100644
--- a/src/ui/mw/mw_cb.cc
+++ b/src/ui/mw/mw_cb.cc
@@ -104,21 +104,21 @@ eMsmtProfileType_changed_cb( GtkComboBox* b, gpointer userdata)
 	auto& ED = *(SExpDesignUI*)userdata;
 	switch ( gtk_combo_box_get_active( b) ) {
 	case 0:
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams1, TRUE);
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams2, FALSE);
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams3, FALSE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsPSD, TRUE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsSWU, FALSE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsMC, FALSE);
 		ED.display_profile_type = metrics::TType::psd;
 	    break;
 	case 1:
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams1, FALSE);
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams2, TRUE);
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams3, FALSE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsPSD, FALSE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsSWU, TRUE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsMC, FALSE);
 		ED.display_profile_type = metrics::TType::swu;
 	    break;
 	case 2:
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams1, FALSE);
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams2, FALSE);
-		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParams3, TRUE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsPSD, FALSE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsSWU, FALSE);
+		gtk_widget_set_visible( (GtkWidget*)ED.cMsmtProfileParamsMC, TRUE);
 		ED.display_profile_type = metrics::TType::mc;
 	    break;
 	}
@@ -147,11 +147,11 @@ eMsmtProfileType_changed_cb( GtkComboBox* b, gpointer userdata)
 
 
 void
-eMsmtOpFreqFrom_value_changed_cb( GtkSpinButton *spinbutton, gpointer userdata)
+eMsmtProfileParamsPSDFreqFrom_value_changed_cb( GtkSpinButton *spinbutton, gpointer userdata)
 {
 	auto& ED = *(SExpDesignUI*)userdata;
 	ED.operating_range_from = gtk_spin_button_get_value( spinbutton);
-	ED.operating_range_upto = ED.operating_range_from + gtk_spin_button_get_value( ED.eMsmtOpFreqWidth);
+	ED.operating_range_upto = ED.operating_range_from + gtk_spin_button_get_value( ED.eMsmtProfileParamsPSDFreqWidth);
 	if ( ED.suppress_redraw )
 		return;
 
@@ -173,7 +173,7 @@ eMsmtOpFreqFrom_value_changed_cb( GtkSpinButton *spinbutton, gpointer userdata)
 }
 
 void
-eMsmtOpFreqWidth_value_changed_cb( GtkSpinButton *spinbutton, gpointer userdata)
+eMsmtProfileParamsPSDFreqWidth_value_changed_cb( GtkSpinButton *spinbutton, gpointer userdata)
 {
 	auto& ED = *(SExpDesignUI*)userdata;
 	ED.operating_range_upto = ED.operating_range_from + gtk_spin_button_get_value( spinbutton);
diff --git a/src/ui/mw/mw_cb.hh b/src/ui/mw/mw_cb.hh
index a0ba564..94bed66 100644
--- a/src/ui/mw/mw_cb.hh
+++ b/src/ui/mw/mw_cb.hh
@@ -1,6 +1,6 @@
 // ;-*-C++-*-
 /*
- *       File name:  ui/mw_cb.hh
+ *       File name:  ui/mw/mw_cb.hh
  *         Project:  Aghermann
  *          Author:  Andrei Zavada <johnhommer at gmail.com>
  * Initial version:  2012-06-25
@@ -47,8 +47,8 @@ void eMsmtProfileSmooth_value_changed_cb( GtkScaleButton*, gdouble, gpointer);
 void eMsmtProfileType_changed_cb( GtkComboBox*, gpointer);
 void eMsmtSession_changed_cb( GtkComboBox*, gpointer);
 void eMsmtChannel_changed_cb( GtkComboBox*, gpointer);
-void eMsmtOpFreqFrom_value_changed_cb( GtkSpinButton*, gpointer);
-void eMsmtOpFreqWidth_value_changed_cb( GtkSpinButton*, gpointer);
+void eMsmtProfileParamsPSDFreqFrom_value_changed_cb( GtkSpinButton*, gpointer);
+void eMsmtProfileParamsPSDFreqWidth_value_changed_cb( GtkSpinButton*, gpointer);
 void eMsmtMCF0_value_changed_cb( GtkSpinButton*, gpointer);
 
 void tvGlobalAnnotations_row_activated_cb( GtkTreeView*, GtkTreePath*, GtkTreeViewColumn*, gpointer);
@@ -76,8 +76,9 @@ void iSimulationsRunClearAll_activate_cb( GtkMenuItem*, gpointer);
 void iSimulationsReportGenerate_activate_cb( GtkMenuItem*, gpointer);
 
 gboolean check_gtk_entry_nonempty_cb( GtkEditable*, gpointer);
-void common_drag_data_received_cb( GtkWidget*, GdkDragContext*, gint, gint, GtkSelectionData*, guint, guint, gpointer);
-gboolean common_drag_drop_cb( GtkWidget*, GdkDragContext*, gint, gint, guint, gpointer);
+
+void cMeasurements_drag_data_received_cb( GtkWidget*, GdkDragContext*, gint, gint, GtkSelectionData*, guint, guint, gpointer);
+gboolean cMeasurements_drag_drop_cb( GtkWidget*, GdkDragContext*, gint, gint, guint, gpointer);
 
 void tTaskSelector_switch_page_cb( GtkNotebook*, gpointer, guint, gpointer);
 void tDesign_switch_page_cb( GtkNotebook*, gpointer, guint, gpointer);
diff --git a/src/ui/sf/sf-channel.cc b/src/ui/sf/sf-channel.cc
index 92aab02..28efc40 100644
--- a/src/ui/sf/sf-channel.cc
+++ b/src/ui/sf/sf-channel.cc
@@ -96,12 +96,12 @@ SChannel( agh::CRecording& r,
 	      // power in a single bin
 		psd.from = _p._p.operating_range_from;
 		psd.upto = _p._p.operating_range_upto;
-		get_psd_course( false);
+		get_psd_course();
 	      // power spectrum (for the first page)
-		spectrum_bins = last_spectrum_bin = crecording.metrics::psd::CProfile::bins();
+		spectrum_bins = last_spectrum_bin = crecording.psd_profile.bins();
 		get_spectrum( 0);
 		// will be reassigned in REDRAW_ALL
-		spectrum_upper_freq = spectrum_bins * crecording.metrics::psd::SPPack::binsize;
+		spectrum_upper_freq = spectrum_bins * crecording.psd_profile.Pp.binsize;
 
 	      // power in bands
 		size_t n_bands = 0;
@@ -111,16 +111,17 @@ SChannel( agh::CRecording& r,
 			else
 				++n_bands;
 		psd.uppermost_band = (n_bands-1);
-		get_psd_in_bands( false);
+		get_psd_in_bands();
 
 	      // swu profile
 		swu.from = _p._p.operating_range_from;
 		swu.upto = _p._p.operating_range_upto;
-		get_swu_course( false);
+		get_swu_course();
 
 	      // mc profile
-		mc.bin = (_p._p.operating_range_from - metrics::mc::SPPack::freq_from) / crecording.bandwidth;
-		get_mc_course( false);
+		mc.from = _p._p.operating_range_from;
+		mc.upto = _p._p.operating_range_from + crecording.mc_profile.Pp.bandwidth;
+		get_mc_course();
 
 	      // delta comes first, calibrate display scale against it
 		//update_profile_display_scales();
@@ -234,10 +235,10 @@ in_annotations( double time) const
 
 void
 aghui::SScoringFacility::SChannel::
-get_psd_course( bool force)
+get_psd_course()
 {
-	auto tmp = (crecording.metrics::psd::CProfile::compute( force),
-		    crecording.metrics::psd::CProfile::course<TFloat>( psd.from, psd.upto));
+	//psd_profile.compute();
+	auto tmp = crecording.course<TFloat>( metrics::TType::psd, psd.from, psd.upto);
 	if ( resample_power ) {
 		auto xi = vector<size_t> (tmp.size());
 		for ( size_t i = 0; i < tmp.size(); ++i )
@@ -249,17 +250,17 @@ get_psd_course( bool force)
 
 void
 aghui::SScoringFacility::SChannel::
-get_psd_in_bands( bool force)
+get_psd_in_bands()
 {
-	crecording.metrics::psd::CProfile::compute( force);
+	crecording.psd_profile.compute();
 	if ( resample_power ) {
-		auto xi = vector<size_t> (crecording.metrics::psd::CProfile::pages());
+		auto xi = vector<size_t> (crecording.psd_profile.pages());
 		for ( size_t i = 0; i < xi.size(); ++i )
 			xi[i] = i;
 		for ( size_t b = 0; b <= psd.uppermost_band; ++b ) {
 			auto	_from = _p._p.freq_bands[b][0],
 				_upto = _p._p.freq_bands[b][1];
-			auto tmp = crecording.metrics::psd::CProfile::course<TFloat>( _from, _upto);
+			auto tmp = crecording.psd_profile.course<TFloat>( _from, _upto);
 			psd.course_in_bands[b] =
 				sigproc::interpolate( xi, 3600/_p.pagesize(),
 						      tmp,
@@ -270,17 +271,17 @@ get_psd_in_bands( bool force)
 			auto	_from = _p._p.freq_bands[b][0],
 				_upto = _p._p.freq_bands[b][1];
 			psd.course_in_bands[b] =
-				crecording.metrics::psd::CProfile::course<TFloat>( _from, _upto);
+				crecording.psd_profile.course<TFloat>( _from, _upto);
 		}
 }
 
 
 void
 aghui::SScoringFacility::SChannel::
-get_swu_course( bool force)
+get_swu_course()
 {
-	auto tmp = (crecording.metrics::swu::CProfile::compute( force),
-		    crecording.metrics::swu::CProfile::course<TFloat>( swu.from, swu.upto));
+	//swu_profile.compute();
+	auto tmp = crecording.course<TFloat>( metrics::TType::swu, swu.from, swu.upto);
 	if ( resample_power ) {
 		auto xi = vector<size_t> (tmp.size());
 		for ( size_t i = 0; i < tmp.size(); ++i )
@@ -293,10 +294,10 @@ get_swu_course( bool force)
 
 void
 aghui::SScoringFacility::SChannel::
-get_mc_course( bool force)
+get_mc_course()
 {
-	auto tmp = (crecording.metrics::mc::CProfile::compute( force),
-		    crecording.metrics::mc::CProfile::course<TFloat>( mc.bin));
+	//mc_profile.compute();
+	auto tmp = crecording.course<TFloat>( metrics::TType::mc, mc.from, mc.upto);
 	if ( resample_power ) {
 		auto xi = vector<size_t> (tmp.size());
 		for ( size_t i = 0; i < tmp.size(); ++i )
@@ -313,13 +314,13 @@ void
 aghui::SScoringFacility::SChannel::
 get_spectrum( size_t p)
 {
-	spectrum = crecording.metrics::psd::CProfile::spectrum<TFloat>( p);
+	spectrum = crecording.psd_profile.spectrum<TFloat>( p);
 }
 void
 aghui::SScoringFacility::SChannel::
 get_spectrum()
 {
-	spectrum = crecording.metrics::psd::CProfile::spectrum<TFloat>( _p.cur_page());
+	spectrum = crecording.psd_profile.spectrum<TFloat>( _p.cur_page());
 }
 
 
@@ -373,10 +374,10 @@ detect_artifacts( const metrics::mc::SArtifactDetectionPP& P)
 	calculate_dirty_percent();
 	get_signal_filtered();
 	if ( type == sigfile::SChannel::TType::eeg ) {
-		get_psd_course( false);
-		get_psd_in_bands( false);
+		get_psd_course();
+		get_psd_in_bands();
 		get_spectrum( _p.cur_page());
-		get_mc_course( false);
+		get_mc_course();
 
 		// if ( this == channel currently displayed on measurements overview )
 		if ( strcmp( name, _p._p.AghH()) == 0 )
@@ -401,10 +402,10 @@ mark_region_as_artifact( bool do_mark)
 	get_signal_filtered();
 
 	if ( type == sigfile::SChannel::TType::eeg ) {
-		get_psd_course( false);
-		get_psd_in_bands( false);
+		get_psd_course();
+		get_psd_in_bands();
 		get_spectrum( _p.cur_page());
-		get_mc_course( false);
+		get_mc_course();
 
 		if ( strcmp( name, _p._p.AghH()) == 0 )
 			_p.redraw_ssubject_timeline();
diff --git a/src/ui/sf/sf-filter_cb.cc b/src/ui/sf/sf-filter_cb.cc
index e1dd911..3e186de 100644
--- a/src/ui/sf/sf-filter_cb.cc
+++ b/src/ui/sf/sf-filter_cb.cc
@@ -44,10 +44,10 @@ iSFPageFilter_activate_cb( GtkMenuItem *menuitem, gpointer userdata)
 		H.get_signal_filtered();
 
 		if ( H.type == sigfile::SChannel::TType::eeg ) {
-			H.get_psd_course( true); // force redo fft due to it not keeping track of filters yet
-			H.get_psd_in_bands( false);
+			H.get_psd_course();
+			H.get_psd_in_bands();
 			H.get_spectrum( SF.cur_page());
-			H.get_mc_course( true);
+			H.get_mc_course();
 		}
 		gtk_widget_queue_draw( (GtkWidget*)SF.daSFMontage);
 
diff --git a/src/ui/sf/sf-ica.cc b/src/ui/sf/sf-ica.cc
index 98d9d1a..beff772 100644
--- a/src/ui/sf/sf-ica.cc
+++ b/src/ui/sf/sf-ica.cc
@@ -280,9 +280,9 @@ apply_remix( bool do_backup)
 		H.get_signal_original();
 		H.get_signal_filtered();
 		if ( H.type ==  sigfile::SChannel::TType::eeg ) {
-			H.get_psd_course( true);
-			H.get_psd_in_bands( true);
-			H.get_mc_course( true);
+			H.get_psd_course();
+			H.get_psd_in_bands();
+			H.get_mc_course();
 			H.get_spectrum();
 		}
 	}
diff --git a/src/ui/sf/sf-montage.cc b/src/ui/sf/sf-montage.cc
index abf8237..dda91a5 100644
--- a/src/ui/sf/sf-montage.cc
+++ b/src/ui/sf/sf-montage.cc
@@ -695,7 +695,7 @@ draw_overlays( cairo_t* cr,
 			// spectrum
 			_p._p.CwB[SExpDesignUI::TColour::spectrum].set_source_rgba( cr, .8);
 			cairo_set_line_width( cr, 2);
-			float factor = psd.display_scale / crecording.metrics::psd::SPPack::binsize;
+			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 ) {
@@ -726,7 +726,7 @@ draw_overlays( cairo_t* cr,
 			cairo_set_font_size( cr, 8);
 
 			snprintf_buf( "%g Hz",
-				      last_spectrum_bin * crecording.metrics::psd::SPPack::binsize);
+				      last_spectrum_bin * crecording.psd_profile.Pp.binsize);
 //				      draw_spectrum_absolute ? 'A' : 'R');
 			cairo_text_extents( cr, __buf__, &extents);
 			cairo_move_to( cr,
@@ -759,8 +759,8 @@ draw_overlays( cairo_t* cr,
 
 		cairo_select_font_face( cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
 		snprintf_buf( "%g–%g Hz",
-			      crecording.freq_from + (mc.bin  ) * crecording.bandwidth,
-			      crecording.freq_from + (mc.bin+1) * crecording.bandwidth);
+			      crecording.mc_profile.Pp.freq_from + crecording.mc_profile.Pp.bandwidth,
+			      crecording.mc_profile.Pp.freq_from + crecording.mc_profile.Pp.bandwidth);
 		cairo_move_to( cr, _p.da_wd - 70, pbot - 30);
 		cairo_show_text( cr, __buf__);
 		cairo_stroke( cr);
diff --git a/src/ui/sf/sf-montage_cb.cc b/src/ui/sf/sf-montage_cb.cc
index 6395d9f..fbb2307 100644
--- a/src/ui/sf/sf-montage_cb.cc
+++ b/src/ui/sf/sf-montage_cb.cc
@@ -346,7 +346,7 @@ daSFMontage_scroll_event_cb( GtkWidget *wid, GdkEventScroll *event, gpointer use
 	} else if ( Ch->type == sigfile::SChannel::TType::eeg
 	     && event->y > Ch->zeroy
 	     && (Ch->draw_psd || Ch->draw_mc) ) {
-		if ( event->state & GDK_SHIFT_MASK && Ch->draw_psd )
+		if ( event->state & GDK_SHIFT_MASK && Ch->draw_psd ) {
 			switch ( event->direction ) {
 			case GDK_SCROLL_DOWN:
 				if ( Ch->draw_bands ) {
@@ -360,7 +360,7 @@ daSFMontage_scroll_event_cb( GtkWidget *wid, GdkEventScroll *event, gpointer use
 					if ( Ch->psd.from > 0 ) {
 						Ch->psd.from -= .5;
 						Ch->psd.upto -= .5;
-						Ch->get_psd_course( false);
+						Ch->get_psd_course();
 						if ( Ch->autoscale_profile )
 							Ch->update_profile_display_scales();
 						gtk_widget_queue_draw( wid);
@@ -376,10 +376,10 @@ daSFMontage_scroll_event_cb( GtkWidget *wid, GdkEventScroll *event, gpointer use
 					}
 				} else {
 					auto& R = Ch->crecording;
-					if ( Ch->psd.upto < R.metrics::psd::SPPack::binsize * R.metrics::psd::CProfile::bins() ) {
+					if ( Ch->psd.upto < R.psd_profile.Pp.binsize * R.psd_profile.bins() ) {
 						Ch->psd.from += .5;
 						Ch->psd.upto += .5;
-						Ch->get_psd_course( false);
+						Ch->get_psd_course();
 						if ( Ch->autoscale_profile )
 							Ch->update_profile_display_scales();
 						gtk_widget_queue_draw( wid);
@@ -391,34 +391,7 @@ daSFMontage_scroll_event_cb( GtkWidget *wid, GdkEventScroll *event, gpointer use
 			default:
 				break;
 			}
-		else if ( event->state & GDK_SHIFT_MASK && event->state & GDK_MOD1_MASK && Ch->draw_mc )
-			switch ( event->direction ) {
-			case GDK_SCROLL_DOWN:
-				if ( Ch->mc.bin > 0 ) {
-					--Ch->mc.bin;
-					Ch->get_mc_course( false);
-					if ( Ch->autoscale_profile )
-						Ch->update_profile_display_scales();
-					gtk_widget_queue_draw( wid);
-				}
-				break;
-			case GDK_SCROLL_UP:
-				if ( Ch->mc.bin < Ch->crecording.metrics::mc::SPPack::compute_n_bins(
-					     Ch->crecording.metrics::mc::CProfile::samplerate()) - 1 ) {
-					++Ch->mc.bin;
-					Ch->get_mc_course( false);
-					if ( Ch->autoscale_profile )
-						Ch->update_profile_display_scales();
-					gtk_widget_queue_draw( wid);
-				}
-				break;
-			case GDK_SCROLL_LEFT:
-			case GDK_SCROLL_RIGHT:
-			default:
-				break;
-			}
-
-		else {
+		} else {
 			switch ( event->direction ) {
 			case GDK_SCROLL_DOWN:
 				Ch->psd.display_scale /= 1.1;
@@ -679,8 +652,8 @@ iSFPageClearArtifacts_activate_cb( GtkMenuItem *menuitem, gpointer userdata)
 	SF.using_channel->get_signal_filtered();
 
 	if ( SF.using_channel->type == sigfile::SChannel::TType::eeg ) {
-		SF.using_channel->get_psd_course( false);
-		SF.using_channel->get_psd_in_bands( false);
+		SF.using_channel->get_psd_course();
+		SF.using_channel->get_psd_in_bands();
 		SF.using_channel->get_spectrum();
 
 		SF.redraw_ssubject_timeline();
@@ -927,34 +900,34 @@ iSFPowerExportRange_activate_cb( GtkMenuItem *menuitem, gpointer userdata)
 
 	string fname_base;
 	if ( SF.using_channel->draw_psd ) {
-		fname_base = R.metrics::psd::CProfile::fname_base();
+		fname_base = R.psd_profile.fname_base();
 		snprintf_buf( "%s-psd_%g-%g.tsv",
 			      fname_base.c_str(), SF.using_channel->psd.from, SF.using_channel->psd.upto);
-		R.metrics::psd::CProfile::export_tsv(
+		R.psd_profile.export_tsv(
 			SF.using_channel->psd.from, SF.using_channel->psd.upto,
 			__buf__);
 		fname_base = __buf__; // recycle
 	}
-	if ( SF.using_channel->draw_swu ) {
-		fname_base = R.metrics::swu::CProfile::fname_base();
-		snprintf_buf( "%s-swu_%g-%g.tsv",
-			      fname_base.c_str(), SF.using_channel->swu.from, SF.using_channel->swu.upto);
-		R.metrics::swu::CProfile::export_tsv(
-			SF.using_channel->swu.from, SF.using_channel->swu.upto,
-			__buf__);
-		fname_base = __buf__; // recycle
-	}
-	if ( SF.using_channel->draw_mc ) {
-		fname_base = R.metrics::mc::CProfile::fname_base();
-		snprintf_buf( "%s-mc_%g-%g.tsv",
-			      fname_base.c_str(),
-			      R.freq_from + R.bandwidth*(SF.using_channel->mc.bin),
-			      R.freq_from + R.bandwidth*(SF.using_channel->mc.bin+1));
-		R.metrics::mc::CProfile::export_tsv(
-			SF.using_channel->mc.bin,
-			__buf__);
-		fname_base = __buf__;
-	}
+	// if ( SF.using_channel->draw_swu ) {
+	// 	fname_base = R.swu_profile.fname_base();
+	// 	snprintf_buf( "%s-swu_%g-%g.tsv",
+	// 		      fname_base.c_str(), SF.using_channel->swu.from, SF.using_channel->swu.upto);
+	// 	R.swu_profile.export_tsv(
+	// 		SF.using_channel->swu.from, SF.using_channel->swu.upto,
+	// 		__buf__);
+	// 	fname_base = __buf__; // recycle
+	// }
+	// if ( SF.using_channel->draw_mc ) {
+	// 	fname_base = R.mc_profile.fname_base();
+	// 	snprintf_buf( "%s-mc_%g-%g.tsv",
+	// 		      fname_base.c_str(),
+	// 		      R.freq_from + R.bandwidth*(SF.using_channel->mc.bin),
+	// 		      R.freq_from + R.bandwidth*(SF.using_channel->mc.bin+1));
+	// 	R.mc_profile.export_tsv(
+	// 		SF.using_channel->mc.bin,
+	// 		__buf__);
+	// 	fname_base = __buf__;
+	// }
 
 	snprintf_buf( "Wrote %s", agh::str::homedir2tilda(fname_base).c_str());
 	SF._p.buf_on_main_status_bar();
@@ -968,27 +941,21 @@ iSFPowerExportAll_activate_cb( GtkMenuItem *menuitem, gpointer userdata)
 
 	string fname_base;
 	if ( SF.using_channel->draw_psd ) {
-		fname_base = SF.using_channel->crecording.metrics::psd::CProfile::fname_base();
-		snprintf_buf( "%s-psd.tsv",
-			      fname_base.c_str());
-		R.metrics::psd::CProfile::export_tsv(
-			__buf__);
+		fname_base = SF.using_channel->crecording.psd_profile.fname_base();
+		snprintf_buf( "%s-psd.tsv", fname_base.c_str());
+		R.psd_profile.export_tsv( __buf__);
 		fname_base = __buf__; // recycle
 	}
 	if ( SF.using_channel->draw_swu ) {
-		fname_base = SF.using_channel->crecording.metrics::swu::CProfile::fname_base();
-		snprintf_buf( "%s-swu.tsv",
-			      fname_base.c_str());
-		R.metrics::swu::CProfile::export_tsv(
-			__buf__);
-		fname_base = __buf__; // recycle
+		fname_base = SF.using_channel->crecording.swu_profile.fname_base();
+		snprintf_buf( "%s-swu.tsv", fname_base.c_str());
+		R.swu_profile.export_tsv( __buf__);
+		fname_base = __buf__;
 	}
 	if ( SF.using_channel->draw_mc ) {
-		fname_base = SF.using_channel->crecording.metrics::mc::CProfile::fname_base();
-		snprintf_buf( "%s-mc.tsv",
-			      fname_base.c_str());
-		R.metrics::mc::CProfile::export_tsv(
-			__buf__);
+		fname_base = SF.using_channel->crecording.mc_profile.fname_base();
+		snprintf_buf( "%s-mc.tsv", fname_base.c_str());
+		R.mc_profile.export_tsv( __buf__);
 		fname_base = __buf__;
 	}
 
@@ -1004,9 +971,10 @@ iSFPowerSmooth_toggled_cb( GtkCheckMenuItem *checkmenuitem, gpointer userdata)
 		return;
 	if ( likely (SF.using_channel->type == sigfile::SChannel::TType::eeg ) ) {
 		SF.using_channel->resample_power = (bool)gtk_check_menu_item_get_active( checkmenuitem);
-		SF.using_channel->get_psd_course(false);
-		SF.using_channel->get_psd_in_bands(false);
-		SF.using_channel->get_mc_course( false);
+		SF.using_channel->get_psd_course();
+		SF.using_channel->get_psd_in_bands();
+		SF.using_channel->get_swu_course();
+		SF.using_channel->get_mc_course();
 		gtk_widget_queue_draw( (GtkWidget*)SF.daSFMontage);
 	}
 }
diff --git a/src/ui/sf/sf-phasediff.cc b/src/ui/sf/sf-phasediff.cc
index a155f9a..4f81529 100644
--- a/src/ui/sf/sf-phasediff.cc
+++ b/src/ui/sf/sf-phasediff.cc
@@ -151,8 +151,8 @@ draw( cairo_t* cr, int wd, int ht)
 
       // psd course in selected freq range
 	{
-		auto	C1 = channel1->crecording.metrics::psd::CProfile::course<TFloat>( from, upto);
-//			C2 = channel2->crecording.metrics::psd::CProfile::course<TFloat>( from, upto) * display_scale + ht/2;
+		auto	C1 = channel1->crecording.psd_profile.course<TFloat>( from, upto);
+//			C2 = channel2->crecording.psd_profile.course<TFloat>( from, upto) * display_scale + ht/2;
 
 		ED.CwB[SExpDesignUI::TColour::profile_psd_sf].set_source_rgba( cr, .5);
 		auto	scale =
diff --git a/src/ui/sf/sf.hh b/src/ui/sf/sf.hh
index 0dd9d17..ec36fac 100644
--- a/src/ui/sf/sf.hh
+++ b/src/ui/sf/sf.hh
@@ -154,7 +154,7 @@ class SScoringFacility
 		// psd
 		struct SProfilePSD {
 			valarray<TFloat>
-				course; // can possibly live outside in core, no?
+				course;
 			double	from, upto;
 			double	display_scale; // saved via libconfig, requiring it to be double
 			array<valarray<TFloat>, metrics::psd::TBand::_total>
@@ -162,18 +162,18 @@ class SScoringFacility
 			size_t	focused_band,
 				uppermost_band;
 		};
-		void get_psd_course( bool force);
-		void get_psd_in_bands( bool force);
+		void get_psd_course();
+		void get_psd_in_bands();
 		SProfilePSD
 			psd;
 		// swu
 		struct SProfileSWU {
 			valarray<TFloat>
-				course; // can possibly live outside in core, no?
+				course;
 			double	from, upto;
-			double	display_scale; // saved via libconfig, requiring it to be double
+			double	display_scale;
 		};
-		void get_swu_course( bool force);
+		void get_swu_course();
 		SProfileSWU
 			swu;
 		// mc
@@ -181,11 +181,11 @@ class SScoringFacility
 			valarray<TFloat>
 				course;
 			double	display_scale;
-			size_t	bin;
+			double	from, upto; // approximate
 		};
 		SProfileMC
 			mc;
-		void get_mc_course( bool force);
+		void get_mc_course();
 
 		void
 		update_profile_display_scales();
diff --git a/src/ui/ui.hh b/src/ui/ui.hh
index 635abba..0d40a18 100644
--- a/src/ui/ui.hh
+++ b/src/ui/ui.hh
@@ -171,6 +171,12 @@ void set_cursor_busy( bool busy, GtkWidget *wid);
 #define AGH_GBGETOBJ3(B, Type, A)			\
 	(A = (Type*)(gtk_builder_get_object( B, #A)))
 
+#define G_CONNECT_1(W, A)						\
+	g_signal_connect(W, #A, (GCallback)W ## _ ## A ## _cb, this)
+#define G_CONNECT_2(W, A1, A2)						\
+	g_signal_connect(W, #A1 "-" #A2, (GCallback)W ## _ ## A1 ## _ ## A2 ## _cb, this)
+#define G_CONNECT_3(W, A1, A2, A3)					\
+	g_signal_connect(W, #A1 "-" #A2 "-" #A3, (GCallback)W ## _ ## A1 ## _ ## A2 ## _ ## A3 ## _cb, this)
 
 } // namespace aghui
 

-- 
Sleep experiment manager



More information about the debian-med-commit mailing list