var scan_meta;
var coral_scanner_settings;
var pmt_ro_settings;
-
+var spectrum;
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();
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({
signal_thresh();
});
+ $('#checkbox_log_spectrum').change(function(){
+// alert($(this).prop('checked'));
+ plot_spectrum();
+ });
$( "#progressbar" ).progressbar({
value: 100
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);
+
+}
+
+
}
-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({
});
}
+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",
}
});
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
{-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'},
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());
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'>";
$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();
}
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};
--- /dev/null
+/* 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);
}
}
+
+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
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
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
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
%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;
}
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;
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');
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";
}
}
+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;
};
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";