Files
sics/site_ansto/instrument/config/hmm/hmm_configuration_common_1.tcl
2015-02-19 09:40:49 +11:00

1951 lines
64 KiB
Tcl

# Author: Ferdi Franceschini
# Based on the examples in the hs_test.tcl sample configuration by Mark Lesha.
# http://gumtree.ansto.gov.au:9080/nbicms/bragg-systems/histogram-server/hs_test.tcl/view
##
# @file Provides generic code and parameters for configuring the ANSTO histogram memory server
# The instrument specific histogram memory configuration files must define an initialisation
# function with the following signature
# @code proc ::histogram_memory::initialize {}
# this function should call the generic initalisation function,
# ::histogram_memory::ic_initialize
#
#@see ::histogram_memory::ic_initialize
source $cfPath(hmm)/hmm_object.tcl
namespace eval histogram_memory {
# Common config variables
variable histmem_simulation
variable ic_count_methods
variable ic_fsrce_values
variable preset_mult
variable monitor_controlled
set monitor_controlled "false"
# Instrument Specific Config variables
set histmem_simulation [SplitReply [hmm_simulation]]
proc init_hmm_objs {} {
variable histmem_simulation
variable ic_count_methods
variable ic_fsrce_values
variable default_frame_source_when_there_is_no_frame_signal
variable default_frame_source_always_internal
if [ catch {
set ic_fsrce_values [ list INTERNAL EXTERNAL ]
set ic_count_methods [concat [list time unlimited period count frame count_roi] $::counter::isc_beam_monitor_list ]
if {$histmem_simulation == "true"} {
MakeHM hmm SIM
hmm configure daq Stopped
hmm configure statuscheck false
hmm configure num_events_filled_to_histo 12345
hmm configure daq_dirname "DAQ_2011-05-09T11-52-50"
hmm configure acq_dataset_active_sec 9.8
hmm configure acq_start_time_t 1303170800
hmm configure acq_stop_time_t 1303170818
hmm configure ratemap_xy_max_bin 123
hmm configure ratemap_xy_total 321
hmm configure maximum_period 0
hmm configure fat_frame_frequency 50
hmm configure fat_clock_scale 1000
foreach bm $::counter::isc_beam_monitor_list {
set bm_num [string index $bm end]
if [string is integer $bm_num] {
hmm configure bm${bm_num}_status DISABLED
hmm configure bm${bm_num}_counts 12345
hmm configure bm${bm_num}_event_rate 50
}
}
} else {
ANSTO_MakeHM hmm anstohttp
}
# Frame source for each instrument if freq = 0, this can happen when automatically
# setting frequencies from choppers.
array set default_frame_source_when_there_is_no_frame_signal {
echidna INTERNAL
koala INTERNAL
kowari EXTERNAL
pelican INTERNAL
platypus EXTERNAL
quokka INTERNAL
taipan INTERNAL
wombat INTERNAL
lyrebird INTERNAL
kookaburra INTERNAL
dingo INTERNAL
bilby INTERNAL
emu INTERNAL
}
array set default_frame_source_always_internal {
echidna "true"
koala "false"
kowari "false"
pelican "false"
platypus "false"
quokka "false"
taipan "false"
wombat "false"
lyrebird "false"
kookaburra "false"
dingo "false"
bilby "false"
emu "false"
}
::utility::mkVar detector_active_height_mm Float user active_height true detector true true
sicslist setatt detector_active_height_mm units mm
::utility::mkVar detector_active_width_mm Float user active_width true detector true true
sicslist setatt detector_active_width_mm units mm
::utility::mkVar hmm_user_configpath Text manager user_configpath false detector false false
hmm_user_configpath ../user_config/hmm
::utility::mkVar hmm_mode Text user mode true detector true true
::utility::mkVar hmm_preset Float user preset true detector true true
} message ] {
return -code error "([info level 0]) $message"
}
}
##############################################
# Creating the histogram memories in SICS
##############################################
# Make a histogram memory object hmm, allows control of the
# remote histogram server via http, and acquisition
# of histogram period data.
##############################################
# Configuring the histogram server
##############################################
# Procedure to read a single config (or any) file, return content as a string.
proc returnconfigfile {filename} {
if [ catch {
set fh [open $filename]
set xml [read $fh]
close $fh
set cfg [subst $xml]
} message ] {
return -code error "([info level 0]) $message"
}
return $cfg
}
# Here, define a function to let us read back the value of dictionary items from the hmm
# such as OAT dimensions.
proc hmmdictitemval {histomem dictitem} {
if [ catch {
set resp [$histomem configure $dictitem]
set retn [lindex [split $resp " "] 2]
} message ] {
return -code error "([info level 0]) $message"
}
return $retn
}
##
# @brief Use histogram server to control acquisitions
proc set_termination_conditions {count_method count_size count_stop} {
if [ catch {
hmm configure FAT_COUNT_METHOD $count_method
hmm configure FAT_COUNT_SIZE $count_size
hmm configure FAT_COUNT_STOP $count_stop
hmm init
} message ] {
return -code error "([info level 0]) $message"
}
}
##############################################
# Support for using expanded histogram period
# to create interlaced/overlapped histograms
##############################################
# Define an OAT offset variable to use with both scans:
# It is possible to effectively offset the histogram filler's
# OAT table by an arbitrary amount. For overlapped data acquisitions, we can
# configure an oversized histogram period using the EXPAND_OAT parameters
# in the FAT. Then at each scan stop, before acqisition commences the offset
# can be adjusted using the OFFSET_OAT paramters of the FAT. By progressively
# stepping the OFFSET_OAT, an overlapped image can be built up.
# The global variable oatoffset is defined for this purpose.
# During the scan, this variable is incremented and can be passed
# in to an argument of set_oat_offset to provide progressively
# increasing offset, producing an overlapped histogram.
#
global oatoffset
#
#Function to apply OAT offsets to the histogram server.
proc set_oat_offset {oatoff_x oatoff_y oatoff_t} {
if [ catch {
hmm configure FAT_OFFSET_OAT_X $oatoff_x
hmm configure FAT_OFFSET_OAT_Y $oatoff_y
hmm configure FAT_OFFSET_OAT_T $oatoff_t
hmm init
} message ] {
return -code error "([info level 0]) $message"
}
}
##############################################
# Support for data acquisition
##############################################
# A simple procedure to read the histogram data through SICS
# and dump the data to a numbered file.
proc savehistodata {histomem filename} {
set ::errorInfo ""
set fh [open $filename "w"]
# To get the whole memory, we don't need to specify the start or end arguments.
# But we need to specify the bank number, this sets the type of data to be read.
#
set histodata [$histomem get [hmmdictitemval $histomem bank]]
# clientput $histodata value
puts -nonewline $fh $histodata
close $fh
return
}
##############################################
##############################################
## Scan Callback Procedures ##
##############################################
##############################################
proc set_sobj_attributes {} {
if [ catch {
# SICS commands
# histogram memory macros
sicslist setatt ::histogram_memory::set_oat_offset privilege internal;
sicslist setatt ::histogram_memory::scan2_runb privilege internal;
sicslist setatt ::histogram_memory::scan2_runa privilege internal;
sicslist setatt ::histogram_memory::returnconfigfile privilege internal;
sicslist setatt ::histogram_memory::save privilege internal;
} message ] {
return -code error "([info level 0]) $message"
}
}
##
# @brief Returns the histogram memory server clock scale.
#
# NOTE: The histmem server doesn't provide the clock scale to SICS\n
# so we just hardwire 1000 nanoseconds which is the current (10/01/08)\n
# value on all the servers.
proc clock_scale {args} {
switch $args {
"" { return [expr [SplitReply [hmm configure fat_clock_scale]]/1000.0] }
"units" { return "microseconds"}
default {
return -code error "[info level 0]: Invalid argument $args"
}
}
}
proc get_clock_scale {} {
return [SplitReply [hmm configure fat_clock_scale]]
}
proc set_clock_scale {val} {
set catch_status [ catch {
if {[string is integer $val] == 0} {
error "ERROR: clock scale should be an integer. NOTE: The clock base is in nanoseconds"
}
hmm configure fat_clock_scale $val
::histogram_memory::stop
hmm init
} message ]
handle_exception $catch_status $message
}
## @brief Use boundaries or centres to calculate axis values
#
# @param axis_name x_bin, y_bin, x_pixel_offset, y_pixel_offset, two_theta
# @param type centres or boundaries
proc set_graphtype {axis_name type} {
variable state
switch -- $type {
"centres" {
set state($axis_name,graph_type) "centres"
}
"boundaries" {
set state($axis_name,graph_type) "boundaries"
}
default {
error "ERROR: Unknown graph type $type"
}
}
}
proc get_graphtype {axis_name} {
variable state
return $state($axis_name,graph_type)
}
## @brief Calculate axis array from a given list of bin boundaries
# Generates a sicsdata array
#
# @param axis_name Fully qualified name of the calling procedure
# @param scale_factor axis scale factor or @none
# @param offset axis offset or @none
# @param boundaries list of bin boundaries or @none
proc calc_axis {axis_name scale_factor offset boundaries {bb_zero_offset 0}} {
variable state
set bin_array ::histogram_memory::${axis_name}_array
if [ catch {
set i 0
$bin_array clear
if {$state($axis_name,graph_type) == "boundaries"} {
foreach bb $boundaries {
set val [expr {$scale_factor*($bb+$bb_zero_offset) + $offset}]
$bin_array putfloat $i $val
incr i
}
} else {
foreach b0 [lrange $boundaries 0 end-1] b1 [lrange $boundaries 1 end] {
set val [expr {$scale_factor*($bb_zero_offset + ($b1 + $b0)/2.0) + $offset}]
$bin_array putfloat $i $val
incr i
}
}
} message ] {
return -code error "([info level 0]) $message"
}
}
sicsdatafactory new ::histogram_memory::y_bin_array
##
# @brief Provides y_bin boundary array for data axes
proc y_bin {args} {
if [ catch {
::histogram_memory::calc_axis "y_bin" 1.0 0.0 [OAT_TABLE Y -getdata BOUNDARIES]
if {$args == "-get_data_ref"} {
set binarray "::histogram_memory::y_bin_array"
} else {
set binarray [::histogram_memory::y_bin_array used]
}
} message ] {
return -code error "([info level 0]) $message"
}
return $binarray
}
set script_name ::histogram_memory::y_bin
publish $script_name user
sicslist setatt $script_name privilege user
sicslist setatt $script_name kind script
sicslist setatt $script_name access read_only
sicslist setatt $script_name dtype floatvarar
sicslist setatt $script_name dlen 100
sicslist setatt $script_name klass detector
sicslist setatt $script_name control false
sicslist setatt $script_name data true
sicslist setatt $script_name nxsave true
sicslist setatt $script_name mutable false
sicslist setatt $script_name long_name y_bin
unset script_name
sicsdatafactory new ::histogram_memory::x_bin_array
##
# @brief Provides x_bin boundary array for data axes
proc x_bin {args} {
if [ catch {
::histogram_memory::calc_axis "x_bin" 1.0 0.0 [OAT_TABLE X -getdata BOUNDARIES]
if {$args == "-get_data_ref"} {
set binarray "::histogram_memory::x_bin_array"
} else {
set binarray [::histogram_memory::x_bin_array used]
}
} message ] {
return -code error "([info level 0]) $message"
}
return $binarray
}
set script_name ::histogram_memory::x_bin
publish $script_name user
sicslist setatt $script_name privilege user
sicslist setatt $script_name kind script
sicslist setatt $script_name access read_only
sicslist setatt $script_name dtype floatvarar
sicslist setatt $script_name dlen 100
sicslist setatt $script_name klass detector
sicslist setatt $script_name control false
sicslist setatt $script_name data true
sicslist setatt $script_name nxsave true
sicslist setatt $script_name mutable false
sicslist setatt $script_name long_name x_bin
unset script_name
# requires detector_active_width_mm det_radius_mm
sicsdatafactory new ::histogram_memory::y_pixel_offset_array
proc y_pixel_offset {args} {
variable state
if [ catch {
set det_height_mm [SplitReply [detector_active_height_mm]]
set max_chan [OAT_TABLE Y -getdata MAX_CHAN]
set scale_factor [expr {1.0 * $det_height_mm / $max_chan}]
set offset 0.0
::histogram_memory::calc_axis "y_pixel_offset" $scale_factor $offset [OAT_TABLE Y -getdata BOUNDARIES]
if {$args == "-get_data_ref"} {
set binarray "::histogram_memory::y_pixel_offset_array"
} else {
set binarray [::histogram_memory::y_pixel_offset_array used]
}
} message ] {
return -code error "([info level 0]) $message"
}
return $binarray
}
set script_name ::histogram_memory::y_pixel_offset
publish $script_name user
sicslist setatt $script_name privilege user
sicslist setatt $script_name kind script
sicslist setatt $script_name access read_only
sicslist setatt $script_name dtype floatvarar
sicslist setatt $script_name dlen 100
sicslist setatt $script_name klass detector
sicslist setatt $script_name control false
sicslist setatt $script_name data true
sicslist setatt $script_name nxsave true
sicslist setatt $script_name mutable false
sicslist setatt $script_name long_name y_pixel_offset
sicslist setatt $script_name units "mm"
unset script_name
# requires detector_active_width_mm det_radius_mm
sicsdatafactory new ::histogram_memory::x_pixel_offset_array
proc x_pixel_offset {args} {
variable state
if [ catch {
set det_width_mm [SplitReply [detector_active_width_mm]]
set max_chan [OAT_TABLE X -getdata MAX_CHAN]
set scale_factor [expr {1.0 * $det_width_mm / $max_chan}]
set offset 0.0
::histogram_memory::calc_axis "x_pixel_offset" $scale_factor $offset [OAT_TABLE X -getdata BOUNDARIES]
if {$args == "-get_data_ref"} {
set binarray "::histogram_memory::x_pixel_offset_array"
} else {
set binarray [::histogram_memory::x_pixel_offset_array used]
}
} message ] {
return -code error "([info level 0]) $message"
}
return $binarray
}
set script_name ::histogram_memory::x_pixel_offset
publish $script_name user
sicslist setatt $script_name privilege user
sicslist setatt $script_name kind script
sicslist setatt $script_name access read_only
sicslist setatt $script_name dtype floatvarar
sicslist setatt $script_name dlen 100
sicslist setatt $script_name klass detector
sicslist setatt $script_name control false
sicslist setatt $script_name data true
sicslist setatt $script_name nxsave true
sicslist setatt $script_name mutable false
sicslist setatt $script_name long_name x_pixel_offset
sicslist setatt $script_name units "mm"
unset script_name
sicsdatafactory new ::histogram_memory::time_channel_array
proc time_channel {args} {
variable state
if [ catch {
::histogram_memory::calc_axis "time_channel" [::histogram_memory::clock_scale] 0.0 [OAT_TABLE T -getdata BOUNDARIES]
if {$args == "-get_data_ref"} {
set binarray "::histogram_memory::time_channel_array"
} else {
set binarray [::histogram_memory::time_channel_array used]
}
} message ] {
return -code error "([info level 0]) $message"
}
return $binarray
}
set script_name ::histogram_memory::time_channel
publish $script_name user
sicslist setatt $script_name privilege user
sicslist setatt $script_name kind script
sicslist setatt $script_name access read_only
sicslist setatt $script_name dtype floatvarar
sicslist setatt $script_name dlen 100
sicslist setatt $script_name klass detector
sicslist setatt $script_name control false
sicslist setatt $script_name data true
sicslist setatt $script_name nxsave true
sicslist setatt $script_name mutable false
sicslist setatt $script_name long_name time_of_flight
sicslist setatt $script_name units [::histogram_memory::clock_scale units]
unset script_name
}
#################################
# Must always specify number of channels
# bb list len <= channels+1
# Calculate the boundaries after successfully uploading a configuration.
# set values [OAT_TABLE -get X]
# set channels [OAT_TABLE -get NXC]
# OAT_TABLE X -setdata BOUNDARIES [calc_boundaries $values $channels]
proc ::histogram_memory::calc_boundaries {values channels} {
if [ catch {
set bbnum [llength $values]
set maxbblen [expr $channels+1]
set maxchan [expr $channels - 1]
if {$bbnum > $maxbblen} {
error "ERROR: The number of bin boundaries must be less than or equal to $maxbblen"
}
set BOUNDARIES ""
if {$bbnum > 2} {
set BOUNDARIES $values
} elseif {$bbnum == 2} {
foreach {leftbb rightbb} $values {}
set bstep [expr {$rightbb-$leftbb}]
if {$bstep == 0} {
error "ERROR: The generating bin boundaries are equal"
}
set startbin [expr ($leftbb+$rightbb)/2.0]
# FIXME This check doesn't work for time, T
# if {$startbin < 0.0 || $startbin > $maxchan} {
# error "ERROR: $leftbb and $rightbb must bound a channel >= 0 or <= $maxchan"
# }
for {set bb $leftbb; set i 0} {$i < $maxbblen} {incr i; set bb [expr {$bb + $bstep}]} {
lappend BOUNDARIES $bb
}
} else {
error "ERROR: You must specify at least two bin boundaries"
}
} message ] {
return -code error $message
}
return $BOUNDARIES
}
set hmm_xml ""
##
# @brief Provides a standard set of subcommands for the histogram server table
# configuration commands.
#
# @param tag Table identifier, one of BAT CAT FAT NAT OAT SAT SRV
# @param attributes Defines the list of attributes which you will be allowed to set.
# @param element_list Defines the list of elements which you will be allowed to set.
# Use "" if your table doesn't contain any elements.
# @param args This can be empty, or a list of name value pairs for the attributes
# and elements which you want to set or one of the subcommands listed below.
# If args is empty this function will simply return an xml fragment for the named table,
#
# Subcommands\n
# -clear clears the table\n
# -init A list of name value pairs. If you use attribute or element names then
# the corresponding table entries will be initilised to the given values, any
# attributes or elements which aren't specified will be cleared. You can also
# specify extra parameters to store in the table which might be required to
# specify limits or constants which may be necessary for deriving configuration
# parameters.\n
# -get return the value for the named attribute or element\n
# -attlist list all of the attributes with their values.\n
# TODO Maintain "proposed" and "current" tables. Provide a setcurrent command which can
# only be called by the upload_config command to set the proposed tables as current
# TODO Allow for top level content in tables and attributes in sub-elements
proc HISTMEM_TABLE {tpath args} {
global hmm_xml
if [ catch {
set retVal ""
set tpath [string toupper $tpath]
foreach {opt arglist} [::utility::get_opt_arglist $args] {}
switch -- $opt {
"-dump" {
foreach {k v} $hmm_xml {clientput $k; foreach {name val} $v {clientput "$name: $val"}}
}
"-allowed_attributes" {
if {[llength $arglist] == 0} {
set retVal [::utility::tabget hmm_xml $tpath/_ALLOWED_ATTRIBUTES_]
} else {
::utility::tabset hmm_xml $tpath/_ALLOWED_ATTRIBUTES_ [lindex $arglist 0]
}
}
"-allowed_elements" {
if {[llength $arglist] == 0} {
set retVal [::utility::tabget hmm_xml $tpath/_ALLOWED_ELEMENTS_]
} else {
::utility::tabset hmm_xml $tpath/_ALLOWED_ELEMENTS_ [lindex $arglist 0]
::utility::tabset hmm_xml $tpath/_ELEMENTS_ [lindex $arglist 0]
}
}
"-setel" {
set element [lindex $arglist 0]
set value [lindex $arglist 1]
if {[lsearch [::utility::tabget hmm_xml $tpath/_ALLOWED_ELEMENTS_] $element] >= 0} {
::utility::tabset hmm_xml $tpath/$element/_CONTENT_ $value
} else {
error "ERROR: $element is not an allowed element in $tpath"
}
}
"-setatt" {
set attname [lindex $arglist 0]
set value [lindex $arglist 1]
if {[lsearch [::utility::tabget hmm_xml $tpath/_ALLOWED_ATTRIBUTES_] $attname] >= 0} {
::utility::tabset hmm_xml $tpath/_ATTLIST_/$attname $value
} else {
error "ERROR: $attname is not an allowed attribute in $tpath"
}
}
"-getel" {
set element [lindex $arglist 0]
set retVal [::utility::tabget hmm_xml $tpath/$element/_CONTENT_]
}
"-getatt" {
set attribute [lindex $arglist 0]
set retVal [::utility::tabget hmm_xml $tpath/_ATTLIST_/$attribute]
}
"-delel" {
set element [lindex $arglist 0]
::utility::tabdel hmm_xml $tpath/$element
}
"-delatt" {
set attribute [lindex $arglist 0]
::utility::tabdel hmm_xml $tpath/_ATTLIST_/$attribute
}
"-clear" {
::utility::tabdel hmm_xml $tpath/_ATTLIST_
::utility::tabdel hmm_xml $tpath/_CONTENT_
foreach element [::utility::tabget hmm_xml $tpath/_ELEMENTS_] {
::utility::tabdel hmm_xml $tpath/$element
}
}
"-setdata" {
if {[llength $arglist] == 1} {
set arglist [lindex $arglist 0]
}
foreach {name value} $arglist {
if {$value == ""} {
error "ERROR: No value supplied when setting $name at $tpath in the histogram memory table"
}
::utility::tabset hmm_xml $tpath/_DATA_/$name $value
}
}
"-getdata" {
if {[llength $arglist] == 1} {
set arglist [lindex $arglist 0]
}
if {[llength $arglist] <= 1} {
set retVal [::utility::tabget hmm_xml $tpath/_DATA_/$arglist]
} else {
foreach name $arglist {
lappend values [::utility::tabget hmm_xml $tpath/_DATA_/$name]
}
set retVal $values
}
}
"-getxml" {
set retVal [::utility::tabxml hmm_xml $tpath]
}
}
} message ] {
return -code error "([info level 0]) $message"
} else {
return $retVal
}
}
##
# @brief Base Address Table configuration parameters as maintained by SICS
#
proc BAT_TABLE {args} {
if [ catch {
set attributes { NO_BAT_ENTRIES NO_BAT_PERIODS NO_REPEAT_ENTRY NO_REPEAT_TABLE NO_EXECUTE_TABLE }
set elements {{PERIOD_INDICES }}
set tag BAT
foreach {opt arglist} [::utility::get_opt_arglist $args] {}
switch -- $opt {
"" {
return [HISTMEM_TABLE $tag -getxml]
}
"-init" {
HISTMEM_TABLE $tag -allowed_elements $elements
HISTMEM_TABLE $tag -allowed_attributes [concat $attributes $arglist]
}
"-set" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach {arg val} $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setel $arg $val
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setatt $attname $val
}
}
}
}
"-get" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach arg $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getel $arg]
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getatt $attname]
}
}
}
if {[llength $values] == 1} {
return [lindex $values 0]
} else {
return $values
}
}
"-del" {
foreach att [lindex $attributes 0] el [lindex $elements 0] {
set index [lsearch -exact $arglist $el]
if {$index >= 0} {
HISTMEM_TABLE $tag -delel $el
}
set index [lsearch -exact $arglist $att]
if {$index >= 0} {
HISTMEM_TABLE $tag -delatt $att
}
}
}
"-setdata" {
HISTMEM_TABLE $tag -setdata $arglist
}
"-getdata" {
return [HISTMEM_TABLE $tag -getdata $arglist]
}
"-clear" {
HISTMEM_TABLE $tag -clear
}
default {
error "ERROR: Unknown subcommand $opt"
}
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
##
# @brief CAlibration Table configuration parameters as maintained by SICS
#
proc CAT_TABLE {args} {
if [ catch {
set attributes { FRAME_FREQUENCY SIZE_PERIOD COUNT_METHOD COUNT_SIZE READ_DATA_TYPE }
set elements {{MESYTEC_MPSD8_CHANNEL_GAINS MESYTEC_MPSD8_THRESHOLDS MESYTEC_TUBE_PAIR_RESISTANCE_RATIOS MESYTEC_TUBE_MAGNIFICATIONS MESYTEC_TUBE_OFFSETS MESYTEC_TUBE_HISTOGRAM_WEIGHTS }}
set tag CAT
foreach {opt arglist} [::utility::get_opt_arglist $args] {}
switch -- $opt {
"" {
return [HISTMEM_TABLE $tag -getxml]
}
"-init" {
HISTMEM_TABLE $tag -allowed_elements $elements
HISTMEM_TABLE $tag -allowed_attributes [concat $attributes $arglist]
}
"-set" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach {arg val} $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setel $arg $val
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setatt $attname $val
}
}
}
}
"-get" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach arg $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getel $arg]
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getatt $attname]
}
}
}
if {[llength $values] == 1} {
return [lindex $values 0]
} else {
return $values
}
}
"-del" {
foreach att [lindex $attributes 0] el [lindex $elements 0] {
set index [lsearch -exact $arglist $el]
if {$index >= 0} {
HISTMEM_TABLE $tag -delel $el
}
set index [lsearch -exact $arglist $att]
if {$index >= 0} {
HISTMEM_TABLE $tag -delatt $att
}
}
}
"-setdata" {
HISTMEM_TABLE $tag -setdata $arglist
}
"-getdata" {
return [HISTMEM_TABLE $tag -getdata $arglist]
}
"-clear" {
HISTMEM_TABLE $tag -clear
}
default {
error "ERROR: Unknown subcommand $opt"
}
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
##
# @brief Frequency Address Table configuration parameters as maintained by SICS
#
proc FAT_TABLE {args} {
if [ catch {
set attributes { FRAME_FREQUENCY FRAME_BUFFER FRAME_DUTYCYCLE SIZE_PERIOD NOS_PERIODS COUNT_METHOD COUNT_SIZE READ_DATA_TYPE VIEW_MAG_X VIEW_MAG_Y HISTO_STREAMING P7888_PLL_FREQ_CARD_X P7888_PLL_FREQ_CARD_Y P7888_CARD_MODE_X P7888_CARD_MODE_Y RAW_HISTO_XMIN RAW_HISTO_XMAX RAW_HISTO_YMIN RAW_HISTO_YMAX TEST_HISTO_1D_SIZES TEST_HISTO_2D_SIZES P7888_PLL_SYNC_METHOD COUNT_ROI_XMIN COUNT_ROI_XMAX COUNT_ROI_YMIN COUNT_ROI_YMAX COUNT_ROI_TMIN COUNT_ROI_TMAX COUNT_ROI_TYPE COUNT_ROI_REGION COUNT_ROI_K1 }
set elements {{ }}
set tag FAT
foreach {opt arglist} [::utility::get_opt_arglist $args] {}
switch -- $opt {
"" {
return [HISTMEM_TABLE $tag -getxml]
}
"-init" {
HISTMEM_TABLE $tag -allowed_elements $elements
HISTMEM_TABLE $tag -allowed_attributes [concat $attributes $arglist]
}
"-set" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach {arg val} $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setel $arg $val
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setatt $attname $val
}
}
}
}
"-get" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach arg $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getel $arg]
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getatt $attname]
}
}
}
if {[llength $values] == 1} {
return [lindex $values 0]
} else {
return $values
}
}
"-del" {
foreach att [lindex $attributes 0] el [lindex $elements 0] {
set index [lsearch -exact $arglist $el]
if {$index >= 0} {
HISTMEM_TABLE $tag -delel $el
}
set index [lsearch -exact $arglist $att]
if {$index >= 0} {
HISTMEM_TABLE $tag -delatt $att
}
}
}
"-setdata" {
HISTMEM_TABLE $tag -setdata $arglist
}
"-getdata" {
return [HISTMEM_TABLE $tag -getdata $arglist]
}
"-clear" {
HISTMEM_TABLE $tag -clear
}
default {
error "ERROR: Unknown subcommand $opt"
}
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
##
# @brief Offset Address Table configuration parameters as maintained by SICS
#
# @param -clear clears OAT_TABLE XML fragment
# @param -init X_MIN <x0> X_MAX <x1> Y_MIN <y0> Y_MAX <y1>
# Initialise minimum and maximum bin boundaries.
# @param -get
# @param -attlist
# @param -clear clears the oat table and the fat table SIZE_PERIOD
#
# Sets X_BOUNDARIES, Y_BOUNDARIES and T_BOUNDARIES
proc OAT_TABLE {args} {
if [ catch {
array set attlookup {NXC NO_OAT_X_CHANNELS NYC NO_OAT_Y_CHANNELS NTC NO_OAT_T_CHANNELS}
set elements {{ X Y T }}
set tag OAT
set element [lindex $args 0]
if {[ lsearch [lindex $elements 0] $element] == -1} {
unset element
} else {
set tag $tag/$element
set args [lrange $args 1 end]
}
foreach {opt arglist} [::utility::get_opt_arglist $args] {}
switch -- $opt {
"" {
return [HISTMEM_TABLE $tag -getxml]
}
"-init" {
HISTMEM_TABLE $tag -allowed_elements $elements
foreach {n v} [array get attlookup] {
lappend attributes $v
}
HISTMEM_TABLE $tag -allowed_attributes [concat $attributes $arglist]
}
"-set" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach {arg val} $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setel $arg $val
} else {
if [info exists attlookup($arg)] {
set attname $attlookup($arg)
} else {
set attname $arg
}
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setatt $attname $val
}
}
}
foreach {nxc nyc} [OAT_TABLE -get NXC NYC] {}
set max_nxc [::histogram_memory::max_chan_num X]
set max_nyc [::histogram_memory::max_chan_num Y]
if {$nxc > $max_nxc} {
gumput "WARNING: Reducing NO_OAT_X_CHANNELS from $nxc to maximum $max_nxc" warning
OAT_TABLE -set NXC $max_nxc
}
if {$nyc > $max_nyc} {
gumput "WARNING: Reducing NO_OAT_Y_CHANNELS from $nyc to maximum $max_nyc" warning
OAT_TABLE -set NYC $max_nyc
}
foreach axis {X Y T} {
set bins [::histogram_memory::oat_bins $axis]
set nch [::histogram_memory::number_of_channels $axis]
OAT_TABLE $axis -setdata BOUNDARIES [::histogram_memory::calc_boundaries $bins $nch]
}
}
"-get" {
set allowed_atts [HISTMEM_TABLE $tag -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach arg $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getel $arg]
} else {
if [info exists attlookup($arg)] {
set attname $attlookup($arg)
} else {
set attname $arg
}
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getatt $attname]
}
}
}
if {[llength $values] == 1} {
return [lindex $values 0]
} else {
return $values
}
}
"-del" {
foreach att [array names attlookup] el [lindex $elements 0] {
set index [lsearch -exact $arglist $el]
if {$index >= 0} {
HISTMEM_TABLE $tag -delel $el
}
set index [lsearch -exact $arglist $att]
if {$index >= 0} {
HISTMEM_TABLE $tag -delatt $attlookup($att)
}
}
}
"-setdata" {
HISTMEM_TABLE $tag -setdata $arglist
}
"-getdata" {
return [HISTMEM_TABLE $tag -getdata $arglist]
}
"-clear" {
HISTMEM_TABLE $tag -clear
}
default {
error "ERROR: Unknown subcommand $opt"
}
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
# @brief Spatial Allocation Table configuration parameters as maintained by SICS
#
# Only one element, ie SPLIT with no content just attributes.
proc SAT_TABLE {args} {
if [ catch {
set attributes { APPLY MIDPOINT DIRECTION WRAP SWAP}
set elements {{ SPLIT }}
set tag SAT
set attpath SAT/SPLIT
foreach {opt arglist} [::utility::get_opt_arglist $args] {}
switch -- $opt {
"" {
return [HISTMEM_TABLE $tag -getxml]
}
"-init" {
HISTMEM_TABLE $tag -allowed_elements $elements
HISTMEM_TABLE $attpath -allowed_attributes [concat $attributes $arglist]
}
"-set" {
set allowed_atts [HISTMEM_TABLE $attpath -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach {arg val} $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
incr index
HISTMEM_TABLE $tag -setel $arg $val
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
incr index
HISTMEM_TABLE $attpath -setatt $attname $val
}
}
}
}
"-get" {
set allowed_atts [HISTMEM_TABLE $attpath -allowed_attributes]
set allowed_els [HISTMEM_TABLE $tag -allowed_elements]
foreach arg $arglist {
set index [lsearch -exact $allowed_els $arg]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getel $arg]
} else {
set attname $arg
set index [lsearch -exact $allowed_atts $attname]
if {$index >= 0} {
lappend values [HISTMEM_TABLE $tag -getatt $attname]
}
}
}
if {[llength $values] == 1} {
return [lindex $values 0]
} else {
return $values
}
}
"-del" {
foreach att $attributes {
set index [lsearch -exact $arglist $att]
if {$index >= 0} {
HISTMEM_TABLE $attpath -delatt $att
}
}
}
"-setdata" {
HISTMEM_TABLE $tag -setdata $arglist
}
"-getdata" {
return [HISTMEM_TABLE $tag -getdata $arglist]
}
"-clear" {
HISTMEM_TABLE $tag -clear
HISTMEM_TABLE $attpath -allowed_attributes $attributes
}
default {
error "ERROR: Unknown subcommand $opt"
}
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
proc ::histogram_memory::pre_count {} {}
proc ::histogram_memory::post_count {} {}
##
# @brief Resolve dependencies between the histogram memory tables
proc ::histogram_memory::synch_tables {} {
if [ catch {
set noxch [OAT_TABLE -get NXC]
set noych [OAT_TABLE -get NYC]
set notch [OAT_TABLE -get NTC]
FAT_TABLE -set SIZE_PERIOD [expr $noxch*$noych*$notch]
} message ] {
return -code error "([info level 0]) $message"
}
}
proc ::histogram_memory::clear_tables {} {
if [ catch {
set ::errorInfo ""
BAT_TABLE -clear
CAT_TABLE -clear
FAT_TABLE -clear
OAT_TABLE -clear
SAT_TABLE -clear
} message ] {
return -code error "([info level 0]) $message"
}
}
##
# @brief Calculate the maximum number of oat channels from the generating bin
# boundaries of the given axis
proc ::histogram_memory::max_chan_num {axis} {
if [ catch {
set bins [OAT_TABLE -get $axis]
set numb_bins [llength $bins]
if {$numb_bins < 2} {
error "ERROR: $axis must have at least two bin boundaries"
} elseif {$numb_bins > 2} {
return $numb_bins
} else {
foreach {leftbb rightbb} $bins {}
set bstep [expr $rightbb - $leftbb]
if {$bstep == 0} {
error "ERROR: Bin boundaries for $axis must not be equal"
} elseif {$bstep < 0} {
set binlim [OAT_TABLE $axis -getdata BMIN]
} else {
set binlim [OAT_TABLE $axis -getdata BMAX]
}
}
set numb_bins [expr {int(floor(($binlim - $leftbb)/$bstep))}]
return $numb_bins
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
##
# @brief When called without arguments this returns the name of the filler defaults file
# for the histogram server. When called with an argument it sets the current name of the
# filler defaults file.
#
# When anstohm_linked.xml is uploaded to the histogram server it calls this via
# command substitution to set the name of the filler defaults file.
proc ::histogram_memory::filler_defaults {args} {
variable hmm_def_filename
if [ catch {
if {[llength $args] > 0} {
set hmm_def_filename $args
}
} message ] {
return -code error "([info level 0]) $message"
}
return $hmm_def_filename
}
##
# @brief Returns the oat table bin boundaries.
# This function can be replaced with an instrument specific definition
# in the instrumenent specific configuration file.
proc ::histogram_memory::oat_bins {axis} {
if [ catch {
set bins [OAT_TABLE -get $axis]
} message ] {
return -code error "([info level 0]) $message"
}
return $bins
}
##
# @brief Returns the current number of channels for a given axis.
# This function can be replaced with an instrument specific definition
# in the instrumenent specific configuration file.
proc ::histogram_memory::number_of_channels {axis} {
array set channID {X NXC Y NYC T NTC}
if [ catch {
set nchans [OAT_TABLE -get $channID($axis)]
} message ] {
return -code error "([info level 0]) $message"
}
return $nchans
}
# TODO Set current oat table after uploading proposed oat_table
proc ::histogram_memory::upload_config {filler_defaults} {
if [ catch {
::histogram_memory::synch_tables
::histogram_memory::filler_defaults $filler_defaults
hmm astop
wait 5
hmm configure init 1
hmm init
# Restore the init level to 0
# subesquent inits will only upload specified FAT settings to histogram server.
hmm configure init 0
hmm init
# Now issue stop to the server.
# This not only makes sure it's stopped, but lets us see certain configuration variables
# which get placed in the dictionary as part of the status checking done during the stop.
hmm configure statuscheck true
hmm astop
hmm configure statuscheck false
# ::histogram_memory::configure_dims
# foreach axis {X Y T} {
# set bins [oat_bins $axis]
# set nch [number_of_channels $axis]
# OAT_TABLE $axis -setdata BOUNDARIES [calc_boundaries $bins $nch]
# }
clientput "histmem configuration uploaded"
} message ] {
if {$::errorCode=="NONE"} {
return $message
} else {
return -code error "([info level 0]) $message"
}
}
}
##
# @brief If set to true then the frame_source will always be set to INTERNAL.
#
# @see ::histogram_memory::set_frame_source
proc ::histogram_memory::frame_source_always_internal {args} {
variable fs_always_internal
if [ catch {
if {$args == ""} {
return $fs_always_internal
}
set flag [lindex $args 0]
if {[string is boolean $flag] == 0} {
error "ERROR: $args must be a boolean"
} else {
set fs_always_internal $flag
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
publish ::histogram_memory::frame_source_always_internal mugger
##
# @brief Return the last frame source which SICS attempted to set
proc ::histogram_memory::get_frame_source {} {
if [ catch {
if [::histogram_memory::frame_source_always_internal] {
clientput "WARNING: The frame source is set to always_internal" value
clientput "Use ::histogram_memory::frame_source_always_internal <true/false> to change this." value
return INTERNAL
} else {
return [SplitReply [hmm configure fat_frame_source]]
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
##
# @brief Sets the histogram memory frame source to the given value.
#
# @param srce EXTERNAL or INTERNAL
# @param always_internal true or false (optional) (default false)
proc ::histogram_memory::set_frame_source {srce} {
variable ic_fsrce_values
if [ catch {
if {[lsearch $ic_fsrce_values $srce] == -1} {
error "ERROR: $srce is invalid, valid values are \"$ic_fsrce_values\""
}
if [::histogram_memory::frame_source_always_internal] {
clientput "WARNING: The frame source is set to always_internal" value
clientput "Use ::histogram_memory::frame_source_always_internal <true/false> to change this." value
hmm configure fat_frame_source INTERNAL
} else {
hmm configure fat_frame_source $srce
}
::histogram_memory::stop
hmm init
} message ] {
return -code error "([info level 0]) $message"
}
}
##
# @brief Return the last frame frequency which SICS attempted to set
proc ::histogram_memory::get_frame_freq {} {
if [ catch {
set frameFreq [SplitReply [hmm configure fat_frame_frequency]]
} message ] {
return -code error "([info level 0]) $message"
}
return $frameFreq
}
##
# @brief Sets the histogram memory frame frequency to the given value.
#
# @param freq Frequency in Hz.\n
# @param frame_source INTERNAL or EXTERNAL(default)
#
# If freq=0 then it sets the frequency to 50Hz with an internal frame source. This is useful
# if you are setting the frequency from a chopper which is stopped.
proc ::histogram_memory::set_frame_freq {freq {frame_source EXTERNAL}} {
variable state
variable default_frame_source_when_there_is_no_frame_signal
if [ catch {
if {[string is double $freq] == 0 || $freq < 0} {
error "ERROR: Frequency must be a non-negative floating point number"
}
#TODO Add tolerance parameters to choppercontroller
if {abs($freq - 0) <= [expr {2.0/60.0}]} {
set zf_frame_source $default_frame_source_when_there_is_no_frame_signal([instname])
if {$zf_frame_source == "INTERNAL"} {
clientput "WARNING: A histmem frame frequency of zero was requested, setting frequency to 50Hz instead" value
} else {
clientput "WARNING: A histmem frame frequency of zero was requested, setting frequency to 50Hz instead" value
clientput "WARNING: You must provide an external oscillator" value
}
::histogram_memory::set_frame_source $zf_frame_source
set newfreq 50
} else {
::histogram_memory::set_frame_source [string toupper $frame_source]
::set newfreq $freq
}
::histogram_memory::stop
hmm configure fat_frame_frequency $newfreq
hmm init
} message ] {
return -code error "([info level 0]) $message"
}
}
publish ::histogram_memory::set_frame_freq user
proc ::histogram_memory::t_max {} {
if [ catch {
set frame_freq [SplitReply [hmm configure fat_frame_frequency]]
} message ] {
return -code error "([info level 0]) $message"
}
}
##
# @brief Total counts in histogram defined by the OAT table.
::utility::macro::getset int ::histogram_memory::total_counts {} {
return "total_counts = [SplitReply [hmm configure num_events_filled_to_histo]]"
}
sicslist setatt ::histogram_memory::total_counts klass detector
sicslist setatt ::histogram_memory::total_counts long_name total_counts
sicslist setatt ::histogram_memory::total_counts mutable true
sicslist setatt ::histogram_memory::total_counts units count
sicslist setatt ::histogram_memory::total_counts link data_set
##
# @brief Histogram memory dataset directory
::utility::macro::getset text ::histogram_memory::daq_dirname {} {
return "daq_dirname = [SplitReply [hmm configure daq_dirname]]"
}
sicslist setatt ::histogram_memory::daq_dirname klass detector
sicslist setatt ::histogram_memory::daq_dirname long_name daq_dirname
sicslist setatt ::histogram_memory::daq_dirname mutable false
##
# @brief Histogram memory acquisition time
::utility::macro::getset float ::histogram_memory::time {} {
return "time = [SplitReply [hmm configure acq_dataset_active_sec]]"
}
sicslist setatt ::histogram_memory::time klass detector
sicslist setatt ::histogram_memory::time long_name time
sicslist setatt ::histogram_memory::time mutable true
sicslist setatt ::histogram_memory::time units seconds
##
# @brief Histogram memory acquisition start_time
::utility::macro::getset int ::histogram_memory::start_time {} {
set start_time_sec [SplitReply [hmm configure acq_start_time_t]]
# set start_time [clock format $start_time_sec -format "%G-%m-%d %T"]
return "start_time = $start_time_sec"
}
sicslist setatt ::histogram_memory::start_time klass detector
sicslist setatt ::histogram_memory::start_time long_name start_time
sicslist setatt ::histogram_memory::start_time mutable true
sicslist setatt ::histogram_memory::start_time units seconds
##
# @brief Histogram memory acquisition stop_time
::utility::macro::getset int ::histogram_memory::stop_time {} {
set stop_time_sec [SplitReply [hmm configure acq_stop_time_t]]
# set stop_time [clock format $stop_time_sec -format "%G-%m-%d %T"]
return "stop_time = $stop_time_sec"
}
sicslist setatt ::histogram_memory::stop_time klass detector
sicslist setatt ::histogram_memory::stop_time long_name stop_time
sicslist setatt ::histogram_memory::stop_time mutable true
sicslist setatt ::histogram_memory::stop_time units seconds
::utility::macro::getset float ::histogram_memory::ratemap_xy_max_bin {} {
return "ratemap_xy_max_bin = [lindex [hmm configure ratemap_xy_max_bin] 2]"
}
sicslist setatt ::histogram_memory::ratemap_xy_max_bin klass detector
sicslist setatt ::histogram_memory::ratemap_xy_max_bin long_name max_binrate
sicslist setatt ::histogram_memory::ratemap_xy_max_bin mutable true
::utility::macro::getset float ::histogram_memory::ratemap_xy_total {} {
return "ratemap_xy_total = [lindex [hmm configure ratemap_xy_total] 2]"
}
sicslist setatt ::histogram_memory::ratemap_xy_total klass detector
sicslist setatt ::histogram_memory::ratemap_xy_total long_name total_maprate
sicslist setatt ::histogram_memory::ratemap_xy_total mutable true
# Returns 0 If all trips acknowledged, -n if n trips unacknowledged, +n if too many acks?
::utility::macro::getset float ::histogram_memory::reset_trip {args} {
set num_trips [ SplitReply [hmm configure detector_protect_num_trip] ]
set num_acks [ SplitReply [hmm configure detector_protect_num_trip_ack] ]
set trip_cnt_diff [expr {$num_acks - $num_trips}]
if {$args == ""} {
return "reset_trip = $trip_cnt_diff"
} else {
if {$trip_cnt_diff != 0} {
hmm configure fat_detector_protect_num_trip_ack $num_trips
hmm astop
wait 2
hmm init
}
}
}
sicslist setatt ::histogram_memory::reset_trip klass detector
sicslist setatt ::histogram_memory::reset_trip long_name reset_trip
sicslist setatt ::histogram_memory::reset_trip data false
##
# @brief Update the beam monitors when the histmem has finished counting.
proc ::histogram_memory::countend_event {} {
::histogram_memory::post_count
::histogram::histmem_cmd -set feedback status IDLE
bm status
}
publish ::histogram_memory::countend_event user
##
# @brief Sets histogram server to default configuration, initialises SICS histogram memory
# dictionary values and clears SICS OAT BAT CAT FAT ... tables
proc ::histogram_memory::ic_initialize {} {
variable default_frame_source_when_there_is_no_frame_signal
variable default_frame_source_always_internal
set ::errorInfo ""
if [ catch {
# Generate beam monitor feedback macros
foreach bm $::counter::isc_beam_monitor_list {
set bm_num [string index $bm end]
if [string is integer $bm_num] {
set bm_status bm${bm_num}_status
::utility::macro::getset text $bm_status {} [subst -nocommands {
return "$bm_status = [SplitReply [hmm configure $bm_status]]"
}]
sicslist setatt $bm_status klass monitor
sicslist setatt $bm_status long_name $bm_status
sicslist setatt $bm_status mutable false
set bm_event_rate bm${bm_num}_event_rate
::utility::macro::getset float $bm_event_rate {} [subst -nocommands {
return "$bm_event_rate = [lindex [hmm configure $bm_event_rate] 2]"
}]
sicslist setatt $bm_event_rate klass monitor
sicslist setatt $bm_event_rate long_name $bm_event_rate
sicslist setatt $bm_event_rate mutable true
sicslist setatt $bm_event_rate units "count/sec"
} else {
error "ERROR: Failed to get beam monitor number"
}
}
set configuration "::histogram_memory::returnconfigfile config/hmm/anstohm_linked.xml"
::histogram_memory::set_graphtype "y_bin" "boundaries"
::histogram_memory::set_graphtype "x_bin" "boundaries"
::histogram_memory::set_graphtype "y_pixel_offset" "boundaries"
::histogram_memory::set_graphtype "x_pixel_offset" "boundaries"
::histogram_memory::set_graphtype "time_channel" "boundaries"
::histogram_memory::clear_tables
# FAT_TABLE -set VIEW_MAG_X -1 VIEW_MAG_Y -1
foreach hm_obj [sicslist type histmem] {
set host [dict get $::HISTMEM_HOSTPORT HMM HOST]
set port [dict get $::HISTMEM_HOSTPORT HMM PORT]
$hm_obj configure hmaddress http://$host:$port
$hm_obj configure username SICS
$hm_obj configure password SICS
$hm_obj configure histmode transparent
}
# ::histogram_memory::initialise_dictionary
::histogram_memory::frame_source_always_internal $default_frame_source_always_internal([instname])
## ffr clock scale, frame freq and source should be set in instrument specific hmm_configuration.tcl to speed up initialisation
# ::histogram_memory::set_frame_freq 50
# ::histogram_memory::set_clock_scale 1000
# ::histogram_memory::set_frame_source $default_frame_source_when_there_is_no_frame_signal([instname])
::histogram_memory::count_method unlimited
::histogram_memory::count_size 0
::histogram_memory::softveto false
hmm configure hmDataPath ../HMData
hmm configure hmconfigscript $configuration
#XXX ::histogram_memory::configure_dims
scriptcallback connect hmm COUNTEND ::histogram_memory::countend_event
} message ] {
return -code error "([info level 0]) $message"
}
}
Publish ::histogram_memory::set_oat_offset user
Publish ::histogram_memory::scan2_runb user
Publish ::histogram_memory::scan2_runa user
Publish ::histogram_memory::returnconfigfile user
Publish ::histogram_memory::save user
Publish BAT_TABLE user
Publish CAT_TABLE user
Publish FAT_TABLE user
Publish OAT_TABLE user
Publish SAT_TABLE user
##
# @brief Start an acquisition, non-blocking by default
#
# @param block (optional) default="noblock"
proc ::histogram_memory::start {{blocking "noblock"}} {
variable histmem_simulation
variable monitor_controlled
if [ catch {
set options [list block noblock]
if {[lsearch $options $blocking] == -1} {
error "ERROR: Valid options are $options"
}
::histogram_memory::pre_count
## TODO Test monitor controlled counting
# set hm_start {hmm init}
# if {$monitor_controlled == "true"} {
# set hm_start {hmm count}
# } else {
# bm setmode timer
# bm setpreset 32000000
# }
if {$blocking == "block"} {
hmm countblock
} else {
hmm count
}
} message ] {
return -code error "([info level 0]) $message"
}
}
proc ::histogram_memory::softveto {{enable ""}} {
variable state
if {$enable == ""} {
return $state(veto)
}
if {[string is boolean $enable] == 0} {
error "ERROR: $enable must be a boolean"
} else {
if {$enable} {
hmm configure FAT_SOFT_VETO_1 ENABLE
} else {
hmm configure FAT_SOFT_VETO_1 DISABLE
}
}
}
proc ::histogram_memory::veto {action} {
switch $action {
"on" {
hmm veto
}
"off" {
hmm noveto
}
default {
error "ERROR: $action must be 'on' or 'off'"
}
}
}
##
# @brief This sends the magic incantation which stops the histogram server.
proc ::histogram_memory::stop {} {
variable histmem_simulation
if [ catch {
hmm pause
hmm configure statuscheck true
hmm astop
hmm configure statuscheck false
set reply [SplitReply [hmm configure daq]]
if {$histmem_simulation==false && $reply != "Stopped"} {
error "ERROR: Histogram server failed to stop"
}
} message ] {
return -code error "([info level 0]) $message"
}
clientput "histmem stopped" value
}
##
# @brief Allows resume if MULTIPLE_DATASETS=DISABLE, otherwise if MULTIPLE_DATASETS=ENABLE
# (the default) this acts like a stop but allows a fast restart.
proc ::histogram_memory::pause {} {
variable histmem_simulation
if [ catch {
hmm pause
::histogram_memory::post_count
set reply [SplitReply [hmm configure daq]]
if {$histmem_simulation==false && $reply != "Paused"} {
error "ERROR: Histogram server failed to pause"
}
} message ] {
return -code error "([info level 0]) $message"
}
clientput "histmem paused" value
}
##
# @brief Choose method for controlling acquisition duration.
#
# @param method Set histmem mode or return current mode if blank
proc ::histogram_memory::count_method {{method ""}} {
variable ic_count_methods
variable preset_mult
variable monitor_controlled
if {$method==""} {
return [SplitReply [hmm_mode]]
}
if [ catch {
set modes $ic_count_methods
if {[lsearch $modes $method] == -1} {
error "ERROR: Count mode, $method, must be one of $modes"
}
if {$method == "time"} {
set preset_mult 100
} else {
set preset_mult 1
}
hmm configure FAT_COUNT_METHOD $method
if {[string range $method 0 [string first "R_" $method]] == "MONITOR"} {
hmm configure FAT_${method}_CONTROL ENABLE
set bmchan [expr [string index $method end] - 1]
bm setchannel $bmchan
set monitor_controlled "true"
} else {
set monitor_controlled "false"
}
hmm astop
hmm init
hmm_mode $method
} message ] {
return -code error "([info level 0]) $message"
}
}
##
# @brief Count until the preset count size has been reached.
#
# @param preset: The interpretation of the preset depends on the count method.
# @see count_method
proc ::histogram_memory::count_size {{preset ""}} {
variable state
variable preset_mult
if [ catch {
if {$preset == ""} {
return $state(preset)
} else {
if {[string is double $preset] == 0 || $preset < 0} {
error "ERROR: The preset must be a non-negative floating point number"
}
hmm configure FAT_COUNT_SIZE [expr {$preset_mult * $preset}]
hmm init
set state(preset) $preset
hmm_preset $preset
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
##
# @brief Check histogram memory status
#
# @return Stopped, Paused, Started, or raises a Tcl error
proc ::histogram_memory::hmm_status {} {
if [ catch {
set reply [SplitReply [hmm configure daq]]
} message ] {
return -code error "([info level 0]) $message"
}
return $reply
}
##
# @brief Set stop condition for histogram memory
#
# @param condition
proc ::histogram_memory::stop_condition {condition} {
variable state
if [ catch {
array set count_stop {immediate IMMEDIATE period AT_END_OF_PERIOD}
if {$condition == ""} {
return $state(stop_cond)
} else {
hmm configure FAT_COUNT_STOP $count_stop($condition)
hmm init
set state(stop_cond) $condition
}
} message ] {
if {$::errorCode=="NONE"} {return $message}
return -code error "([info level 0]) $message"
}
}
# Make controller for histmem textstatus. Used by hmstat proc
set host [dict get $::HISTMEM_HOSTPORT HMSTAT HOST]
set port [dict get $::HISTMEM_HOSTPORT HMSTAT PORT]
if {$::histogram_memory::histmem_simulation == "false"} {
MakeSctController sct_hmm astvelsel $host:$port
}
proc ::histogram_memory::hmstat {args} {
variable histmem_simulation
if {$histmem_simulation == "true"} {
return
}
set startIndex -1
# Try three times to get at least some data following the HTTP header.
# Usually we get all the data but sometimes we just get the header.
for {set i 0} {$i < 3 && $startIndex == -1} {incr i} {
set req "GET /admin/textstatus.egi HTTP/1.1\r\nAuthorization: Basic bWFuYWdlcjphbnN0bw==\r\n"
set textstatus [sct_hmm transact $req]
set lTextStatus [split $textstatus \n]
set startIndex [lsearch -glob $lTextStatus HM-Host*]
}
# Throw away HTTP header
set lTextStatus [lrange $lTextStatus $startIndex end]
# Create text status array
foreach l $lTextStatus {
if {[string length $l] == 0} {
continue
}
set v [split $l ':']
set key [lindex $v 0]
set val [lindex $v 1 0]
if [string is double $val] {
set hmarr($key) $val
} else {
set hmarr($key) '$val'
}
}
# Return requested values to user
set argc [llength $args]
switch $argc {
0 {
set keys [array names hmarr]
foreach k [lrange $keys 0 end-1] {
lappend d "'$k': $hmarr($k),"
}
set k [lindex $keys end]
lappend d "'$k': $hmarr($k)"
return [join $d]
}
1 {
return $hmarr($args)
}
default {
foreach k [lrange $args 0 end-1] {
lappend d "'$k': $hmarr($k),"
}
set k [lindex $args end]
lappend d "'$k': $hmarr($k)"
return [join $d]
}
}
}
# Poll to keep HTTP connection alive
if {$::histogram_memory::histmem_simulation == "false"} {
sicspoll add ::histogram_memory::hmstat script 30 ::histogram_memory::hmstat
}
namespace eval ::histogram_memory {
#TODO Create GumTree commands to setup, start and stop the histmem
##
# @brief Choose method for controlling acquisition duration.
#command mode {text:time,monitor,unlimited,period,count,frame method} {}
##
# @brief Count until the preset count size has been reached.
#
# @param preset: The interpretation of the preset depends on the count method.
# @see count_method
#command preset {float: pre} {}
##
# @brief Set stop condition for histogram memory
#
# @param condition
#command stop_condition {text:immediate,period condition}
}
##
# @brief Convenience command providing user interface to histogram control
#
# @param cmd is one of start, stop, pause, mode, preset, fsrce, status, loadconf
# @param args is an optional list of arguments for the given command
proc _histmem {cmd args} {
#TODO Add "continue"
set reply ""
if [ catch {
switch $cmd {
"start" {
eval "::histogram_memory::start $args"
}
"stop" {
::histogram_memory::stop
}
"pause" {
::histogram_memory::pause
}
"veto" {
eval "::histogram_memory::veto $args"
}
"mode" {
if {$args == ""} {
set reply [::histogram_memory::count_method ]
} else {
eval "::histogram_memory::count_method $args"
}
}
"preset" {
if {$args == ""} {
set reply [::histogram_memory::count_size ]
} else {
eval "::histogram_memory::count_size $args"
}
}
"clockscale" {
if {$args == ""} {
set reply [::histogram_memory::get_clock_scale ]
} else {
eval "::histogram_memory::set_clock_scale $args"
}
}
"freq" {
if {$args == ""} {
set reply [::histogram_memory::get_frame_freq ]
} else {
eval "::histogram_memory::set_frame_freq $args"
}
}
"fsrce" {
if {$args == ""} {
set reply [::histogram_memory::get_frame_source ]
} else {
eval "::histogram_memory::set_frame_source $args"
}
}
"status" {
set reply [::histogram_memory::hmm_status]
}
"textstatus" {
set reply [eval "::histogram_memory::hmstat $args"]
}
"loadconf" {
# Loads configuration tables (OAT, FAT, ...) to histogram server
if {$args == ""} {
::histogram_memory::upload_config Filler_defaults
} else {
eval "::histogram_memory::upload_config $args"
}
}
default {
error "ERROR: Available commands are, start stop pause mode preset freq fsrce status loadconf"
}
}
} message ] {
return -code error "([info level 0]) $message"
}
return $reply
}