[med-svn] [aghermann] 69/85: enable dirlevel profiles for artifacts, too

andrei zavada hmmr-guest at alioth.debian.org
Thu Sep 26 23:46:34 UTC 2013


This is an automated email from the git hooks/post-receive script.

hmmr-guest pushed a commit to branch master
in repository aghermann.

commit 291c2ec5950845824e540a548c4b89be3ba5018a
Author: Andrei Zavada <johnhommer at gmail.com>
Date:   Sun Sep 22 01:52:44 2013 +0300

    enable dirlevel profiles for artifacts, too
---
 upstream/data/sf-artifacts.glade                   |  169 ++++++++++++++++----
 upstream/src/aghermann/ui/mw/mainmenu_cb.cc        |   68 ++++++--
 upstream/src/aghermann/ui/mw/mw.cc                 |   76 ---------
 upstream/src/aghermann/ui/mw/mw.hh                 |   11 +-
 upstream/src/aghermann/ui/mw/populate.cc           |   17 --
 upstream/src/aghermann/ui/sf/Makefile.am           |    2 +-
 upstream/src/aghermann/ui/sf/channel.cc            |    9 +-
 upstream/src/aghermann/ui/sf/channel.hh            |    2 +-
 .../src/aghermann/ui/sf/d/artifacts-construct.cc   |   94 -----------
 .../src/aghermann/ui/sf/d/artifacts-profiles_cb.cc |   92 +++++++++++
 upstream/src/aghermann/ui/sf/d/artifacts.cc        |  165 ++++++++++++++++---
 upstream/src/aghermann/ui/sf/d/artifacts.hh        |   76 ++++-----
 upstream/src/aghermann/ui/sf/d/artifacts_cb.cc     |  152 ++++++------------
 upstream/src/libmetrics/forward-decls.hh           |    2 +-
 upstream/src/libmetrics/mc-artifacts.cc            |    3 +-
 upstream/src/libmetrics/mc-artifacts.hh            |  107 +++++++++++--
 upstream/src/libmetrics/mc-artifacts.ii            |    4 +-
 17 files changed, 635 insertions(+), 414 deletions(-)

diff --git a/upstream/data/sf-artifacts.glade b/upstream/data/sf-artifacts.glade
index c04e12b..8a89dd9 100644
--- a/upstream/data/sf-artifacts.glade
+++ b/upstream/data/sf-artifacts.glade
@@ -941,11 +941,14 @@
               <object class="GtkBox" id="box8">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="spacing">3</property>
+                <property name="spacing">5</property>
                 <child>
-                  <object class="GtkComboBox" id="eSFADProfiles">
+                  <object class="GtkButton" id="bSFADProfileRevert">
+                    <property name="label" translatable="yes">_Revert</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_underline">True</property>
                   </object>
                   <packing>
                     <property name="expand">False</property>
@@ -954,6 +957,17 @@
                   </packing>
                 </child>
                 <child>
+                  <object class="GtkComboBox" id="eSFADProfileList">
+                    <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">1</property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkButton" id="bSFADProfileSave">
                     <property name="label" translatable="yes">Save</property>
                     <property name="visible">True</property>
@@ -967,8 +981,8 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkButton" id="bSFADProfileDelete">
-                    <property name="label" translatable="yes">Delete</property>
+                  <object class="GtkButton" id="bSFADProfileDiscard">
+                    <property name="label" translatable="yes">Discard</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
@@ -1057,64 +1071,157 @@
       <action-widget response="-5">bSFADApply</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkDialog" id="wSFADSaveProfileName">
+  <object class="GtkDialog" id="wSFADProfileSave">
     <property name="width_request">200</property>
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
-    <property name="title" translatable="yes">New AD profile</property>
+    <property name="title" translatable="yes">Save pattern</property>
     <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
     <property name="destroy_with_parent">True</property>
     <property name="type_hint">dialog</property>
     <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">wSFAD</property>
     <signal name="close" handler="gtk_widget_hide_on_delete" swapped="no"/>
     <signal name="response" handler="gtk_widget_hide_on_delete" swapped="no"/>
     <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox13">
+      <object class="GtkBox" id="dialog-vbox4">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="margin_left">5</property>
+        <property name="margin_right">5</property>
+        <property name="margin_top">5</property>
+        <property name="margin_bottom">5</property>
         <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
+        <property name="spacing">10</property>
         <child>
-          <object class="GtkLabel" id="label43">
+          <object class="GtkFrame" id="frame2">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Profile _name:</property>
-            <property name="use_underline">True</property>
-            <property name="mnemonic_widget">eSFADSaveProfileNameName</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <object class="GtkEntry" id="eSFADProfileSaveName">
+                <property name="width_request">130</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="margin_top">5</property>
+                <property name="margin_bottom">5</property>
+                <property name="invisible_char">•</property>
+                <property name="activates_default">True</property>
+                <property name="invisible_char_set">True</property>
+                <property name="primary_icon_activatable">False</property>
+                <property name="secondary_icon_activatable">False</property>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes"><b>Profile name</b></property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
           </object>
           <packing>
-            <property name="expand">False</property>
+            <property name="expand">True</property>
             <property name="fill">True</property>
             <property name="position">0</property>
           </packing>
         </child>
         <child>
-          <object class="GtkEntry" id="eSFADSaveProfileNameName">
-            <property name="width_request">130</property>
+          <object class="GtkFrame" id="frame1">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="can_default">True</property>
-            <property name="invisible_char">•</property>
-            <property name="activates_default">True</property>
-            <property name="invisible_char_set">True</property>
-            <property name="primary_icon_activatable">False</property>
-            <property name="secondary_icon_activatable">False</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <object class="GtkBox" id="box13">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">3</property>
+                <property name="margin_right">3</property>
+                <property name="margin_top">3</property>
+                <property name="margin_bottom">3</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">3</property>
+                <child>
+                  <object class="GtkRadioButton" id="eSFADProfileSaveOriginUser">
+                    <property name="label" translatable="yes">_User</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="xalign">0</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">eSFADProfileSaveOriginExperiment</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="eSFADProfileSaveOriginExperiment">
+                    <property name="label" translatable="yes">_Experiment</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="xalign">0</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">eSFADProfileSaveOriginUser</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="eSFADProfileSaveOriginSubject">
+                    <property name="label" translatable="yes">_Subject</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="xalign">0</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">eSFADProfileSaveOriginUser</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label51">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes"><b>Scope</b></property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
           </object>
           <packing>
-            <property name="expand">True</property>
+            <property name="expand">False</property>
             <property name="fill">True</property>
             <property name="position">2</property>
           </packing>
         </child>
         <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area13">
+          <object class="GtkButtonBox" id="dialog-action_area4">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
             <child>
-              <object class="GtkButton" id="button8">
+              <object class="GtkButton" id="button1">
                 <property name="label">gtk-cancel</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
@@ -1129,7 +1236,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="button9">
+              <object class="GtkButton" id="bSFADProfileSaveOK">
                 <property name="label">gtk-ok</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
@@ -1157,8 +1264,8 @@
       </object>
     </child>
     <action-widgets>
-      <action-widget response="-6">button8</action-widget>
-      <action-widget response="-5">button9</action-widget>
+      <action-widget response="-6">button1</action-widget>
+      <action-widget response="-5">bSFADProfileSaveOK</action-widget>
     </action-widgets>
   </object>
   <object class="GtkSizeGroup" id="zSFADEstimateEControls">
@@ -1182,7 +1289,7 @@
     <widgets>
       <widget name="bSFADProfileRevert"/>
       <widget name="bSFADProfileSave"/>
-      <widget name="bSFADProfileDelete"/>
+      <widget name="bSFADProfileDiscard"/>
     </widgets>
   </object>
 </interface>
