]> jspc29.x-matter.uni-frankfurt.de Git - coral.git/commitdiff
added flot library for plotting in browser
authorMichael Wiebusch <m.wiebusch@gsi.de>
Tue, 27 Jan 2015 09:30:53 +0000 (10:30 +0100)
committerMichael Wiebusch <m.wiebusch@gsi.de>
Tue, 27 Jan 2015 09:30:53 +0000 (10:30 +0100)
user_interface/coral_scanner.js
user_interface/coral_scanner.pm
user_interface/has_settings.pm
user_interface/jquery.flot.selection.js [new file with mode: 0644]
user_interface/jquery.mwiebusch.js
user_interface/pmt_ro.pl
user_interface/pmt_ro.pm
user_interface/shm_manager.pm

index 3a5df4f805c6d2e6c3a781d06308d1ad18e37e1c..854f2ccfb429e4b989bfe72b6f8ddadc3c90f0a9 100644 (file)
@@ -7,7 +7,7 @@ var timer;
 var scan_meta;
 var coral_scanner_settings;
 var pmt_ro_settings;
-
+var spectrum;
 
 
 
@@ -28,6 +28,7 @@ $(document).ready(function(){
   unfolds($("#show_main_controls"),$("#main_controls_container"));
   unfolds($("#show_pmt_ro_settings"),$("#pmt_ro_settings_container"));
   unfolds($("#show_table_control_settings"),$("#table_control_settings_container"));
+  unfolds($("#show_pmt_spectrum"),$("#pmt_spectrum_container"));
   
   $("#button_home").click(function(){
     home();
@@ -45,6 +46,20 @@ $(document).ready(function(){
     get_scan_svg();
   });
   
+  $("#button_program_padiwa").click(function(){
+    apply_device_settings();
+  });
+  $("#button_plot_spectrum").click(function(){
+    spectrum = get_spectrum_JSON();
+    plot_spectrum();
+  });
+  $("#button_clear_spectrum").click(function(){
+    clear_spectrum();
+  });
+  $("#button_record_spectrum").click(function(){
+    record_spectrum();
+  });
+  
   $("#button_count").click(function(){
      $('#text_count_out').val("");
      $.ajax({
@@ -70,6 +85,10 @@ $(document).ready(function(){
     signal_thresh();
   });
   
+  $('#checkbox_log_spectrum').change(function(){
+//     alert($(this).prop('checked'));
+    plot_spectrum();
+  });
   
   $( "#progressbar" ).progressbar({
     value: 100
@@ -78,17 +97,112 @@ $(document).ready(function(){
   get_coral_scanner_settings();
   get_pmt_ro_settings();
   
-
+  spectrum = get_spectrum_JSON();
+  plot_spectrum();
   
   get_scan_meta();
 //   get_scan_svg();
   
   set_clear_timer();
+//   make_flot();
   
 });
 
 
 
+function make_flot(){
+  
+  var d1 = [];
+                for (var i = 0; i < 14; i += 0.5) {
+                        d1.push([i, Math.sin(i)]);
+                }
+
+                var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]];
+
+                var d3 = [];
+                for (var i = 0; i < 14; i += 0.5) {
+                        d3.push([i, Math.cos(i)]);
+                }
+
+                var d4 = [];
+                for (var i = 0; i < 14; i += 0.1) {
+                        d4.push([i, Math.sqrt(i * 10)]);
+                }
+
+                var d5 = [];
+                for (var i = 0; i < 14; i += 0.5) {
+                        d5.push([i, Math.sqrt(i)]);
+                }
+
+                var d6 = [];
+                for (var i = 0; i < 14; i += 0.5 + Math.random()) {
+                        d6.push([i, Math.sqrt(2*i + Math.sin(i) + 5)]);
+                }
+
+                $.plot("#spectrum_plot_container", [{
+                        data: d1,
+                        lines: { show: true, fill: true }
+                }, {
+                        data: d2,
+                        bars: { show: true }
+                }, {
+                        data: d3,
+                        points: { show: true }
+                }, {
+                        data: d4,
+                        lines: { show: true }
+                }, {
+                        data: d5,
+                        lines: { show: true },
+                        points: { show: true }
+                }, {
+                        data: d6,
+                        lines: { show: true, steps: true }
+                }]);
+  
+  
+}
+
+function plot_spectrum() {
+  var data = [];
+  for (x in spectrum){
+    data.push(
+      {
+        data: spectrum[x].data,
+        bars: { show: true ,  barWidth: 0.8*parseFloat(spectrum[x].meta.bin_width), align: "center" },
+        label: x
+      }
+    );
+  }
+  
+  var options = {
+    selection: {
+      mode: "xy"
+    },
+    xaxis : {
+      autoscaleMargin: .1
+    },
+    legend : {
+      position : "nw"
+    }
+  };
+  
+  
+  if($('#checkbox_log_spectrum').prop('checked')){
+      $.extend(options,{
+        yaxis: {
+          transform: function (v) { return Math.log(v); },
+          inverseTransform: function (v) { return Math.exp(v); }
+        }
+      });
+  }
+
+  
+  flot_w_selectZoom('#spectrum_plot_container', data, options);
+  
+}
+
+
 
 
 
@@ -161,21 +275,21 @@ function get_scan_meta(){
 }
 
 
-function get_scan_status_report(){
-  $.ajax({
-        url:       "coral_scanner.pl",
-        cache:     false,
-        async:     true,
-        dataType:  "text",
-        data:      {
-          sub        : "scan_status",
-          report     : "true"
-        },
-        success:   function(answer) {
-          $("#scan_status_container").html("<pre>"+answer+"</pre>");
-        }
-     });
-}
+// function get_scan_status_report(){
+//   $.ajax({
+//         url:       "coral_scanner.pl",
+//         cache:     false,
+//         async:     true,
+//         dataType:  "text",
+//         data:      {
+//           sub        : "scan_status",
+//           report     : "true"
+//         },
+//         success:   function(answer) {
+//           $("#scan_status_container").html("<pre>"+answer+"</pre>");
+//         }
+//      });
+// }
 
 function get_scan_status(){
   $.ajax({
@@ -213,6 +327,20 @@ function home(){
      });
 }
 
+function apply_device_settings(){
+  $.ajax({
+        url:       "pmt_ro.pl",
+        cache:     false,
+        async:     false,
+        dataType:  "text",
+        data:      {
+          sub        : "apply_device_settings"
+        },
+        success:   function(answer) {
+        }
+     });
+}
+
 function signal_thresh(){
   $.ajax({
         url:       "pmt_ro.pl",
@@ -286,4 +414,53 @@ function load_settings(url){
         }
      });
   return return_obj;
+}
+
+function get_spectrum_JSON(){
+  var return_obj;
+  $.ajax({
+        url:       "pmt_ro.pl",
+        cache:     false,
+        async:     false,
+        dataType:  "json",
+        data:      {
+            sub      : "spectrum_JSON",
+        },
+        success:   function(answer) {
+          return_obj = answer;
+        }
+     });
+  return return_obj;
+}
+
+function clear_spectrum(){
+  $.ajax({
+        url:       "pmt_ro.pl",
+        cache:     false,
+        async:     false,
+        dataType:  "text",
+        data:      {
+            sub      : "clear_spectrum",
+        },
+        success:   function(answer) {
+          alert(answer);
+        }
+     });
+}
+
+function record_spectrum(){
+  $.ajax({
+        url:       "coral_scanner.pl",
+        cache:     false,
+        async:     true,
+        dataType:  "text",
+        data:      {
+            sub      : "record_spectrum",
+            name     : $('#text_spectrum_name').val()
+        },
+        success:   function(answer) {
+          spectrum = get_spectrum_JSON();
+          plot_spectrum();
+        }
+     });
 }
\ No newline at end of file
index 4e6a41b55b892311b18ccddcdaf1dab156daef12..83ee2e2415c399725f3a03b7b276d8b151c328c0 100644 (file)
@@ -98,6 +98,8 @@ sub main_html {
       {-src => './jquery.min.js'},
       {-src => './jquery.timer.js'},
       {-src => './jquery-ui.js'},
+      {-src => './jquery.flot.js'},
+      {-src => './jquery.flot.selection.js'},
       {-src => './jquery.mwiebusch.js'},
       {-src => './coral_scanner.js'},
 #       {-src => './SVGPan.js'},
@@ -125,7 +127,7 @@ sub main_html {
   print br;
   print '<div id="slider-range"></div>';
   print br;
-  print "<input type='button' value='replot' id='button_replot'></input>";
+  print "<input type='button' value='replot' id='button_replot'>";
   print br;
   print br;
   print "estimated scan duration: ".hms_string($self->scan_ETA());
@@ -149,20 +151,34 @@ sub main_html {
   print "<input type='button' id='button_home' value='home'>";
   print "<input type='button' id='button_start_scan' value='start scan'>";
   print "<input type='button' id='button_stop_scan' value='stop scan'>";
+  print "<input type='button' id='button_program_padiwa' value='program padiwa settings'>";
   print "<input type='button' id='button_test' value='test'>";
   print br br;
   print "PMT test:";
   print br;
   print "<input type='button' id='button_thresh' value='set threshold'>";
-  print "<input type='text' id='text_thresh' value=''></input>";
+  print "<input type='text' id='text_thresh' value=''>";
   print br;
   print "<input type='button' id='button_count' value='count'>";
-  print "<input type='text' id='text_count' value='1'></input>";
+  print "<input type='text' id='text_count' value='1'>";
   print " [s] ";
-  print "<input type='text' id='text_count_out' value='' readonly></input>";
+  print "<input type='text' id='text_count_out' value='' readonly>";
+  
+  
   
   print "</div>";
   
+  print "<p id='show_pmt_spectrum' class='quasibutton' >spectrum</p>";
+  print "<div id='pmt_spectrum_container' class='stylishBox padded'>";
+  print '<div id="spectrum_plot_container" style="width:600px;height:300px"></div>';
+  print "<input type='button' id='button_plot_spectrum' value='plot spectrum'>";
+  print "<input type='button' id='button_clear_spectrum' value='clear spectrum'>";
+  print "<label><input type='checkbox' id='checkbox_log_spectrum' >log y</label>";
+  print br br;
+  print "record name: ";
+  print "<input type='text' id='text_spectrum_name' value='signal'>";
+  print "<input type='button' id='button_record_spectrum' value='record spectrum'>";
+  print "</div>";
   
   print "<p id='show_pmt_ro_settings' class='quasibutton' >pmt_ro settings</p>";
   print "<div align=right id='pmt_ro_settings_container' class='stylishBox settings_form hidden_by_default'>";
@@ -368,6 +384,19 @@ sub start_scan {
   $self->scan_sample();
 }
 
+sub record_spectrum {
+  my $self= shift;
+  my %options = @_;
+  my $name = $options{name} || "signal";
+  
+  daemonize();
+  $self->{pmt_ro}->spectral_scan_onesided(
+    name => $name
+  );
+  
+  return " ";
+}
+
 sub home {
   my $self= shift;
   daemonize();
index 5fc8e27ca76618fd8dfdd42b01e7deb0b077897a..3fb6e69f4538b82dc13676b78f478815eded93af 100644 (file)
@@ -26,11 +26,10 @@ sub load_settings {
 }
 
 sub save_settings {
+# make sure load settings is executed first, or you will lose your data!
   my $self=shift;
   my %options = @_;
   
-  $self->require_run("load_settings");
-  
   my $settings_file = $self->{settings_file};
   
   $self->{settings} = { %{$self->{settings}}, %options};
diff --git a/user_interface/jquery.flot.selection.js b/user_interface/jquery.flot.selection.js
new file mode 100644 (file)
index 0000000..d3c20fa
--- /dev/null
@@ -0,0 +1,360 @@
+/* Flot plugin for selecting regions of a plot.
+
+Copyright (c) 2007-2014 IOLA and Ole Laursen.
+Licensed under the MIT license.
+
+The plugin supports these options:
+
+selection: {
+       mode: null or "x" or "y" or "xy",
+       color: color,
+       shape: "round" or "miter" or "bevel",
+       minSize: number of pixels
+}
+
+Selection support is enabled by setting the mode to one of "x", "y" or "xy".
+In "x" mode, the user will only be able to specify the x range, similarly for
+"y" mode. For "xy", the selection becomes a rectangle where both ranges can be
+specified. "color" is color of the selection (if you need to change the color
+later on, you can get to it with plot.getOptions().selection.color). "shape"
+is the shape of the corners of the selection.
+
+"minSize" is the minimum size a selection can be in pixels. This value can
+be customized to determine the smallest size a selection can be and still
+have the selection rectangle be displayed. When customizing this value, the
+fact that it refers to pixels, not axis units must be taken into account.
+Thus, for example, if there is a bar graph in time mode with BarWidth set to 1
+minute, setting "minSize" to 1 will not make the minimum selection size 1
+minute, but rather 1 pixel. Note also that setting "minSize" to 0 will prevent
+"plotunselected" events from being fired when the user clicks the mouse without
+dragging.
+
+When selection support is enabled, a "plotselected" event will be emitted on
+the DOM element you passed into the plot function. The event handler gets a
+parameter with the ranges selected on the axes, like this:
+
+       placeholder.bind( "plotselected", function( event, ranges ) {
+               alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
+               // similar for yaxis - with multiple axes, the extra ones are in
+               // x2axis, x3axis, ...
+       });
+
+The "plotselected" event is only fired when the user has finished making the
+selection. A "plotselecting" event is fired during the process with the same
+parameters as the "plotselected" event, in case you want to know what's
+happening while it's happening,
+
+A "plotunselected" event with no arguments is emitted when the user clicks the
+mouse to remove the selection. As stated above, setting "minSize" to 0 will
+destroy this behavior.
+
+The plugin allso adds the following methods to the plot object:
+
+- setSelection( ranges, preventEvent )
+
+  Set the selection rectangle. The passed in ranges is on the same form as
+  returned in the "plotselected" event. If the selection mode is "x", you
+  should put in either an xaxis range, if the mode is "y" you need to put in
+  an yaxis range and both xaxis and yaxis if the selection mode is "xy", like
+  this:
+
+       setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
+
+  setSelection will trigger the "plotselected" event when called. If you don't
+  want that to happen, e.g. if you're inside a "plotselected" handler, pass
+  true as the second parameter. If you are using multiple axes, you can
+  specify the ranges on any of those, e.g. as x2axis/x3axis/... instead of
+  xaxis, the plugin picks the first one it sees.
+
+- clearSelection( preventEvent )
+
+  Clear the selection rectangle. Pass in true to avoid getting a
+  "plotunselected" event.
+
+- getSelection()
+
+  Returns the current selection in the same format as the "plotselected"
+  event. If there's currently no selection, the function returns null.
+
+*/
+
+(function ($) {
+    function init(plot) {
+        var selection = {
+                first: { x: -1, y: -1}, second: { x: -1, y: -1},
+                show: false,
+                active: false
+            };
+
+        // FIXME: The drag handling implemented here should be
+        // abstracted out, there's some similar code from a library in
+        // the navigation plugin, this should be massaged a bit to fit
+        // the Flot cases here better and reused. Doing this would
+        // make this plugin much slimmer.
+        var savedhandlers = {};
+
+        var mouseUpHandler = null;
+        
+        function onMouseMove(e) {
+            if (selection.active) {
+                updateSelection(e);
+                
+                plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
+            }
+        }
+
+        function onMouseDown(e) {
+            if (e.which != 1)  // only accept left-click
+                return;
+            
+            // cancel out any text selections
+            document.body.focus();
+
+            // prevent text selection and drag in old-school browsers
+            if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
+                savedhandlers.onselectstart = document.onselectstart;
+                document.onselectstart = function () { return false; };
+            }
+            if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
+                savedhandlers.ondrag = document.ondrag;
+                document.ondrag = function () { return false; };
+            }
+
+            setSelectionPos(selection.first, e);
+
+            selection.active = true;
+
+            // this is a bit silly, but we have to use a closure to be
+            // able to whack the same handler again
+            mouseUpHandler = function (e) { onMouseUp(e); };
+            
+            $(document).one("mouseup", mouseUpHandler);
+        }
+
+        function onMouseUp(e) {
+            mouseUpHandler = null;
+            
+            // revert drag stuff for old-school browsers
+            if (document.onselectstart !== undefined)
+                document.onselectstart = savedhandlers.onselectstart;
+            if (document.ondrag !== undefined)
+                document.ondrag = savedhandlers.ondrag;
+
+            // no more dragging
+            selection.active = false;
+            updateSelection(e);
+
+            if (selectionIsSane())
+                triggerSelectedEvent();
+            else {
+                // this counts as a clear
+                plot.getPlaceholder().trigger("plotunselected", [ ]);
+                plot.getPlaceholder().trigger("plotselecting", [ null ]);
+            }
+
+            return false;
+        }
+
+        function getSelection() {
+            if (!selectionIsSane())
+                return null;
+            
+            if (!selection.show) return null;
+
+            var r = {}, c1 = selection.first, c2 = selection.second;
+            $.each(plot.getAxes(), function (name, axis) {
+                if (axis.used) {
+                    var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]); 
+                    r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
+                }
+            });
+            return r;
+        }
+
+        function triggerSelectedEvent() {
+            var r = getSelection();
+
+            plot.getPlaceholder().trigger("plotselected", [ r ]);
+
+            // backwards-compat stuff, to be removed in future
+            if (r.xaxis && r.yaxis)
+                plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
+        }
+
+        function clamp(min, value, max) {
+            return value < min ? min: (value > max ? max: value);
+        }
+
+        function setSelectionPos(pos, e) {
+            var o = plot.getOptions();
+            var offset = plot.getPlaceholder().offset();
+            var plotOffset = plot.getPlotOffset();
+            pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
+            pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
+
+            if (o.selection.mode == "y")
+                pos.x = pos == selection.first ? 0 : plot.width();
+
+            if (o.selection.mode == "x")
+                pos.y = pos == selection.first ? 0 : plot.height();
+        }
+
+        function updateSelection(pos) {
+            if (pos.pageX == null)
+                return;
+
+            setSelectionPos(selection.second, pos);
+            if (selectionIsSane()) {
+                selection.show = true;
+                plot.triggerRedrawOverlay();
+            }
+            else
+                clearSelection(true);
+        }
+
+        function clearSelection(preventEvent) {
+            if (selection.show) {
+                selection.show = false;
+                plot.triggerRedrawOverlay();
+                if (!preventEvent)
+                    plot.getPlaceholder().trigger("plotunselected", [ ]);
+            }
+        }
+
+        // function taken from markings support in Flot
+        function extractRange(ranges, coord) {
+            var axis, from, to, key, axes = plot.getAxes();
+
+            for (var k in axes) {
+                axis = axes[k];
+                if (axis.direction == coord) {
+                    key = coord + axis.n + "axis";
+                    if (!ranges[key] && axis.n == 1)
+                        key = coord + "axis"; // support x1axis as xaxis
+                    if (ranges[key]) {
+                        from = ranges[key].from;
+                        to = ranges[key].to;
+                        break;
+                    }
+                }
+            }
+
+            // backwards-compat stuff - to be removed in future
+            if (!ranges[key]) {
+                axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
+                from = ranges[coord + "1"];
+                to = ranges[coord + "2"];
+            }
+
+            // auto-reverse as an added bonus
+            if (from != null && to != null && from > to) {
+                var tmp = from;
+                from = to;
+                to = tmp;
+            }
+            
+            return { from: from, to: to, axis: axis };
+        }
+        
+        function setSelection(ranges, preventEvent) {
+            var axis, range, o = plot.getOptions();
+
+            if (o.selection.mode == "y") {
+                selection.first.x = 0;
+                selection.second.x = plot.width();
+            }
+            else {
+                range = extractRange(ranges, "x");
+
+                selection.first.x = range.axis.p2c(range.from);
+                selection.second.x = range.axis.p2c(range.to);
+            }
+
+            if (o.selection.mode == "x") {
+                selection.first.y = 0;
+                selection.second.y = plot.height();
+            }
+            else {
+                range = extractRange(ranges, "y");
+
+                selection.first.y = range.axis.p2c(range.from);
+                selection.second.y = range.axis.p2c(range.to);
+            }
+
+            selection.show = true;
+            plot.triggerRedrawOverlay();
+            if (!preventEvent && selectionIsSane())
+                triggerSelectedEvent();
+        }
+
+        function selectionIsSane() {
+            var minSize = plot.getOptions().selection.minSize;
+            return Math.abs(selection.second.x - selection.first.x) >= minSize &&
+                Math.abs(selection.second.y - selection.first.y) >= minSize;
+        }
+
+        plot.clearSelection = clearSelection;
+        plot.setSelection = setSelection;
+        plot.getSelection = getSelection;
+
+        plot.hooks.bindEvents.push(function(plot, eventHolder) {
+            var o = plot.getOptions();
+            if (o.selection.mode != null) {
+                eventHolder.mousemove(onMouseMove);
+                eventHolder.mousedown(onMouseDown);
+            }
+        });
+
+
+        plot.hooks.drawOverlay.push(function (plot, ctx) {
+            // draw selection
+            if (selection.show && selectionIsSane()) {
+                var plotOffset = plot.getPlotOffset();
+                var o = plot.getOptions();
+
+                ctx.save();
+                ctx.translate(plotOffset.left, plotOffset.top);
+
+                var c = $.color.parse(o.selection.color);
+
+                ctx.strokeStyle = c.scale('a', 0.8).toString();
+                ctx.lineWidth = 1;
+                ctx.lineJoin = o.selection.shape;
+                ctx.fillStyle = c.scale('a', 0.4).toString();
+
+                var x = Math.min(selection.first.x, selection.second.x) + 0.5,
+                    y = Math.min(selection.first.y, selection.second.y) + 0.5,
+                    w = Math.abs(selection.second.x - selection.first.x) - 1,
+                    h = Math.abs(selection.second.y - selection.first.y) - 1;
+
+                ctx.fillRect(x, y, w, h);
+                ctx.strokeRect(x, y, w, h);
+
+                ctx.restore();
+            }
+        });
+        
+        plot.hooks.shutdown.push(function (plot, eventHolder) {
+            eventHolder.unbind("mousemove", onMouseMove);
+            eventHolder.unbind("mousedown", onMouseDown);
+            
+            if (mouseUpHandler)
+                $(document).unbind("mouseup", mouseUpHandler);
+        });
+
+    }
+
+    $.plot.plugins.push({
+        init: init,
+        options: {
+            selection: {
+                mode: null, // one of null, "x", "y" or "xy"
+                color: "#e8cfac",
+                shape: "round", // one of "round", "miter", or "bevel"
+                minSize: 5 // minimum number of pixels
+            }
+        },
+        name: 'selection',
+        version: '1.1'
+    });
+})(jQuery);
index 10a32019c7023c5c7d3e4695b394b87204b690b7..a0e88fdad828b4a14a106a475cdcf4fdd3d34456 100644 (file)
@@ -28,3 +28,24 @@ function unfolds(button,container){
   }
   
 }
+
+function flot_w_selectZoom(id,data,options) {
+  $.plot(id, data, options);
+  
+  $(id).bind("plotselected", function (event, ranges) {
+    // clamp the zooming to prevent eternal zoom
+    if (ranges.xaxis.to - ranges.xaxis.from < 0.00001) {
+      ranges.xaxis.to = ranges.xaxis.from + 0.00001;
+    }
+    if (ranges.yaxis.to - ranges.yaxis.from < 0.00001) {
+      ranges.yaxis.to = ranges.yaxis.from + 0.00001;
+    }
+    // do the zooming
+    plot = $.plot(id, data,
+      $.extend(true, {}, options, {
+        xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to },
+        yaxis: { min: ranges.yaxis.from, max: ranges.yaxis.to }
+      })
+    );
+  });
+}
\ No newline at end of file
index ec0f614263b238eaecfea501ca7b8f656eea5b6a..5b173f63eb125050ce4c9ad3e82b1a25a3b1dae7 100755 (executable)
@@ -31,7 +31,9 @@ my $dispatch_table = {
   spectral_scan => 1,
   spectral_scan_onesided => 1,
   dead_time => 1,
-  apply_device_settings => 1
+  apply_device_settings => 1,
+  spectrum_JSON => 1,
+  clear_spectrum => 1
 };
 
 CGI_dispatch::dispatch_sub(package => $self, dispatch_table => $dispatch_table);
\ No newline at end of file
index b173b7ba2044e90c0d53d779dfdde97bd8fab16f..eaa2c75de07865a6be2c59571fa3e6efc6523742 100644 (file)
@@ -9,6 +9,9 @@ use POSIX;
 use FileHandle;
 use regio;
 
+use shm_manager;
+use JSON;
+
 use misc_subs;
 use has_settings;
 our @ISA = qw/has_settings/; # assimilate the methods of the has_settings class
@@ -48,7 +51,11 @@ sub new {
     is_calibrated => 0,
     dead_time => 265, # corresponds to 2 us dead time
     signal_thresh => 0,
-    veto_thresh => 0
+    veto_thresh => 0,
+    spectrum_start => -2000,
+    spectrum_stop  => 0,
+    spectrum_bins  => 24,
+    spectrum_delay  => 1
   };
 
   $self->{has_run} = {}; # remember which subs already have run
@@ -60,7 +67,12 @@ sub new {
     %options
   };
   bless($self, $class);
-  $self->load_settings(); 
+  $self->load_settings();
+  
+  $self->{spectrum_shm} = shm_manager->new(
+    shmPath => "./",
+    shmName => __PACKAGE__.".spectrum" );
+  $self->{spectrum_shm}->initShm(); 
   return $self;
 }
 
@@ -93,47 +105,47 @@ sub apply_device_settings {
   return;
 }
 
-sub spectral_scan {
-  my $self = shift;
-  my %options = @_;
-  
-#  $self->require_run("load_settings");
-  $self->require_run("setup_regio");
-  
-  die "device zero offset calibration has to be performed first!\n
-  run subroutine zero_calib!\n" unless $self->{settings}->{is_calibrated};
-  
-  my $start=$options{start};
-  my $stop=$options{stop};
-  my $bins=$options{bins}||64;
-  my $delay=$options{delay}||1;
-  my $verbose=$options{verbose};
-  
-  my $spec_width = $stop-$start;
-  my $bin_width = $spec_width/$bins;
-  
-  my $file = FileHandle->new("./test.dat", 'w');
-  
-  my $counts;
-  my $bin_pos;
-  my $spectrum;
-  
-  print "#bin\t#bin_pos\t#counts\n" if $verbose;
-  for (my $i=0; $i<$bins; $i++){
-    $self->veto_thresh(value => floor($start+$bin_width*$i) );
-    $self->signal_thresh(value => floor($start+$bin_width*($i+1)) );
-    $bin_pos = floor($start+$bin_width*($i+0.5));
-    $counts = $self->count(channel => "net", delay => $delay);
-    $spectrum->{$i} = { 
-      counts => $counts,
-      bin_pos => $bin_pos
-    };
-    print "$i\t$bin_pos\t$counts\n" if $verbose;
-    print $file "$i\t$bin_pos\t$counts\n";
-  }
-  return $spectrum;
-  
-}
+sub spectral_scan {
+  my $self = shift;
+  my %options = @_;
+#   
+#  $self->require_run("load_settings");
+  $self->require_run("setup_regio");
+#   
+  die "device zero offset calibration has to be performed first!\n
+  run subroutine zero_calib!\n" unless $self->{settings}->{is_calibrated};
+#   
+  my $start=$options{start};
+  my $stop=$options{stop};
+  my $bins=$options{bins}||64;
+  my $delay=$options{delay}||1;
+  my $verbose=$options{verbose};
+#   
+  my $spec_width = $stop-$start;
+  my $bin_width = $spec_width/$bins;
+#   
+  my $file = FileHandle->new("./test.dat", 'w');
+#   
+  my $counts;
+  my $bin_pos;
+  my $spectrum;
+#   
+  print "#bin\t#bin_pos\t#counts\n" if $verbose;
+  for (my $i=0; $i<$bins; $i++){
+    $self->veto_thresh(value => floor($start+$bin_width*$i) );
+    $self->signal_thresh(value => floor($start+$bin_width*($i+1)) );
+    $bin_pos = floor($start+$bin_width*($i+0.5));
+    $counts = $self->count(channel => "net", delay => $delay);
+    $spectrum->{$i} = { 
+      counts => $counts,
+      bin_pos => $bin_pos
+    };
+    print "$i\t$bin_pos\t$counts\n" if $verbose;
+    print $file "$i\t$bin_pos\t$counts\n";
+  }
+  return $spectrum;
+#   
+}
 
 sub spectral_scan_onesided {
   my $self = shift;
@@ -145,12 +157,12 @@ sub spectral_scan_onesided {
   die "device zero offset calibration has to be performed first!\n
   run subroutine zero_calib!\n" unless $self->{settings}->{is_calibrated};
   
-  my $start=$options{start};
-  my $stop=$options{stop};
-  my $bins=$options{bins}||64;
-  my $delay=$options{delay}||1;
-  my $verbose=$options{verbose};
-  my $tofile=$options{tofile};
+  my $start = (defined($options{start})) ? ($options{start}) : ($self->{settings}->{spectrum_start});
+  my $stop  = (defined($options{stop}))  ? ($options{stop})  : ($self->{settings}->{spectrum_stop});
+  my $bins  = (defined($options{bins}))  ? ($options{bins})  : ($self->{settings}->{spectrum_bins});
+  my $delay = (defined($options{delay})) ? ($options{delay}) : ($self->{settings}->{spectrum_delay});
+  my $name  = (defined($options{name}))  ? ($options{name})  : "signal";
+  my $verbose = $options{verbose};
   
   my $file = FileHandle->new("./cumul_spec.dat", 'w');
   
@@ -158,23 +170,31 @@ sub spectral_scan_onesided {
   my $bin_width = $spec_width/$bins;
   
   my $counts;
-  my $bin_pos;
-  my $spectrum;
+  my $thresh;
+  my $spectrum = {};
+  
+  $spectrum->{meta} = {
+    bin_width  => $bin_width,
+    spec_width => $spec_width,
+    delay      => $delay,
+    start      => $start,
+    stop       => $stop
+  };
+  $spectrum->{data} = [];
   
-  my $cumulation;
+
+  $self->{spectrum_shm}->updateShm({$name => $spectrum}); #write empty spectrum
   
-  print "#bin\t#bin_pos\t#counts\n" if $verbose;
+  print "#bin\t#thresh\t#counts\n" if $verbose;
   for (my $i=0; $i<$bins; $i++){
 #     $self->veto_thresh(value => floor($start+$bin_width*$i) );
     $self->signal_thresh(value => floor($start+$bin_width*$i) );
-    $bin_pos = floor($start+$bin_width*($i+0.5));
+    $thresh = floor($start+$bin_width*$i);
     $counts = $self->count(channel => "signal", delay => $delay);
-    $spectrum->{$i} = { 
-      counts => $counts,
-      bin_pos => $bin_pos
-    };
-    print "$i\t$bin_pos\t$counts\n" if $verbose;
-    print $file "$i\t$bin_pos\t$counts\n";
+    $spectrum->{data}->[$i] = [$thresh,$counts];
+    $self->{spectrum_shm}->updateShm({ $name => $spectrum }); #update spectrum
+    print "$i\t$thresh\t$counts\n" if $verbose;
+    print $file "$i\t$thresh\t$counts\n";
     
   }
   
@@ -183,6 +203,24 @@ sub spectral_scan_onesided {
   
 }
 
+sub spectrum_JSON {
+  my $self = shift;
+  
+  my $spectrum = $self->{spectrum_shm}->readShm();
+  print encode_json $spectrum;
+  return " ";
+
+}
+
+sub clear_spectrum {
+  my $self = shift;
+  
+  my $spectrum = {};
+  $self->{spectrum_shm}->writeShm($spectrum);
+  return "cleared";
+}
+
+
 sub signal_thresh {
   # reads or sets signal threshold
   my $self = shift;
index 191f5d1dbd33ebb84b93bc3b97d6b32ab2499df2..289475c434954679f15836126b0b7a6500d2f922 100644 (file)
@@ -16,8 +16,13 @@ sub new {
   };
   
   die "shm_manager must get an shmName" unless defined($self->{shmName});
-  
-  $self->{shmFile} = "/dev/shm/".$self->{shmName};
+  if(defined($self->{shmPath})){
+    $self->{shmPath} =~ s/\/+$//; #remove trailing "/"
+    $self->{shmPath} .= "/";
+    $self->{shmFile} = $self->{shmPath}.$self->{shmName};
+  } else {
+    $self->{shmFile} = "/dev/shm/".$self->{shmName};
+  }
 #   $self->{dataDir} = $self->{shmFile}."_data";
 #   $self->{dataFile} = $self->{dataDir}."/data";