Index: branches/FACT++_scripts_refactoring/CheckUnderflow.js
===================================================================
--- branches/FACT++_scripts_refactoring/CheckUnderflow.js	(revision 18233)
+++ branches/FACT++_scripts_refactoring/CheckUnderflow.js	(revision 18237)
@@ -1,21 +1,31 @@
 'use strict';
+
+include('scripts/CheckStates.js');
+include('scripts/Hist2D.js');
+include('scripts/Func.js');
+include('scripts/takeRun.js');
+include('scripts/tools.js');
+
 if (!("CheckUnderflow" in this)){
     var CheckUnderflow = {
-        checkUnderflow : function(){
-
-            include('scripts/CheckStates.js');
-            // include('scripts/Hist1D.js');  // DN: apparently not even used.
-            include('scripts/Hist2D.js');
-            include('scripts/Func.js');
-            include('scripts/takeRun.js');
-
-            console.out(("\n%78s".$("")).replace(/ /g, "="));
-
-            if (dim.state("FTM_CONTROL").name=="TriggerOn")
-            {
-                dim.send("FTM_CONTROL/STOP_TRIGGER");
-                dim.wait("FTM_CONTROL", "Valid");
-            }
-
+
+        check_power_on_time_and_get_drs_runs : function(){
+            console.out("Checking power on time");
+
+            var service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
+            var runs = service_drs.get(5000, false);
+            var power = dim.state("AGILENT_CONTROL_50V").time;
+            var now   = new Date();
+
+            console.out(" * Now:                "+now);
+            console.out(" * Last power cycle:   "+power);
+            console.out(" * Last DRS calib set: "+(runs.data?runs.time:"none"));
+
+            service_drs.close();
+            return runs;
+        },
+
+        // find a GOOD name! 
+        check_states_one : function(){
             var table = [
              [ "MCP",                 [ "Idle"      ] ],
@@ -36,190 +46,208 @@
                         "try to find out what happened...");
             }
-
-            // ===================================================================
-
-           
-
-            console.out("Checking power on time");
-
-            var service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
-
-            var runs = service_drs.get(5000, false);
-            //if (!runs)
-            //    throw new Error("Could not connect to FAD_CONTROL/DRS_RUNS");
-
-            var power = dim.state("AGILENT_CONTROL_50V").time;
-            var now   = new Date();
-
-            var diff = (now-runs.time)/3600000;
-
-            console.out(" * Now:                "+now);
-            console.out(" * Last power cycle:   "+power);
-            console.out(" * Last DRS calib set: "+(runs.data?runs.time:"none"));
-
-
-            if (1)//diff>8 && now.getHours()>16 || runs.time<power)
-            {
-                console.out("Checking send.");
-                CheckStates.checkSend(["FAD_CONTROL", "MCP", "RATE_CONTROL"]);
-                console.out("Checking send: done");
-
-                //console.out("Most probablay the camera has not been checked for underflows yet.");
-
-                var service_event = new Subscription("FAD_CONTROL/EVENT_DATA");
-
-                dim.send("FAD_CONTROL/START_DRS_CALIBRATION");
-                dim.send("FAD_CONTROL/SET_FILE_FORMAT", 0);
-
-                var sub_runs = new Subscription("FAD_CONTROL/RUNS");
-                var sruns = sub_runs.get(5000, false);
-
-                if (dim.state("FAD_CONTROL").name=="RunInProgress" || sruns.qos==1)
+        },
+
+        prepare_drs_calibration : function(){
+            dim.send("FAD_CONTROL/START_DRS_CALIBRATION");
+            dim.send("FAD_CONTROL/SET_FILE_FORMAT", 0);
+
+            var sub_runs = new Subscription("FAD_CONTROL/RUNS");
+            var sruns = sub_runs.get(5000, false);
+
+            if (dim.state("FAD_CONTROL").name=="RunInProgress" || sruns.qos==1)
+            {
+                dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
+                dim.wait("FAD_CONTROL", "Connected", 3000);
+
+                console.out("Waiting for open files to be closed...");
+                v8.timeout(60000, function() { if (sub_runs.get(0, false).qos==0) return true; });
+
+                // Although the file should be closed now, the processing might still be on-going
+                // and delayed events might be received. The only fix for that issue is to
+                // add the run number to the data we are waiting for
+                v8.sleep(5000);
+            }
+
+            sub_runs.close();
+        },
+
+        take_at_least_one_drs_gain_events : function(){
+            console.out("Starting drs-gain... waiting for new event");
+
+            var fad_event_data_service = new Subscription("FAD_CONTROL/EVENT_DATA");
+            var sub_startrun = new Subscription("FAD_CONTROL/START_RUN");
+            var sub_incomplete = new Subscription("FAD_CONTROL/INCOMPLETE");
+            var sub_connections = new Subscription("FAD_CONTROL/CONNECTIONS");
+            sub_connections.get(5000);
+            sub_startrun.get(5000);
+            takeRun.attachFadControlIncompleteOnChange();
+
+            while (1)
+            {
+                var event_counter_before_run = fad_event_data_service.get(10000, false).counter;
+
+                var stop_run_after_first_events_recieved = function ()
                 {
-                    dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
-                    dim.wait("FAD_CONTROL", "Connected", 3000);
-
-                    console.out("Waiting for open files to be closed...");
-                    v8.timeout(60000, function() { if (sub_runs.get(0, false).qos==0) return true; });
-
-                    // Although the file should be closed now, the processing might still be on-going
-                    // and delayed events might be received. The only fix for that issue is to
-                    // add the run number to the data we are waiting for
-                    v8.sleep(5000);
-                }
-
-                sub_runs.close();
-
-                console.out("Starting drs-gain... waiting for new event");
-
-                var sub_startrun = new Subscription("FAD_CONTROL/START_RUN");
-                var sub_incomplete = new Subscription("FAD_CONTROL/INCOMPLETE");
-                var sub_connections = new Subscription("FAD_CONTROL/CONNECTIONS");
-                sub_connections.get(5000);
-                sub_startrun.get(5000);
-
-                
-                takeRun.attachFadControlIncompleteOnChange();
-
-                while (1)
-                {
-                    var event_counter = service_event.get(10000, false).counter;
-
-                    var stop = function ()
+                    while (1)
                     {
-                        while (1)
+                        var current_event_counter = fad_event_data_service.get(0, false).counter;
+                        if (dim.state("MCP").name=="TakingData" && current_event_counter > event_counter_before_run)
                         {
-                            if (dim.state("MCP").name=="TakingData" && service_event.get(0, false).counter>event_counter)
-                            {
-                                dim.send("MCP/STOP");
-                                console.out("Sent MCP/STOP.");
-                                return;
-                            }
-                            v8.sleep(100);
+                            dim.send("MCP/STOP");
+                            console.out("Sent MCP/STOP.");
+                            return;
                         }
-                    }
-
-                    var thread = new Thread(250, stop);
-
-                    var rc = takeRun.takeRun("drs-gain");
-
-                    thread.kill();
-
-                    if (rc)
-                        break;
-                }
-
-                console.out("Event received.");
-
-                sub_incomplete.close();
-                sub_connections.close();
-                sub_startrun.close();
-
-
-                // FIXME: Restore DRS calibration in case of failure!!
-                //        FAD Re-connect in case of failure?
-                //        MCP/RESET in case of failure?
-                //        Proper error reporting!
-
-                var event = service_event.get(3000);//, false);
-                service_event.close();
-
-                console.out("Run stopped.");
-
-                dim.send("RATE_CONTROL/STOP"); // GlobalThresholdSet -> Connected
-                dim.wait("MCP", "Idle", 3000);
-
-                var nn = runs.data && runs.data.length>0 && runs.obj['roi']>0 ? runs.obj['run'].reduce(Func.max) : -1;
-                if (nn>0)
-                {
-                    var night = runs.obj['night'];
-
-                    var yy =  night/10000;
-                    var mm = (night/100)%100;
-                    var dd =  night%100;
-
-                    var filefmt = "/loc_data/raw/%d/%02d/%02d/%8d_%03d.drs.fits";
-
-                    dim.log("Trying to restore last DRS calibration #"+nn+"  ["+runs.time+"; "+night+"]");
-
-                    // FIXME: Timeout
-                    var drs_counter = service_drs.get(0, false).counter;
-                    dim.send("FAD_CONTROL/LOAD_DRS_CALIBRATION", filefmt.$(yy, mm, dd, night, nn));
-
-                    try
-                    {
-                        var now = new Date();
-                        v8.timeout(3000, function() { if (service_drs.get(0, false).counter>drs_counter) return true; });
-                        dim.log("Last DRS calibration restored ["+(new Date()-now)/1000+"s]");
-                    }
-                    catch (e)
-                    {
-                        console.warn("Restoring last DRS calibration failed.");
+                        v8.sleep(100);
                     }
                 }
 
-                var hist = Hist2D.Hist2D(16, -2048.5, 2048.5, 11, -10, 100);
-
-                var data = event.obj;
-
-                for (var i=0; i<1440; i++)
-                    hist.fill(data.avg[i], isNaN(data.rms[i])?-1:data.rms[i]);
-
-                hist.print();
-
-                var stat0 = Func.stat(data.avg, function(val, idx) { if (val<600) console.out(" PIX[hw="+idx+"]="+val); return val<600; });
-                var stat1 = Func.stat(data.rms);
-
-                console.out("Avg[min]=%.1f".$(stat0.min));
-                console.out("Avg[avg]=%.1f +- %.1f".$(stat0.avg, stat0.rms));
-                console.out("Avg[max]=%.1f".$(+stat0.max));
-                console.out("Avg[cnt]="+stat0.count);
-                console.out("");
-                console.out("Rms[min]=%.1f".$(stat1.min));
-                console.out("Rms[avg]=%.1f +- %.1f".$(stat1.avg, stat1.rms));
-                console.out("Rms[max]=%.1f".$(stat1.max));
-                console.out(("%78s\n".$("")).replace(/ /g, "="));
-
-                //      OK                            UNDERFLOW
-                // ------------------------------------------------------
-                // Avg[min]=722.0                Avg[min]=-380.0
-                // Avg[avg]=815.9 +- 45.9        Avg[avg]= 808.0 +- 102.0
-                // Avg[max]=930.5                Avg[max]= 931.1
-                // Avg[cnt]=0                    Avg[cnt]= 9
-
-                // Rms[min]=14.0                 Rms[min]=13.9
-                // Rms[avg]=16.5 +- 1.6          Rms[avg]=18.8 +- 26.8
-                // Rms[max]=44.0                 Rms[max]=382.1
-
-                if (stat0.count>0)
+                var thread = new Thread(250, stop_run_after_first_events_recieved);
+
+                var run_was_okay = takeRun.takeRun("drs-gain");
+
+                thread.kill();
+
+                if (run_was_okay)
+                    break;
+            }
+
+            console.out("Event received.");
+
+            sub_incomplete.close();
+            sub_connections.close();
+            sub_startrun.close();
+
+
+            // FIXME: Restore DRS calibration in case of failure!!
+            //        FAD Re-connect in case of failure?
+            //        MCP/RESET in case of failure?
+            //        Proper error reporting!
+
+            var event = fad_event_data_service.get(3000);
+            fad_event_data_service.close();
+
+            console.out("Run stopped.");
+
+            dim.send("RATE_CONTROL/STOP"); // GlobalThresholdSet -> Connected
+            dim.wait("MCP", "Idle", 3000);
+
+            return event;
+        },
+
+        get_max_drs_run_number : function(drs_runs)
+        {
+            if ( drs_runs.data 
+                    && drs_runs.data.length > 0 
+                    && drs_runs.obj['roi'] > 0 ) 
+                return drs_runs.obj['run'].reduce(Func.max):
+            else
+                return -1;
+        },
+
+        stop_trigger : function(){
+            if (dim.state("FTM_CONTROL").name=="TriggerOn")
+            {
+                dim.send("FTM_CONTROL/STOP_TRIGGER");
+                dim.wait("FTM_CONTROL", "Valid");
+            }
+        },
+
+        path_from_night_n_run : function(night_int, run_number, extension){
+
+            var yy =  night_int/10000;
+            var mm = (night_int/100)%100;
+            var dd =  night_int%100;
+
+            var filefmt = "/loc_data/raw/%d/%02d/%02d/%8d_%03d."+extension;
+            var path = filefmt.$(yy, mm, dd, night_int, run_number);
+            return path;
+        },
+
+        drs_path_from_night_n_run : function(night_int, run_number){
+            return path_from_night_n_run(night_int, run_number, "drs.fits"):
+        },
+
+        restore_drs_calibration : function(drs_runs){
+            var max_drs_run_number = this.get_max_drs_run_number(drs_runs);
+            if (max_drs_run_number > 0)
+            {
+                var night = drs_runs.obj['night'];
+
+                dim.log("Trying to restore last DRS calibration #"+max_drs_run_number+"  ["+drs_runs.time+"; "+night+"]");
+
+                // FIXME: Timeout
+                var service_drs = Subscription("FAD_CONTROL/DRS_RUNS");
+                if (!service_drs)
+                    service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
+                var drs_counter = service_drs.get(0, false).counter;
+                dim.send("FAD_CONTROL/LOAD_DRS_CALIBRATION", drs_path_from_night_n_run(night, max_drs_run_number));
+
+                try
                 {
-                    if (stat0.count>8)
-                        throw new Error("Underflow condition detected in about "+parseInt(stat0.count/9+.5)+" DRS.");
-
-                    console.warn("There is probably an underflow condition in one DRS... please check manually.");
+                    var now = new Date();
+                    v8.timeout(3000, function() { if (service_drs.get(0, false).counter>drs_counter) return true; });
+                    dim.log("Last DRS calibration restored ["+(new Date()-now)/1000+"s]");
                 }
-            }
-
-            service_drs.close();
+                catch (e)
+                {
+                    console.warn("Restoring last DRS calibration failed.");
+                }
+
+                service_drs.close();
+            }
+        },
+
+        analyse_drs_gain_event : function(event){
+            var data = event.obj;
+
+            var hist = Hist2D.Hist2D(16, -2048.5, 2048.5, 11, -10, 100);
+            for (var i=0; i<1440; i++)
+                hist.fill(data.avg[i], isNaN(data.rms[i])?-1:data.rms[i]);
+
+            hist.print();
+
+            var stat0 = Func.stat(data.avg, function(val, idx) { if (val<600) console.out(" PIX[hw="+idx+"]="+val); return val<600; });
+            var stat1 = Func.stat(data.rms);
+
+            console.out("Avg[min]=%.1f".$(stat0.min));
+            console.out("Avg[avg]=%.1f +- %.1f".$(stat0.avg, stat0.rms));
+            console.out("Avg[max]=%.1f".$(+stat0.max));
+            console.out("Avg[cnt]="+stat0.count);
+            console.out("");
+            console.out("Rms[min]=%.1f".$(stat1.min));
+            console.out("Rms[avg]=%.1f +- %.1f".$(stat1.avg, stat1.rms));
+            console.out("Rms[max]=%.1f".$(stat1.max));
+            console.out(tools.line_of_equal_signs(78));
+
+            //      OK                            UNDERFLOW
+            // ------------------------------------------------------
+            // Avg[min]=722.0                Avg[min]=-380.0
+            // Avg[avg]=815.9 +- 45.9        Avg[avg]= 808.0 +- 102.0
+            // Avg[max]=930.5                Avg[max]= 931.1
+            // Avg[cnt]=0                    Avg[cnt]= 9
+
+            // Rms[min]=14.0                 Rms[min]=13.9
+            // Rms[avg]=16.5 +- 1.6          Rms[avg]=18.8 +- 26.8
+            // Rms[max]=44.0                 Rms[max]=382.1
+
+            if (stat0.count>0)
+            {
+                if (stat0.count>8)
+                    throw new Error("Underflow condition detected in about "+parseInt(stat0.count/9+.5)+" DRS.");
+
+                console.warn("There is probably an underflow condition in one DRS... please check manually.");
+            }
+        },
+
+        checkUnderflow : function(){
+            console.out( tools.line_of_equal_signs(78) );            
+            this.stop_trigger();
+            this.check_states_one();
+            var drs_runs = this.check_power_on_time_and_get_drs_runs();
+            CheckStates.checkSend(["FAD_CONTROL", "MCP", "RATE_CONTROL"], 5000, true);            
+            this.prepare_drs_calibration();
+            var event = this.take_at_least_one_drs_gain_events();
+            this.restore_drs_calibration(drs_runs);
+            this.analyse_drs_gain_event(event):
         },
     };