diff --git a/upstream/src/aghermann/ui/mw/mainmenu_cb.cc b/upstream/src/aghermann/ui/mw/mainmenu_cb.cc
index e0d0a2f..c0c16df 100644
--- a/upstream/src/aghermann/ui/mw/mainmenu_cb.cc
+++ b/upstream/src/aghermann/ui/mw/mainmenu_cb.cc
@@ -211,6 +211,37 @@ iExpBasicSADetectUltradianCycles_activate_cb(
 
 
 
+static void
+populate_combo( const list<metrics::mc::CArtifactDetector>& profiles, GtkListStore* mProfiles)
+{
+        gtk_list_store_clear( mProfiles);
+
+        if ( not profiles.empty() ) {
+                GtkTreeIter iter;
+                for ( auto I = profiles.begin(); I != profiles.end(); ++I ) {
+                        gtk_list_store_append(
+                                mProfiles, &iter);
+                        gtk_list_store_set(
+                                mProfiles, &iter,
+                                0, I->name.c_str(),
+                                -1);
+                }
+        }
+}
+
+
+static list<metrics::mc::CArtifactDetector>::const_iterator
+profile_by_idx( const list<metrics::mc::CArtifactDetector>& profiles, size_t idx)
+{
+        size_t i = 0;
+        for ( auto I = profiles.cbegin(); I != profiles.cend(); ++I )
+                if ( i == idx )
+                        return I;
+                else
+                        ++i;
+        throw invalid_argument ("Current profile index invalid");
+}
+
 void
 iExpGloballyDetectArtifacts_activate_cb(
         GtkMenuItem*,
@@ -218,18 +249,32 @@ iExpGloballyDetectArtifacts_activate_cb(
 {
         auto& ED = *(SExpDesignUI*)userdata;
 
-        if ( ED.global_artifact_detection_profiles.size() < 1 ) {
+        using namespace agh;
+        using metrics::mc::CArtifactDetector;
+        list<CArtifactDetector> profiles;
+
+        for ( auto A : {TExpDirLevel::system, TExpDirLevel::user, TExpDirLevel::experiment} )
+                profiles.splice(
+                        profiles.end(),
+                        load_profiles_from_location<CArtifactDetector>(
+                                CArtifactDetector::common_subdir,
+                                A, *ED.ED, agh::SExpDirLevelId {"", "", ""}));
+
+        if ( profiles.size() < 1 ) {
                 pop_ok_message( ED.wMainWindow,
                                 "Create some profiles first",
                                 "You can do it by opening a recording in Scoring Facility and"
                                 " tweaking default parameters in Artifact Detect dialog."
-                                " After saving them as a profile, it will appear here.");
+                                " After saving them as an experiment-wide profile, the latter will appear here.");
                 return;
         }
 
+        populate_combo( profiles, ED.mGlobalADProfiles);
+        gtk_combo_box_set_model( ED.eGlobalADProfiles, (GtkTreeModel*)ED.mGlobalADProfiles);
+
         gtk_label_set_markup(
                 ED.lGlobalADHint,
-                (ED.global_artifact_detection_profiles.size() < 2)
+                (profiles.size() < 2)
                 ? "<small>You can create a custom profile in Scoring Facility,\n"
                   "after tuning parameters on a real recording.</small>"
                 : ""); // good boy
@@ -240,8 +285,11 @@ iExpGloballyDetectArtifacts_activate_cb(
              response == GTK_RESPONSE_DELETE_EVENT )
                 return; // just to save on indents in those lambdas below
 
-        auto& P = ED.global_artifact_detection_profiles[
-                gtk_combo_box_get_active_id(ED.eGlobalADProfiles)];
+        auto& P =
+                profile_by_idx(
+                        profiles,
+                        gtk_combo_box_get_active( ED.eGlobalADProfiles))
+                ->Pp;
         bool keep_existing = gtk_toggle_button_get_active( (GtkToggleButton*)ED.eGlobalADKeepExisting);
 
         SBusyBlock bb (ED.wMainWindow);
@@ -264,14 +312,14 @@ iExpGloballyDetectArtifacts_activate_cb(
                 op =
                 [&]( CRecording& R)
                 {
-                        auto        sr = R.F().samplerate(R.h());
-                        auto&        af = R.F().artifacts(R.h());
+                        auto    sr = R.F().samplerate(R.h());
+                        auto&   af = R.F().artifacts(R.h());
 
-                        auto        signal_original = R.F().get_signal_original(R.h());
+                        auto    signal_original = R.F().get_signal_original(R.h());
 
                         if ( not keep_existing )
                                 af.clear_all();
-                        auto        marked = metrics::mc::detect_artifacts( signal_original, sr, P);
+                        auto    marked = metrics::mc::detect_artifacts( signal_original, sr, P);
                         for ( size_t p = 0; p < marked.size(); ++p )
                                 af.mark_artifact(
                                         marked[p] * P.scope * sr,
@@ -332,7 +380,7 @@ eGlobalADProfiles_changed_cb(
 
         gtk_widget_set_sensitive(
                 (GtkWidget*)ED.bGlobalADOK,
-                ED.global_artifact_detection_profiles.size() > 0);
+                gtk_combo_box_get_active( ED.eGlobalADProfiles) != -1);
 }
 
 
diff --git a/upstream/src/aghermann/ui/mw/mw.cc b/upstream/src/aghermann/ui/mw/mw.cc
index be4b6cb..a7334e4 100644
--- a/upstream/src/aghermann/ui/mw/mw.cc
+++ b/upstream/src/aghermann/ui/mw/mw.cc
@@ -219,10 +219,6 @@ SExpDesignUI (SSessionChooser *parent,
                                   bind( &SExpDesignUI::sb_main_progress_indicator, this,
                                         placeholders::_1, placeholders::_2, placeholders::_3,
                                         ui::TGtkRefreshMode::gtk));
-        load_artifact_detection_profiles();
-        if ( global_artifact_detection_profiles.empty() )
-                global_artifact_detection_profiles["default"] = metrics::mc::SArtifactDetectionPP ();
-
         nodestroy_by_cb = false;
 
         // bind fields to widgets
@@ -314,77 +310,6 @@ SExpDesignUI (SSessionChooser *parent,
         suppress_redraw = false;
 }
 
-void
-SExpDesignUI::
-load_artifact_detection_profiles()
-{
-        FILE *domien = fopen( (string(ED->session_dir()) + "/.AD_profiles").c_str(), "r");
-        if ( domien ) {
-                while ( !feof (domien) ) {
-                        metrics::mc::SArtifactDetectionPP P;
-                        char *name = nullptr;
-                        int int_estimate_E, int_use_range;
-// at least gcc 4.7.2 fails to recognize "%as" (dynamic allocation), so
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat"
-                        if ( 16 ==
-                             fscanf( domien, "%a[^\n]\n%la  %la %la  %la %la %la  %la %la  %la %la %la "
-                                     "%zu %zu %d %d",
-                                     &name,
-                                     &P.scope,
-                                     &P.upper_thr, &P.lower_thr,
-                                     &P.f0, &P.fc, &P.bandwidth,
-                                     &P.mc_gain, &P.iir_backpolate,
-                                     &P.E, &P.dmin, &P.dmax,
-                                     &P.sssu_hist_size,
-                                     &P.smooth_side,
-                                     &int_estimate_E,
-                                     &int_use_range) ) {
-
-                                P.estimate_E = (bool)int_estimate_E;
-                                P.use_range = (bool)int_use_range;
-                                global_artifact_detection_profiles[name] = P;
-#pragma GCC diagnostic pop
-                        } else
-                                break;
-
-                        free( (void*)name);
-                }
-                fclose( domien);
-        }
-}
-
-void
-SExpDesignUI::
-save_artifact_detection_profiles() const
-{
-        // libconfig::Config conf;
-        // auto&        root = conf.getRoot();
-        // auto&        profiles = root.add("profiles", libconfig::Setting::Type::TypeArray);
-        if ( global_artifact_detection_profiles.size() == 0 )
-                return;
-
-        FILE *domien = fopen( (string(ED->session_dir()) + "/.AD_profiles").c_str(), "w");
-        if ( domien ) {
-                for ( auto &P : global_artifact_detection_profiles ) {
-                        fprintf( domien, "%s\n", P.first.c_str());
-                        fprintf( domien, "%a  %a %a  %a %a %a  %a %a  %a %a %a "
-                                 "%zu %zu %d %d\n",
-                                 P.second.scope,
-                                 P.second.upper_thr, P.second.lower_thr,
-                                 P.second.f0, P.second.fc, P.second.bandwidth,
-                                 P.second.mc_gain, P.second.iir_backpolate,
-                                 P.second.E, P.second.dmin, P.second.dmax,
-                                 P.second.sssu_hist_size,
-                                 P.second.smooth_side,
-                                 (int)P.second.estimate_E,
-                                 (int)P.second.use_range);
-
-                }
-                fclose( domien);
-        } else
-                fprintf( stderr, "failed to open $EXPROOT/.AD_profiles for writing\n");
-}
 
 
 size_t
@@ -417,7 +342,6 @@ SExpDesignUI::
                 kill( dl_pid, SIGTERM);
 
         save_settings();
-        save_artifact_detection_profiles();
         auto sielle = open_scoring_facilities;
         // let SF dtor reach back and erase its own mention from open_scoring_facilities
         for ( auto& SF : sielle )
diff --git a/upstream/src/aghermann/ui/mw/mw.hh b/upstream/src/aghermann/ui/mw/mw.hh
index 58baf7a..a9eba59 100644
--- a/upstream/src/aghermann/ui/mw/mw.hh
+++ b/upstream/src/aghermann/ui/mw/mw.hh
@@ -205,11 +205,11 @@ class SExpDesignUI
         forward_list<SAnnotation>
                 global_annotations;
 
-        // common artifact detection profiles
-        map<string, metrics::mc::SArtifactDetectionPP>
-                global_artifact_detection_profiles;
-        void load_artifact_detection_profiles();
-        void save_artifact_detection_profiles() const;
+        // // common artifact detection profiles
+        // map<string, metrics::mc::SArtifactDetectionPPack>
+        //         global_artifact_detection_profiles;
+        // void load_artifact_detection_profiles();
+        // void save_artifact_detection_profiles() const;
 
       // currently open SF instances
         list<agh::ui::SScoringFacility*>
@@ -350,7 +350,6 @@ class SExpDesignUI
         void populate_mSessions();
         void populate_mChannels();
         void populate_mGlobalAnnotations();
-        void populate_mGlobalADProfiles();
         void adjust_op_freq_spinbuttons();
         void __reconnect_channels_combo();
         void __reconnect_sessions_combo();
diff --git a/upstream/src/aghermann/ui/mw/populate.cc b/upstream/src/aghermann/ui/mw/populate.cc
index 4b1e265..35c7156 100644
--- a/upstream/src/aghermann/ui/mw/populate.cc
+++ b/upstream/src/aghermann/ui/mw/populate.cc
@@ -58,7 +58,6 @@ populate( bool do_load)
                 printf( "* single common EEG samplerate: %zu\n", used_eeg_samplerates.front());
         else
                 printf( "* multiple EEG samplerates (%zu)\n", used_eeg_samplerates.size());
-        printf( "* global AD profiles: %zu\n", global_artifact_detection_profiles.size());
 
         if ( do_load ) {
                 if ( load_settings() )
@@ -96,7 +95,6 @@ populate( bool do_load)
                 populate_mChannels();
                 populate_mSessions();
                 populate_mGlobalAnnotations();
-                populate_mGlobalADProfiles();
                 populate_1();
 
                 gtk_combo_box_set_active( eGlobalADProfiles, 0);
@@ -387,21 +385,6 @@ populate_mGlobalAnnotations()
 
 
 
-void
-SExpDesignUI::
-populate_mGlobalADProfiles()
-{
-        gtk_list_store_clear( mGlobalADProfiles);
-        for ( auto &P : global_artifact_detection_profiles ) {
-                GtkTreeIter iter;
-                gtk_list_store_append( mGlobalADProfiles, &iter);
-                gtk_list_store_set( mGlobalADProfiles, &iter,
-                                    0, P.first.c_str(),
-                                    -1);
-        }
-        gtk_combo_box_set_model( eGlobalADProfiles, (GtkTreeModel*)mGlobalADProfiles);
-}
-
 
 
 void
diff --git a/upstream/src/aghermann/ui/sf/Makefile.am b/upstream/src/aghermann/ui/sf/Makefile.am
index e1a16e7..9b90deb 100644
--- a/upstream/src/aghermann/ui/sf/Makefile.am
+++ b/upstream/src/aghermann/ui/sf/Makefile.am
@@ -28,7 +28,7 @@ liba_a_SOURCES := \
 	widgets.hh \
 	d/artifacts.hh \
 	d/artifacts.cc \
-	d/artifacts-construct.cc \
+	d/artifacts-profiles_cb.cc \
 	d/artifacts_cb.cc \
 	d/artifacts-simple.hh \
 	d/artifacts-simple.cc \
diff --git a/upstream/src/aghermann/ui/sf/channel.cc b/upstream/src/aghermann/ui/sf/channel.cc
index 346c298..4643931 100644
--- a/upstream/src/aghermann/ui/sf/channel.cc
+++ b/upstream/src/aghermann/ui/sf/channel.cc
@@ -379,7 +379,7 @@ calculate_dirty_percent()
 
 void
 SScoringFacility::SChannel::
-detect_artifacts( const metrics::mc::SArtifactDetectionPP& P)
+detect_artifacts( const metrics::mc::SArtifactDetectionPPack& P)
 {
         auto marked =
                 metrics::mc::detect_artifacts( signal_original, samplerate(), P);
@@ -613,7 +613,12 @@ SScoringFacility::SChannel::
 _put_selection()
 {
         if ( selection_end_time - selection_start_time > 1. ) {
-                auto& P = _p._p.global_artifact_detection_profiles["default"];
+                static metrics::mc::SArtifactDetectionPPack P;
+                static bool first_post = true;
+                if (first_post) {
+                        metrics::mc::make_default_SArtifactDetectionPPack(P);
+                        first_post = false;
+                }
                 auto sssu =
                         metrics::mc::do_sssu_reduction(
                                 valarray<TFloat> {signal_filtered[ slice (selection_start, (selection_end - selection_start), 1) ]},
diff --git a/upstream/src/aghermann/ui/sf/channel.hh b/upstream/src/aghermann/ui/sf/channel.hh
index fdd2d90..57a95b6 100644
--- a/upstream/src/aghermann/ui/sf/channel.hh
+++ b/upstream/src/aghermann/ui/sf/channel.hh
@@ -90,7 +90,7 @@ struct SScoringFacility::SChannel {
       // artifacts
         float percent_dirty;
         float calculate_dirty_percent();
-        void detect_artifacts( const metrics::mc::SArtifactDetectionPP&);
+        void detect_artifacts( const metrics::mc::SArtifactDetectionPPack&);
         pair<double, double>
         mark_flat_regions_as_artifacts( double at_least_this_long, double pad);
 
diff --git a/upstream/src/aghermann/ui/sf/d/artifacts-construct.cc b/upstream/src/aghermann/ui/sf/d/artifacts-construct.cc
deleted file mode 100644
index 7adb378..0000000
--- a/upstream/src/aghermann/ui/sf/d/artifacts-construct.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *       File name:  aghermann/ui/sf/d/artifacts-construct.cc
- *         Project:  Aghermann
- *          Author:  Andrei Zavada <johnhommer at gmail.com>
- * Initial version:  2013-10-24
- *
- *         Purpose:  scoring facility Artifacts construct
- *
- *         License:  GPL
- */
-
-#include <stdexcept>
-
-#include "aghermann/ui/ui.hh"
-
-#include "artifacts.hh"
-
-using namespace std;
-using namespace agh::ui;
-
-SArtifactsDialogWidgets::
-SArtifactsDialogWidgets ()
-{
-        builder = gtk_builder_new();
-        if ( !gtk_builder_add_from_resource( builder, "/org/gtk/aghermann/sf-artifacts.glade", NULL) )
-                throw runtime_error( "Failed to load SF::artifacts glade resource");
-        gtk_builder_connect_signals( builder, NULL);
-
-        if ( !(AGH_GBGETOBJ (wSFAD)) ||
-             !(AGH_GBGETOBJ (eSFADProfiles)) ||
-             !(AGH_GBGETOBJ (bSFADProfileSave)) ||
-             !(AGH_GBGETOBJ (bSFADProfileDelete)) ||
-             !(AGH_GBGETOBJ (eSFADScope)) ||
-             !(AGH_GBGETOBJ (eSFADUpperThr)) ||
-             !(AGH_GBGETOBJ (eSFADLowerThr)) ||
-             !(AGH_GBGETOBJ (eSFADF0)) ||
-             !(AGH_GBGETOBJ (eSFADFc)) ||
-             !(AGH_GBGETOBJ (eSFADBandwidth)) ||
-             !(AGH_GBGETOBJ (eSFADMCGain)) ||
-             !(AGH_GBGETOBJ (eSFADBackpolate)) ||
-             !(AGH_GBGETOBJ (eSFADEValue)) ||
-             !(AGH_GBGETOBJ (eSFADHistRangeMin)) ||
-             !(AGH_GBGETOBJ (eSFADHistRangeMax)) ||
-             !(AGH_GBGETOBJ (eSFADHistBins)) ||
-             !(AGH_GBGETOBJ (eSFADSmoothSide)) ||
-             !(AGH_GBGETOBJ (eSFADSingleChannelPreview)) ||
-             !(AGH_GBGETOBJ (eSFADEstimateE)) ||
-             !(AGH_GBGETOBJ (eSFADUseThisRange)) ||
-             !(AGH_GBGETOBJ (eSFADUseComputedRange)) ||
-             !(AGH_GBGETOBJ (cSFADWhenEstimateEOn)) ||
-             !(AGH_GBGETOBJ (cSFADWhenEstimateEOff)) ||
-             !(AGH_GBGETOBJ (lSFADInfo)) ||
-             !(AGH_GBGETOBJ (lSFADDirtyPercent)) ||
-             !(AGH_GBGETOBJ (bSFADPreview)) ||
-             !(AGH_GBGETOBJ (bSFADApply)) ||
-             !(AGH_GBGETOBJ (bSFADCancel)) ||
-             !(AGH_GBGETOBJ (wSFADSaveProfileName)) ||
-             !(AGH_GBGETOBJ (eSFADSaveProfileNameName)) )
-                throw runtime_error ("Failed to construct SF widgets (7)");
-
-        mSFADProfiles = gtk_list_store_new( 1, G_TYPE_STRING);
-        // this GtkListStore is populated from the same source, but something
-        // haunting GTK+ forbids reuse of _p.mGlobalArtifactDetectionProfiles
-        gtk_combo_box_set_model_properly( eSFADProfiles, mSFADProfiles);
-
-        G_CONNECT_1 (wSFAD, show);
-        G_CONNECT_1 (wSFAD, close);
-        G_CONNECT_2 (wSFAD, delete, event);
-        eSFADProfiles_changed_cb_handler_id =
-                G_CONNECT_1 (eSFADProfiles, changed);
-        G_CONNECT_1 (bSFADProfileSave, clicked);
-        G_CONNECT_1 (bSFADProfileDelete, clicked);
-        G_CONNECT_1 (eSFADEstimateE, toggled);
-        G_CONNECT_1 (eSFADUseThisRange, toggled);
-        G_CONNECT_1 (bSFADPreview, toggled);
-        G_CONNECT_1 (bSFADApply, clicked);
-        G_CONNECT_1 (bSFADCancel, clicked);
-}
-
-
-SArtifactsDialogWidgets::
-~SArtifactsDialogWidgets ()
-{
-        gtk_widget_destroy( (GtkWidget*)wSFAD);
-        g_object_unref( (GObject*)mSFADProfiles);
-        g_object_unref( (GObject*)builder);
-}
-
-
-// Local Variables:
-// indent-tabs-mode: nil
-// tab-width: 8
-// c-basic-offset: 8
-// End:
diff --git a/upstream/src/aghermann/ui/sf/d/artifacts-profiles_cb.cc b/upstream/src/aghermann/ui/sf/d/artifacts-profiles_cb.cc
new file mode 100644
index 0000000..0d5c59b
--- /dev/null
+++ b/upstream/src/aghermann/ui/sf/d/artifacts-profiles_cb.cc
@@ -0,0 +1,92 @@
+/*
+ *       File name:  aghermann/ui/sf/d/artifacts-profiles_cb.cc
+ *         Project:  Aghermann
+ *          Author:  Andrei Zavada <johnhommer at gmail.com>
+ * Initial version:  2013-09-21
+ *
+ *         Purpose:  scoring facility: artifacts dialog profile mgmt callbacks
+ *
+ *         License:  GPL
+ */
+
+#include "artifacts.hh"
+
+using namespace std;
+using namespace agh::ui;
+
+extern "C" {
+
+void eSFADProfileList_changed_cb(
+        GtkComboBox*,
+        gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+
+        AD.eXProfileList_changed_cb();
+}
+
+
+
+
+void
+bSFADProfileSave_clicked_cb(
+        GtkButton*,
+        const gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+
+        AD.bXProfileSave_clicked_cb();
+}
+
+
+void
+bSFADProfileDiscard_clicked_cb(
+        GtkButton*,
+        const gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+
+        AD.bXProfileDiscard_clicked_cb();
+}
+
+
+void
+bSFADProfileRevert_clicked_cb(
+        GtkButton*,
+        const gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+
+        AD.bXProfileRevert_clicked_cb();
+}
+
+
+
+void eSFADProfileSaveName_changed_cb(
+        GtkEditable*,
+        const gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+
+        AD.eXProfileSaveName_changed_cb();
+}
+
+void
+eSFAD_any_profile_origin_toggled_cb(
+        GtkRadioButton*,
+        const gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+
+        AD.eX_any_profile_origin_toggled_cb();
+}
+
+
+
+} // extern "C"
+
+// Local Variables:
+// indent-tabs-mode: nil
+// tab-width: 8
+// c-basic-offset: 8
+// End:
diff --git a/upstream/src/aghermann/ui/sf/d/artifacts.cc b/upstream/src/aghermann/ui/sf/d/artifacts.cc
index fe8cfec..66506d5 100644
--- a/upstream/src/aghermann/ui/sf/d/artifacts.cc
+++ b/upstream/src/aghermann/ui/sf/d/artifacts.cc
@@ -27,9 +27,97 @@ artifacts_d()
 
 SScoringFacility::SArtifactsDialog::
 SArtifactsDialog (SScoringFacility& p_)
-      : using_channel (nullptr),
+      : SDirlevelStorableAdapter<metrics::mc::CArtifactDetector> (
+              *p_._p.ED, agh::SExpDirLevelId {p_._p.ED->group_of(p_.csubject()), p_.csubject().id, p_.session()},
+              mSFADProfiles, eSFADProfileList, eSFADProfileList_changed_cb_handler_id,
+              bSFADProfileSave, bSFADProfileRevert, bSFADProfileDiscard,
+              wSFADProfileSave, eSFADProfileSaveName,
+              eSFADProfileSaveOriginSubject, eSFADProfileSaveOriginExperiment, eSFADProfileSaveOriginUser,
+              bSFADProfileSaveOK),
+        using_channel (nullptr),
         _p (p_)
 {
+      // 1. widgets
+        builder = gtk_builder_new();
+        if ( !gtk_builder_add_from_resource( builder, "/org/gtk/aghermann/sf-artifacts.glade", NULL) )
+                throw runtime_error( "Failed to load SF::artifacts glade resource");
+        gtk_builder_connect_signals( builder, NULL);
+
+        AGH_GBGETOBJ (wSFAD);
+        AGH_GBGETOBJ (eSFADScope);
+        AGH_GBGETOBJ (eSFADUpperThr);
+        AGH_GBGETOBJ (eSFADLowerThr);
+        AGH_GBGETOBJ (eSFADF0);
+        AGH_GBGETOBJ (eSFADFc);
+        AGH_GBGETOBJ (eSFADBandwidth);
+        AGH_GBGETOBJ (eSFADMCGain);
+        AGH_GBGETOBJ (eSFADBackpolate);
+        AGH_GBGETOBJ (eSFADEValue);
+        AGH_GBGETOBJ (eSFADHistRangeMin);
+        AGH_GBGETOBJ (eSFADHistRangeMax);
+        AGH_GBGETOBJ (eSFADHistBins);
+        AGH_GBGETOBJ (eSFADSmoothSide);
+        AGH_GBGETOBJ (eSFADSingleChannelPreview);
+        AGH_GBGETOBJ (eSFADEstimateE);
+        AGH_GBGETOBJ (eSFADUseThisRange);
+        AGH_GBGETOBJ (eSFADUseComputedRange);
+        AGH_GBGETOBJ (cSFADWhenEstimateEOn);
+        AGH_GBGETOBJ (cSFADWhenEstimateEOff);
+        AGH_GBGETOBJ (lSFADInfo);
+        AGH_GBGETOBJ (lSFADDirtyPercent);
+        AGH_GBGETOBJ (bSFADPreview);
+        AGH_GBGETOBJ (bSFADApply);
+        AGH_GBGETOBJ (bSFADCancel);
+
+        AGH_GBGETOBJ (eSFADProfileList);
+        AGH_GBGETOBJ (bSFADProfileSave);
+        AGH_GBGETOBJ (bSFADProfileRevert);
+        AGH_GBGETOBJ (bSFADProfileDiscard);
+        AGH_GBGETOBJ (wSFADProfileSave);
+        AGH_GBGETOBJ (eSFADProfileSaveName);
+        AGH_GBGETOBJ (eSFADProfileSaveOriginSubject);
+        AGH_GBGETOBJ (eSFADProfileSaveOriginExperiment);
+        AGH_GBGETOBJ (eSFADProfileSaveOriginUser);
+        AGH_GBGETOBJ (bSFADProfileSaveOK);
+
+        mSFADProfiles = gtk_list_store_new( 1, G_TYPE_STRING);
+        // this GtkListStore is populated from the same source, but something
+        // haunting GTK+ forbids reuse of _p.mGlobalArtifactDetectionProfiles
+        gtk_combo_box_set_model_properly( eSFADProfileList, mSFADProfiles);
+
+        G_CONNECT_1 (wSFAD, show);
+        G_CONNECT_1 (wSFAD, close);
+        G_CONNECT_2 (wSFAD, delete, event);
+
+        eSFADProfileList_changed_cb_handler_id =
+                G_CONNECT_1 (eSFADProfileList, changed);
+
+        G_CONNECT_1 (bSFADProfileSave, clicked);
+        G_CONNECT_1 (bSFADProfileRevert, clicked);
+        G_CONNECT_1 (bSFADProfileDiscard, clicked);
+
+        for ( auto& W : {eSFADUpperThr, eSFADLowerThr, eSFADScope,
+                         eSFADF0, eSFADFc, eSFADBandwidth, eSFADMCGain, eSFADBackpolate, eSFADEValue,
+                                eSFADHistRangeMin, eSFADHistRangeMax, eSFADHistBins, eSFADSmoothSide} )
+                g_signal_connect(
+                        W, "value-changed",
+                        (GCallback)eSFAD_any_profile_value_changed_cb,
+                        this);
+
+        G_CONNECT_1 (eSFADEstimateE, toggled);
+        G_CONNECT_1 (eSFADUseThisRange, toggled);
+
+        G_CONNECT_1 (bSFADPreview, toggled);
+        G_CONNECT_1 (bSFADApply, clicked);
+        G_CONNECT_1 (bSFADCancel, clicked);
+
+        for ( auto& W : {eSFADProfileSaveOriginUser, eSFADProfileSaveOriginExperiment, eSFADProfileSaveOriginSubject} )
+                g_signal_connect(
+                        W, "toggled",
+                        (GCallback)eSFAD_any_profile_origin_toggled_cb,
+                        this);
+      // 2. vars
+        auto& P = Pp2.Pp;
         W_V.reg( eSFADScope,              &P.scope);
         W_V.reg( eSFADUpperThr,           &P.upper_thr);
         W_V.reg( eSFADLowerThr,           &P.lower_thr);
@@ -46,33 +134,72 @@ SArtifactsDialog (SScoringFacility& p_)
         W_V.reg( eSFADSmoothSide,   (int*)&P.smooth_side);
         W_V.reg( eSFADUseThisRange,       &P.use_range);
 
-        populate_mSFADProfiles();
+        atomic_up();
+}
+
+
+SScoringFacility::SArtifactsDialog::
+~SArtifactsDialog ()
+{
+        gtk_widget_destroy( (GtkWidget*)wSFADProfileSave);
+        gtk_widget_destroy( (GtkWidget*)wSFAD);
+        g_object_unref( (GObject*)mSFADProfiles);
+        g_object_unref( (GObject*)builder);
 }
 
 
+// a very odd one out!
+// putting these in libmetrics.so brings in a hell of dependencies
+// which are not needed for standalone operations (such as in agh-profile-gen)
+metrics::mc::CArtifactDetector::
+CArtifactDetector (const string& name_, agh::TExpDirLevel level_, agh::CExpDesign& ED_, const agh::SExpDirLevelId& level_id_)
+      : CStorablePPack (common_subdir, name_, level_, ED_, level_id_)
+{
+        using agh::confval::SValidator;
+        config_keys_g.assign({
+                SValidator<double>("scope",          &Pp.scope,           SValidator<double>::SVFRangeIn (0.5, 60.)),
+                SValidator<double>("upper_thr",      &Pp.upper_thr,       SValidator<double>::SVFRangeIn (0., 100.)),
+                SValidator<double>("lower_thr",      &Pp.lower_thr,       SValidator<double>::SVFRangeIn (-100., 0.)),
+                SValidator<double>("f0",             &Pp.f0,              SValidator<double>::SVFRangeIn (.1, 80.)),
+                SValidator<double>("fc",             &Pp.fc,              SValidator<double>::SVFRangeIn (.1, 80.)),
+                SValidator<double>("bandwidth",      &Pp.bandwidth,       SValidator<double>::SVFRangeIn (.1, 40.)),
+                SValidator<double>("mc_gain",        &Pp.mc_gain,         SValidator<double>::SVFRangeIn (0., 100.)),
+                SValidator<double>("iir_backpolate", &Pp.iir_backpolate,  SValidator<double>::SVFRangeIn (0., 1.)),
+                SValidator<double>("E",              &Pp.E,               SValidator<double>::SVFRangeIn (.1, 100.)),
+                SValidator<double>("dmin",           &Pp.dmin,            SValidator<double>::SVFRangeIn (-100., 100.)),
+                SValidator<double>("dmax",           &Pp.dmax,            SValidator<double>::SVFRangeIn (-100., 100.)),
+        });
+        config_keys_z.assign({
+                SValidator<size_t>("sssu_hist_size", &Pp.sssu_hist_size,  SValidator<size_t>::SVFRangeIn (10, 1000)),
+                SValidator<size_t>("smooth_side",    &Pp.smooth_side,     SValidator<size_t>::SVFRangeIn (0, 10)),
+        });
+        config_keys_b.assign({
+                SValidator<bool>("estimate_E", &Pp.estimate_E),
+                SValidator<bool>("use_range", &Pp.use_range),
+        });
 
+        make_default_SArtifactDetectionPPack( Pp);
+        load();
+}
 
-// maybe it's not needed in GTK+ 3?
-void
-SScoringFacility::SArtifactsDialog::
-populate_mSFADProfiles()
+
+string
+metrics::mc::CArtifactDetector::
+serialize() const
 {
-        g_signal_handler_block( eSFADProfiles, eSFADProfiles_changed_cb_handler_id);
-        gtk_list_store_clear( mSFADProfiles);
-        for ( auto &P : _p._p.global_artifact_detection_profiles ) {
-                GtkTreeIter iter;
-                gtk_list_store_append(
-                        mSFADProfiles, &iter);
-                gtk_list_store_set(
-                        mSFADProfiles, &iter,
-                        0, P.first.c_str(),
-                        -1);
-        }
-        gtk_combo_box_set_model( eSFADProfiles, (GtkTreeModel*)mSFADProfiles);
-        g_signal_handler_unblock( eSFADProfiles, eSFADProfiles_changed_cb_handler_id);
+        return move(
+                CStorablePPack::serialize() +
+                agh::str::sasprintf(
+                        "scope:%g; upper_thr:%g; lower_thr:%g; f0:%g; fc:%g; bandwidth:%g; mc_gain:%g; iir_backpolate:%g; E:%g; dmin:%g; dmax:%g; sssu_hist_size:%zu; smooth_side:%zu; estimate_E:%d;  use_range:%d;",
+                        Pp.scope, Pp.upper_thr, Pp.lower_thr, Pp.f0, Pp.fc, Pp.bandwidth, Pp.mc_gain, Pp.iir_backpolate,
+                        Pp.E, Pp.dmin, Pp.dmax, Pp.sssu_hist_size, Pp.smooth_side,
+                        Pp.estimate_E, Pp.use_range));
 }
 
 
+
+
+
 // Local Variables:
 // Mode: c++
 // indent-tabs-mode: nil
diff --git a/upstream/src/aghermann/ui/sf/d/artifacts.hh b/upstream/src/aghermann/ui/sf/d/artifacts.hh
index d2cf7e3..e254618 100644
--- a/upstream/src/aghermann/ui/sf/d/artifacts.hh
+++ b/upstream/src/aghermann/ui/sf/d/artifacts.hh
@@ -18,6 +18,7 @@
 
 #include "libmetrics/mc-artifacts.hh"
 #include "libsigfile/source-base.hh"
+#include "aghermann/ui/dirlevel-storable-adapter.hh"
 #include "aghermann/ui/ui++.hh"
 #include "aghermann/ui/sf/sf.hh"
 
@@ -30,10 +31,25 @@ using namespace std;
 namespace agh {
 namespace ui {
 
-struct SArtifactsDialogWidgets {
+struct SScoringFacility::SArtifactsDialog
+  : public SDirlevelStorableAdapter<metrics::mc::CArtifactDetector> {
+
+        DELETE_DEFAULT_METHODS (SArtifactsDialog);
 
-        SArtifactsDialogWidgets ();
-       ~SArtifactsDialogWidgets ();
+        SArtifactsDialog (SScoringFacility&);
+       ~SArtifactsDialog ();
+
+        SScoringFacility::SChannel
+                *using_channel;
+        sigfile::SArtifacts
+                artifacts_backup;
+        bool    orig_signal_visible_backup;
+        list<pair<SScoringFacility::SChannel*, bool>>
+                channels_visible_backup;
+        bool    suppress_preview_handler;
+
+        SScoringFacility&
+                _p;
 
         GtkBuilder *builder;
 
@@ -42,11 +58,12 @@ struct SArtifactsDialogWidgets {
         GtkListStore
                 *mSFADProfiles;
         GtkComboBox
-                *eSFADProfiles;
-        gulong  eSFADProfiles_changed_cb_handler_id;
+                *eSFADProfileList;
+        gulong  eSFADProfileList_changed_cb_handler_id;
         GtkButton
                 *bSFADProfileSave,
-                *bSFADProfileDelete;
+                *bSFADProfileRevert,
+                *bSFADProfileDiscard;
         GtkSpinButton
                 *eSFADUpperThr,
                 *eSFADLowerThr,
@@ -78,36 +95,17 @@ struct SArtifactsDialogWidgets {
         GtkButton
                 *bSFADApply,
                 *bSFADCancel;
+
         GtkDialog
-                *wSFADSaveProfileName;
+                *wSFADProfileSave;
+        GtkToggleButton
+                *eSFADProfileSaveOriginSubject,
+                *eSFADProfileSaveOriginExperiment,
+                *eSFADProfileSaveOriginUser;
+        GtkButton
+                *bSFADProfileSaveOK;
         GtkEntry
-                *eSFADSaveProfileNameName;
-};
-
-struct SScoringFacility::SArtifactsDialog
-    : public SArtifactsDialogWidgets {
-
-        DELETE_DEFAULT_METHODS (SArtifactsDialog);
-
-        SArtifactsDialog (SScoringFacility&);
-
-        SScoringFacility::SChannel
-                *using_channel;
-        metrics::mc::SArtifactDetectionPP
-                P;
-        sigfile::SArtifacts
-                artifacts_backup;
-        bool    orig_signal_visible_backup;
-        list<pair<SScoringFacility::SChannel*, bool>>
-                channels_visible_backup;
-        bool    suppress_preview_handler;
-        SUIVarCollection
-                W_V;
-
-        SScoringFacility&
-                _p;
-
-        void populate_mSFADProfiles();
+                *eSFADProfileSaveName;
 };
 
 
@@ -119,9 +117,15 @@ extern "C" {
 gboolean wSFAD_delete_event_cb(GtkWidget*, GdkEvent*, gpointer);
 void wSFAD_close_cb(GtkWidget*, gpointer);
 void wSFAD_show_cb(GtkWidget*, gpointer);
-void eSFADProfiles_changed_cb( GtkComboBox*, gpointer);
+void eSFADProfileList_changed_cb( GtkComboBox*, gpointer);
 void bSFADProfileSave_clicked_cb( GtkButton*, gpointer);
-void bSFADProfileDelete_clicked_cb( GtkButton*, gpointer);
+void bSFADProfileRevert_clicked_cb( GtkButton*, gpointer);
+void bSFADProfileDiscard_clicked_cb( GtkButton*, gpointer);
+
+void eSFAD_any_profile_value_changed_cb( GtkSpinButton*, gpointer);
+void eSFAD_any_criteria_value_changed_cb( GtkSpinButton*, gpointer);
+void eSFAD_any_profile_origin_toggled_cb(GtkRadioButton*, gpointer);
+
 void eSFADEstimateE_toggled_cb( GtkToggleButton*, gpointer);
 void eSFADUseThisRange_toggled_cb( GtkToggleButton*, gpointer);
 void bSFADPreview_toggled_cb( GtkToggleButton*, gpointer);
diff --git a/upstream/src/aghermann/ui/sf/d/artifacts_cb.cc b/upstream/src/aghermann/ui/sf/d/artifacts_cb.cc
index 1f5472b..23f7d60 100644
--- a/upstream/src/aghermann/ui/sf/d/artifacts_cb.cc
+++ b/upstream/src/aghermann/ui/sf/d/artifacts_cb.cc
@@ -19,69 +19,74 @@ using namespace agh::ui;
 
 
 
+extern "C" {
+
 void
-eSFADProfiles_changed_cb(
-        GtkComboBox* w,
+wSFAD_show_cb(
+        GtkWidget*,
         const gpointer userdata)
 {
         auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
         auto& SF = AD._p;
+        SF.artifacts_dialog_shown = true;
 
-        if ( gtk_combo_box_get_active( w) != -1 ) {
-                AD.P = SF._p.global_artifact_detection_profiles[
-                        gtk_combo_box_get_active_id(w)];
-                AD.W_V.up();
-                gtk_widget_set_sensitive( (GtkWidget*)AD.bSFADProfileDelete, TRUE);
-        } else
-                gtk_widget_set_sensitive( (GtkWidget*)AD.bSFADProfileDelete, FALSE);
-}
+        AD.load_profiles();
+        if ( AD.profiles.empty() )
+                AD.profiles.emplace_back(
+                        *SF._p.ED,
+                        agh::SExpDirLevelId {SF._p.ED->group_of(SF.csubject()), SF.csubject().id, SF.session()});
+        AD.populate_combo();
+        AD.set_profile_manage_buttons_visibility();
 
-void
-bSFADProfileSave_clicked_cb(
-        GtkButton*,
-        const gpointer userdata)
-{
-        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
-        auto& SF = AD._p;
+        // g_signal_emit_by_name( AD.eSFADEstimateE, "toggled");
+        // g_signal_emit_by_name( AD.eSFADEstimateE, "toggled");
+        // g_signal_emit_by_name( AD.eSFADUseThisRange, "toggled");
+        // g_signal_emit_by_name( AD.eSFADUseThisRange, "toggled");
 
-        if ( GTK_RESPONSE_OK ==
-             gtk_dialog_run( AD.wSFADSaveProfileName) ) {
-                AD.W_V.down();
-                SF._p.global_artifact_detection_profiles[
-                        gtk_entry_get_text( AD.eSFADSaveProfileNameName)] = AD.P;
+        gtk_widget_set_sensitive( (GtkWidget*)AD.bSFADApply, FALSE);
+        AD.suppress_preview_handler = true;
+        gtk_toggle_button_set_active( AD.bSFADPreview, FALSE);
+        AD.suppress_preview_handler = false;
 
-                SF._p.populate_mGlobalADProfiles();
-                AD.populate_mSFADProfiles(); // stupid
+        AD.using_channel = AD._p.using_channel;  // because the latter is mutable, and AD isn't modal
 
-                int now_active = SF._p.global_artifact_detection_profiles.size()-1;
-                gtk_combo_box_set_active( AD.eSFADProfiles, now_active);
-                gtk_combo_box_set_active( SF._p.eGlobalADProfiles, now_active);
-        }
+        gtk_label_set_text(
+                AD.lSFADInfo,
+                snprintf_buf( "Artifact detection in channel %s", AD.using_channel->name()));
+        gtk_label_set_text(
+                AD.lSFADDirtyPercent,
+                snprintf_buf( "%4.2f%% marked", AD.using_channel->calculate_dirty_percent() * 100));
 }
 
-void
-bSFADProfileDelete_clicked_cb(
-        GtkButton*,
+gboolean
+wSFAD_delete_event_cb(
+        GtkWidget*,
+        GdkEvent*,
         const gpointer userdata)
 {
-        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
-        auto& SF = AD._p;
+        bSFADCancel_clicked_cb( NULL, userdata);
+        return TRUE;
+}
 
-        const gchar *deleting_id = gtk_combo_box_get_active_id( AD.eSFADProfiles);
-        int deleting = gtk_combo_box_get_active( AD.eSFADProfiles);
-        SF._p.global_artifact_detection_profiles.erase( deleting_id);
+void
+wSFAD_close_cb(
+        GtkWidget*,
+        const gpointer userdata)
+{
+        bSFADCancel_clicked_cb( NULL, userdata);
+}
 
-        SF._p.populate_mGlobalADProfiles();
-        AD.populate_mSFADProfiles(); // stupid
 
-        if ( SF._p.global_artifact_detection_profiles.size() > 0 &&
-             deleting > (int)SF._p.global_artifact_detection_profiles.size()-1 )
-                gtk_combo_box_set_active( AD.eSFADProfiles, deleting-1);
 
-        g_signal_emit_by_name( AD.eSFADProfiles, "changed");
+void
+eSFAD_any_profile_value_changed_cb(
+        GtkSpinButton* button,
+        const gpointer userdata)
+{
+        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
+        AD.eX_any_profile_value_changed_cb();
 }
 
-
 void
 eSFADEstimateE_toggled_cb(
         GtkToggleButton *b,
@@ -112,15 +117,8 @@ eSFADUseThisRange_toggled_cb(
         gtk_widget_set_sensitive(
                 (GtkWidget*)AD.eSFADHistRangeMax,
                 state);
-
-        // if ( state ) {
-        //         snprintf_buf( "Estimated <i>E</i> = %4.2f",
-        //                       SF.using_channel -> estimate_E( P));
-        // }
 }
 
-
-
 void
 bSFADApply_clicked_cb(
         GtkButton*,
@@ -182,7 +180,7 @@ bSFADPreview_toggled_cb(
                 AD.orig_signal_visible_backup = AD.using_channel->draw_original_signal;
                 AD.artifacts_backup = AD.using_channel->artifacts;
 
-                AD.using_channel->detect_artifacts( (AD.W_V.down(), AD.P));
+                AD.using_channel->detect_artifacts( (AD.W_V.down(), AD.Pp2.Pp));
                 AD.using_channel->draw_original_signal = true;
                 gtk_widget_set_sensitive( (GtkWidget*)AD.bSFADApply, TRUE);
 
@@ -213,58 +211,6 @@ bSFADPreview_toggled_cb(
         gtk_widget_queue_draw( (GtkWidget*)SF.daSFHypnogram);
 }
 
-
-
-void
-wSFAD_show_cb(
-        GtkWidget*,
-        const gpointer userdata)
-{
-        auto& AD = *(SScoringFacility::SArtifactsDialog*)userdata;
-        auto& SF = AD._p;
-        SF.artifacts_dialog_shown = true;
-
-        AD.using_channel = AD._p.using_channel;  // because the latter is mutable, and AD isn't modal
-
-        AD.W_V.up();
-        AD.populate_mSFADProfiles();
-        g_signal_emit_by_name( AD.eSFADProfiles, "changed");
-
-        g_signal_emit_by_name( AD.eSFADEstimateE, "toggled");
-        g_signal_emit_by_name( AD.eSFADEstimateE, "toggled");
-        g_signal_emit_by_name( AD.eSFADUseThisRange, "toggled");
-        g_signal_emit_by_name( AD.eSFADUseThisRange, "toggled");
-
-        gtk_widget_set_sensitive( (GtkWidget*)AD.bSFADApply, FALSE);
-        AD.suppress_preview_handler = true;
-        gtk_toggle_button_set_active( AD.bSFADPreview, FALSE);
-        AD.suppress_preview_handler = false;
-
-        gtk_label_set_text(
-                AD.lSFADInfo,
-                snprintf_buf( "Artifact detection in channel %s", AD.using_channel->name()));
-        gtk_label_set_text(
-                AD.lSFADDirtyPercent,
-                snprintf_buf( "%4.2f%% marked", AD.using_channel->calculate_dirty_percent() * 100));
-}
-
-
-gboolean
-wSFAD_delete_event_cb(
-        GtkWidget*,
-        GdkEvent*,
-        const gpointer userdata)
-{
-        bSFADCancel_clicked_cb( NULL, userdata);
-        return TRUE;
-}
-
-void
-wSFAD_close_cb(
-        GtkWidget*,
-        const gpointer userdata)
-{
-        bSFADCancel_clicked_cb( NULL, userdata);
 }
 
 // Local Variables:
diff --git a/upstream/src/libmetrics/forward-decls.hh b/upstream/src/libmetrics/forward-decls.hh
index b9a074b..bbee699 100644
--- a/upstream/src/libmetrics/forward-decls.hh
+++ b/upstream/src/libmetrics/forward-decls.hh
@@ -25,7 +25,7 @@ class CProfile;
 namespace mc {
 struct SPPack;
 class CProfile;
-struct SArtifactDetectionPP;
+struct SArtifactDetectionPPack;
 }
 
 namespace swu {
diff --git a/upstream/src/libmetrics/mc-artifacts.cc b/upstream/src/libmetrics/mc-artifacts.cc
index e94e59d..75eaed7 100644
--- a/upstream/src/libmetrics/mc-artifacts.cc
+++ b/upstream/src/libmetrics/mc-artifacts.cc
@@ -24,11 +24,12 @@
 
 using namespace std;
 
-template vector<size_t> metrics::mc::detect_artifacts( const valarray<TFloat>&, size_t, const SArtifactDetectionPP&);
+template vector<size_t> metrics::mc::detect_artifacts( const valarray<TFloat>&, size_t, const SArtifactDetectionPPack&);
 
 namespace metrics {
 namespace mc {
 
+
 template <>
 double
 estimate_E( const valarray<double>& sssu_diff,
diff --git a/upstream/src/libmetrics/mc-artifacts.hh b/upstream/src/libmetrics/mc-artifacts.hh
index 77005cf..f59afc6 100644
--- a/upstream/src/libmetrics/mc-artifacts.hh
+++ b/upstream/src/libmetrics/mc-artifacts.hh
@@ -16,6 +16,7 @@
 #include <vector>
 #include <valarray>
 #include "libsigproc/sigproc.hh"
+#include "aghermann/expdesign/dirlevel.hh"
 
 #if HAVE_CONFIG_H && !defined(VERSION)
 #  include "config.h"
@@ -26,31 +27,109 @@ using namespace std;
 namespace metrics {
 namespace mc {
 
-struct SArtifactDetectionPP {
-        double	scope,
+struct SArtifactDetectionPPack {
+        double  scope,
                 upper_thr, lower_thr,
                 f0, fc, bandwidth,
                 mc_gain, iir_backpolate;
-        double	E, dmin, dmax;
-        size_t	sssu_hist_size,
+        double  E, dmin, dmax;
+        size_t  sssu_hist_size,
                 smooth_side;
-        bool	estimate_E,
+        bool    estimate_E,
                 use_range;
-        SArtifactDetectionPP ()
-              : scope (4.),
-		upper_thr (9.), lower_thr (-9.),
-		f0 (1.), fc (1.8), bandwidth (1.5),
-		mc_gain (10.), iir_backpolate (.5),
-		E (4.), dmin (-10), dmax (20),
-		sssu_hist_size (100), smooth_side (0),
-		estimate_E (true), use_range (false)
+
+        bool
+        operator==( const SArtifactDetectionPPack& rv) const
+                {
+                        return  scope == rv.scope &&
+                                upper_thr == rv.upper_thr &&
+                                lower_thr == rv.lower_thr &&
+                                f0 == rv.f0 &&
+                                fc == rv.fc &&
+                                bandwidth == rv.bandwidth &&
+                                mc_gain == rv.mc_gain &&
+                                iir_backpolate == rv.iir_backpolate &&
+                                E == rv.E &&
+                                dmin == rv.dmin &&
+                                dmax == rv.dmax &&
+                                sssu_hist_size == rv.sssu_hist_size &&
+                                smooth_side == rv.smooth_side &&
+                                estimate_E == rv.estimate_E &&
+                                use_range == rv.use_range;
+                }
+};
+
+inline void
+make_default_SArtifactDetectionPPack( SArtifactDetectionPPack& p)
+{
+        p.scope = 4.;
+        p.upper_thr = 9.;
+        p.lower_thr = -9.;
+        p.f0 = 1.;
+        p.fc = 1.8;
+        p.bandwidth = 1.5;
+        p.mc_gain = 10.;
+        p.iir_backpolate = .5;
+        p.E = 4.;
+        p.dmin = -10;
+        p.dmax = 20;
+        p.sssu_hist_size = 100;
+        p.smooth_side = 0;
+        p.estimate_E = true;
+        p.use_range = false;
+}
+
+
+
+class CArtifactDetector
+  : public agh::CStorablePPack {
+
+    public:
+        static constexpr const char* common_subdir = ".artifact-profiles/";
+
+        CArtifactDetector (const string& name_, agh::TExpDirLevel, agh::CExpDesign&, const agh::SExpDirLevelId&);
+        CArtifactDetector (agh::CExpDesign& ED_, const agh::SExpDirLevelId& level_id_)
+              : CStorablePPack (common_subdir, "(unnamed)", agh::TExpDirLevel::transient, ED_, level_id_)
                 {}
+        explicit CArtifactDetector (const CArtifactDetector& rv)
+              : CStorablePPack (rv),
+                Pp (rv.Pp)
+                {
+                        // assign_keys();
+                }
+        explicit CArtifactDetector (CArtifactDetector&& rv)
+              : CStorablePPack (common_subdir, move(rv.name), rv.level, rv.ED, move(rv.level_id)),
+                Pp (move(rv.Pp))
+                {
+                        rv.level = agh::TExpDirLevel::transient;  // we do the saving, prevent rv from doing so
+                        // assign_keys();
+                }
+
+       ~CArtifactDetector ()
+                {
+                        save();
+                }
+
+        CArtifactDetector&
+        operator=( const CArtifactDetector& rv)
+                { return Pp = rv.Pp, *this; }
+
+        bool
+        operator==( const CArtifactDetector& rv) const
+                { return Pp == rv.Pp; }  // don't bother about CStorable
+
+        string serialize() const;
+
+        SArtifactDetectionPPack
+                Pp;
 };
 
+
+
 template <typename T>
 vector<size_t> // don't estimate, use pi*B*x^2 (E) as provided
 detect_artifacts( const valarray<T>& signal, size_t sr,
-                  const SArtifactDetectionPP& P);
+                  const SArtifactDetectionPPack& P);
 
 
 template <typename T>
diff --git a/upstream/src/libmetrics/mc-artifacts.ii b/upstream/src/libmetrics/mc-artifacts.ii
index 192f7a1..4d63512 100644
--- a/upstream/src/libmetrics/mc-artifacts.ii
+++ b/upstream/src/libmetrics/mc-artifacts.ii
@@ -11,12 +11,12 @@
  */
 
 
-extern template vector<size_t> detect_artifacts( const valarray<TFloat>&, size_t, const SArtifactDetectionPP&);
+extern template vector<size_t> detect_artifacts( const valarray<TFloat>&, size_t, const SArtifactDetectionPPack&);
 
 template <typename T>
 vector<size_t> // don't estimate, use pi*B*x^2 (E) as provided
 detect_artifacts( const valarray<T>& signal, size_t sr,
-                  const SArtifactDetectionPP& P)
+                  const SArtifactDetectionPPack& P)
 {
         auto	sssu
                 = do_sssu_reduction(

-- 
Alioth's /git/debian-med/git-commit-notice on /srv/git.debian.org/git/debian-med/aghermann.git



More information about the debian-med-commit mailing list