750 lines
24 KiB
Tcl
750 lines
24 KiB
Tcl
##
|
|
# @file Scan functionality and common high level commands are defined here.
|
|
#
|
|
# namespace variables\n
|
|
# ::scan::save_filetype data/scratch, controls if data will be saved to a
|
|
# scratch file.\n
|
|
# ::scan::reset_position true/false (default=true), drive motor back to start
|
|
# position at end of scan\n
|
|
# ::scan::force_scan true/false, (default=false), Will force a scan if the
|
|
# instrument isn't ready, eg shutters closed. Note: The scan will still fail if
|
|
# you are scanning against a motor and motion control is disabled.\n
|
|
# If force_scan is true it is immediately reset to false after it is checked.
|
|
#TODO Get rid of duplication in bmonscan and hmscan code
|
|
|
|
namespace eval scan {
|
|
variable ic_runscanpar
|
|
|
|
variable ic_hmm_datatype
|
|
variable save_filetype
|
|
variable reset_position
|
|
variable check_thread0
|
|
variable check_instrument_ready
|
|
variable force_scan
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
variable scaninitposlist
|
|
|
|
set check_thread0 true
|
|
set check_instrument_ready true
|
|
set force_scan false
|
|
set save_filetype "data"
|
|
set reset_position "false"
|
|
|
|
if {[SplitReply [motor_simulation]] == "true"} {
|
|
set check_thread0 false
|
|
}
|
|
|
|
}
|
|
|
|
##
|
|
# @brief This is a convenience command which allows hmscans to be forced.
|
|
# Call this before calling hmscan run to force a scan if the instrument isn't ready.
|
|
proc force_scan {} {
|
|
set ::scan::force_scan "true"
|
|
}
|
|
publish force_scan user
|
|
|
|
proc ::scan::print_hdr_svars {sobj point counts actime} {
|
|
set numvars [SplitReply [$sobj noscanvar]]
|
|
set infostart [expr [string length $sobj] + 1]
|
|
for {set i 0} {$i < $numvars} {incr i} {
|
|
set svinfo [$sobj getvarpar $i]
|
|
foreach {svar start step} [ split [string range $svinfo $infostart end] = ] {
|
|
set svar [string trim $svar]
|
|
lappend scanvarlist $svar
|
|
lappend scanstartlist $start
|
|
lappend scansteplist $step
|
|
lappend varposlist [SplitReply [$svar]]
|
|
}
|
|
}
|
|
set fmtstr "%-4.4s [string repeat "%-9.9s " $numvars] %-14s %-7.7s"
|
|
|
|
set headercmd [subst {format "$fmtstr" NP $scanvarlist Counts Time}]
|
|
set header [eval $headercmd ]
|
|
set fmtstr "%-4d [string repeat "%-9.3f " $numvars] %-14d %-7.2f"
|
|
set datacmd [subst {format "$fmtstr" $point $varposlist $counts $actime} ]
|
|
set data [eval $datacmd]
|
|
clientput $header
|
|
clientput $data
|
|
}
|
|
proc ::scan::bm_scan_collect {sobj uobj point} {
|
|
set counts [SplitReply [bm getcounts]]
|
|
set actime [SplitReply [bm gettime]]
|
|
print_hdr_svars $sobj $point $counts $actime
|
|
for {set chn 0} {$chn < $::counter::isc_numchannels} {incr chn} {
|
|
clientput "Channel $chn [SplitReply [bm getmonitor $chn]]"
|
|
}
|
|
}
|
|
|
|
proc ::scan::hmm_scan_collect {sobj uobj point} {
|
|
set counts [SplitReply [::histogram_memory::total_counts]]
|
|
set actime [SplitReply [::histogram_memory::time]]
|
|
print_hdr_svars $sobj $point $counts $actime
|
|
for {set bmn 1} {$bmn <= $::counter::isc_numchannels} {incr bmn} {
|
|
set bmon bm$bmn
|
|
clientput "Monitor $bmn [SplitReply [$bmon getcounts]]"
|
|
}
|
|
}
|
|
proc ::scan::hmscanend_event {} {
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
|
|
::scan::runscan_cmd -set feedback status IDLE
|
|
}
|
|
publish ::scan::hmscanend_event user
|
|
|
|
proc ::scan::bmonscanend_event {} {
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
|
|
::scan::hdb_bmonscan -set feedback status IDLE
|
|
}
|
|
publish ::scan::bmonscanend_event user
|
|
|
|
proc ::scan::ic_initialize {} {
|
|
if [ catch {
|
|
variable ic_runscanpar
|
|
variable ic_hmm_datatype
|
|
|
|
set ic_hmm_datatype HISTOGRAM_XYT
|
|
|
|
MakeScanCommand hmscan bm $::cfPath(scan)/scan_common_1.hdd recover.bin
|
|
MakeScanCommand bmonscan bm $::cfPath(scan)/scan_common_1.hdd recover.bin
|
|
|
|
bmonscan configure script
|
|
bmonscan function writeheader ::scan::donothing
|
|
bmonscan function writepoint ::scan::bm_writepoint
|
|
bmonscan function count ::scan::bm_count
|
|
bmonscan function collect ::scan::bm_scan_collect
|
|
bmonscan function prepare ::scan::bm_scan_prepare
|
|
bmonscan function finish ::scan::bm_scan_finish
|
|
|
|
|
|
hmscan configure script
|
|
hmscan function writeheader ::scan::donothing
|
|
hmscan function writepoint ::scan::hmm_writepoint
|
|
hmscan function count ::scan::hmm_count
|
|
hmscan function collect ::scan::hmm_scan_collect
|
|
hmscan function prepare ::scan::hmm_scan_prepare
|
|
hmscan function finish ::scan::hmm_scan_finish
|
|
|
|
# TODO Use ic_runscanpar to create the ::scan::runscan command and
|
|
# to validate the "runscan" proc parameters.
|
|
array set ic_runscanpar [subst {
|
|
scanvar text=drivable
|
|
start float
|
|
stop float
|
|
numpoints int=0,inf
|
|
mode text=[join [concat [list time unlimited period count frame] $::counter::isc_beam_monitor_list ] , ]
|
|
preset float=0,inf
|
|
datatype text=[join [array names ::nexus::histmem_filetype_spec] , ]
|
|
savetype text=save,nosave
|
|
force boolean
|
|
}]
|
|
scriptcallback connect hmscan SCANEND ::scan::hmscanend_event
|
|
scriptcallback connect bmonscan SCANEND ::scan::bmonscanend_event
|
|
} message ] {
|
|
if {$::errorCode=="NONE"} {return $message}
|
|
return -code error $message
|
|
}
|
|
}
|
|
|
|
##
|
|
# @brief Returns an error if a scan variable target position exceeds the limits.
|
|
proc ::scan::check_limit {scan_variable limit_name target} {
|
|
switch $limit_name {
|
|
"hardlowerlim" - "softlowerlim" {
|
|
set limit [SplitReply [$scan_variable $limit_name]]
|
|
if { $target < $limit} {
|
|
return -code error "Final position of $target violates $limit_name $limit for $scan_variable"
|
|
}
|
|
}
|
|
"hardupperlim" - "softupperlim" {
|
|
set limit [SplitReply [$scan_variable $limit_name]]
|
|
if { $target > $limit} {
|
|
return -code error "Final position of $target violates $limit_name $limit for $scan_variable"
|
|
}
|
|
}
|
|
default {
|
|
return -code error "Invalid limit name $limit_name"
|
|
}
|
|
}
|
|
}
|
|
## \brief check final position against scan variable limits
|
|
#
|
|
# NOTE: The sics scan object alread checks if a variable is drivable
|
|
# so we don't have to.
|
|
# TODO We can't check limits of virtual motors yet because the
|
|
# configurablevirtualmotor doesn't set a checklimits function.
|
|
proc ::scan::check_scanvar {sobj uobj} {
|
|
variable check_thread0
|
|
set vlist [split [$sobj getvarpar 0] = ];
|
|
set NP [SplitReply [$sobj np]]
|
|
set scan_variable [string trim [lindex [split [lindex $vlist 0] . ] 1]]
|
|
set scan_start [lindex $vlist 1];
|
|
set scan_increment [lindex $vlist 2];
|
|
if {[getatt $scan_variable type] == "motor"} {
|
|
if {[SplitReply [$scan_variable fixed]] >= 0} {
|
|
return -code error "ERROR: Can't drive scan variable, $scan_variable position is set to 'fixed'"
|
|
} else {
|
|
set mtype [getatt $scan_variable mtype]
|
|
if {$mtype != "tclmot" && $check_thread0 && [SplitReply [$scan_variable thread0]] == -1} {
|
|
return -code error "ERROR: Can't scan ${scan_variable}. Thread zero has stopped running on the motion controller"
|
|
}
|
|
}
|
|
set scan_final [expr $scan_start + ($NP-1) * $scan_increment]
|
|
if [catch {
|
|
::scan::check_limit $scan_variable softlowerlim $scan_final
|
|
::scan::check_limit $scan_variable softupperlim $scan_final
|
|
::scan::check_limit $scan_variable softlowerlim $scan_start
|
|
::scan::check_limit $scan_variable softupperlim $scan_start
|
|
}] {
|
|
return -code error $::errorInfo
|
|
}
|
|
}
|
|
}
|
|
|
|
##
|
|
# @brief Instrument specific scan configurations can override this procedure to perform some setup
|
|
# before running a scan, eg setting hmm frame frequency.
|
|
#
|
|
# NOTES\n
|
|
# Returning an error will cause the scan to abort before it starts\n
|
|
# eg\n
|
|
# return -code error "error message"
|
|
proc ::scan::pre_hmm_scan_prepare {} {}
|
|
|
|
##
|
|
# @brief Do some pre-scan checks and prime the DAE
|
|
proc ::scan::hmm_scan_prepare {sobj uobj} {
|
|
variable save_filetype
|
|
variable ic_hmm_datatype
|
|
variable check_instrument_ready
|
|
variable force_scan
|
|
|
|
if {$force_scan || $check_instrument_ready && [::plc::inst_ready]} {
|
|
set force_scan false
|
|
if [catch {
|
|
::scan::check_scanvar $sobj $uobj
|
|
::scan::pre_hmm_scan_prepare
|
|
}] {
|
|
return -code error "HMSCAN ABORTED: $::errorInfo"
|
|
}
|
|
|
|
if [catch {
|
|
set numpoints [SplitReply [$sobj np]]
|
|
set numvars [SplitReply [$sobj noscanvar]]
|
|
set infostart [expr [string length $sobj] + 1]
|
|
for {set i 0} {$i < $numvars} {incr i} {
|
|
set svinfo [$sobj getvarpar $i]
|
|
foreach {sv start step} [ split [string range $svinfo $infostart end] = ] {
|
|
lappend scanvarlist $sv
|
|
lappend scanstartlist $start
|
|
lappend scansteplist $step
|
|
}
|
|
}
|
|
|
|
::scan::runscan_cmd -set feedback status BUSY
|
|
run_mode "hmscan"
|
|
|
|
set ::histogram_memory::histmem_axes(SVAR) [SplitReply [sicslist [lindex $::scan::scanvarlist 0] hdb_path] ]
|
|
::nexus::newfile $ic_hmm_datatype $save_filetype
|
|
|
|
foreach sv $scanvarlist scanstart $scanstartlist scanstep $scansteplist {
|
|
clientput "Scanvar: $sv start: $scanstart, Scan step: $scanstep, Number of points: $numpoints"
|
|
}
|
|
clientput "Datatype: $ic_hmm_datatype"
|
|
# Prime DAE
|
|
hmm pause
|
|
}] {
|
|
run_mode "normal"
|
|
return -code error $::errorInfo
|
|
}
|
|
} else {
|
|
return -code error "HMSCAN ABORTED: Instrument not ready"
|
|
}
|
|
}
|
|
|
|
proc ::scan::hmm_count {sobj uobj point mode preset} {
|
|
::scan::runscan_cmd -set feedback scanpoint $point
|
|
::scan::runscan_cmd -set feedback scan_variable_value [SplitReply [[lindex $::scan::scanvarlist 0]]]
|
|
# Start histogram and block until count is complete
|
|
::histogram_memory::start block
|
|
}
|
|
|
|
#TODO rangescan: drive to original position for rangescans, not the start position.
|
|
proc ::scan::hmm_scan_finish {sobj uobj} {
|
|
variable save_filetype
|
|
variable reset_position
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
variable scaninitposlist
|
|
|
|
set $save_filetype "data"
|
|
::histogram_memory::stop
|
|
::scan::runscan_cmd -set feedback status IDLE
|
|
run_mode "normal"
|
|
set ::histogram_memory::histmem_axes(SVAR) "/instrument/run_number"
|
|
# Make sure that the next save command doesn't overwrite our scan data.
|
|
# and clear any data links
|
|
::nexus::newfile clear data
|
|
if {$reset_position == "true"} {
|
|
# set reset_position "false"
|
|
foreach svar $scanvarlist initpos $scaninitposlist {
|
|
set svtype [getatt $svar type]
|
|
if {$svtype == "motor" || $svtype == "configurablevirtualmotor"} {
|
|
lappend drivelist $svar $initpos
|
|
}
|
|
eval drive $drivelist
|
|
}
|
|
}
|
|
# ::histogram_memory::configure_server Filler_defaults
|
|
}
|
|
|
|
proc ::scan::bm_scan_finish {sobj uobj} {
|
|
variable reset_position
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
variable scaninitposlist
|
|
|
|
::scan::hdb_bmonscan -set feedback status IDLE
|
|
run_mode "normal"
|
|
set ::histogram_memory::histmem_axes(SVAR) "/instrument/run_number"
|
|
# Make sure that the next save command doesn't overwrite our scan data.
|
|
# and clear any data links
|
|
::nexus::newfile clear data
|
|
if {$reset_position == "true"} {
|
|
# set reset_position "false"
|
|
foreach svar $scanvarlist initpos $scaninitposlist {
|
|
set svtype [getatt $svar type]
|
|
if {$svtype == "motor" || $svtype == "configurablevirtualmotor"} {
|
|
lappend drivelist $svar $initpos
|
|
}
|
|
eval drive $drivelist
|
|
}
|
|
}
|
|
}
|
|
|
|
proc ::scan::bm_writepoint {sobj uobj pt} {
|
|
::nexus::save $pt
|
|
|
|
::scan::hdb_bmonscan -set feedback counts [SplitReply [bm getcounts]];
|
|
}
|
|
|
|
#TODO Feedback for Histogram memory scan
|
|
proc ::scan::hmm_writepoint {sobj uobj pt} {
|
|
variable save_filetype
|
|
# Write hdb tree
|
|
::nexus::save $pt
|
|
}
|
|
|
|
proc ::scan::donothing {args} {}
|
|
|
|
proc ::scan::bm_count {sobj uobj point mode preset} {
|
|
::scan::hdb_bmonscan -set mode $mode
|
|
::scan::hdb_bmonscan -set preset $preset
|
|
::scan::hdb_bmonscan -set feedback scanpoint $point;
|
|
::scan::hdb_bmonscan -set feedback mode $mode;
|
|
::scan::hdb_bmonscan -set feedback preset $preset;
|
|
::scan::hdb_bmonscan -set feedback scan_variable_value [SplitReply [[lindex $::scan::scanvarlist 0]]]
|
|
::monitor::count $mode $preset
|
|
}
|
|
|
|
proc ::scan::bm_scan_prepare {sobj uobj} {
|
|
|
|
variable save_filetype
|
|
variable check_instrument_ready
|
|
variable force_scan
|
|
|
|
if {$force_scan || $check_instrument_ready && [::plc::inst_ready]} {
|
|
set force_scan false
|
|
if [catch {
|
|
::scan::check_scanvar $sobj $uobj
|
|
::scan::pre_hmm_scan_prepare
|
|
}] {
|
|
return -code error "BMONSCAN ABORTED: $::errorInfo"
|
|
}
|
|
|
|
if [catch {
|
|
#TODO Parameterise varindex in some way
|
|
set varindex 0
|
|
set numpoints [SplitReply [$sobj np]]
|
|
set numvars [SplitReply [$sobj noscanvar]]
|
|
set infostart [expr [string length $sobj] + 1]
|
|
for {set i 0} {$i < $numvars} {incr i} {
|
|
set svinfo [$sobj getvarpar $i]
|
|
foreach {sv start step} [ split [string range $svinfo $infostart end] = ] {
|
|
lappend scanvarlist $sv
|
|
lappend scanstartlist $start
|
|
lappend scansteplist $step
|
|
}
|
|
}
|
|
set vlist [split [$sobj getvarpar $varindex] = ]
|
|
set scanstart [lindex $vlist 1]
|
|
set scanstep [lindex $vlist 2]
|
|
::scan::hdb_bmonscan -set NP $numpoints
|
|
::scan::hdb_bmonscan -set scan_variable [string trim [lindex [split [lindex $vlist 0] . ] 1]];
|
|
::scan::hdb_bmonscan -set scan_start $scanstart
|
|
::scan::hdb_bmonscan -set scan_increment $scanstep
|
|
set scanvar_pts [SplitReply [$sobj getvardata $varindex]]
|
|
|
|
::scan::hdb_bmonscan -set feedback status BUSY
|
|
run_mode "bmonscan"
|
|
|
|
array set bm_fb [::scan::hdb_bmonscan -list feedback]
|
|
set ::histogram_memory::histmem_axes(SVAR) [SplitReply [sicslist [lindex $::scan::scanvarlist 0] hdb_path] ]
|
|
::nexus::newfile BEAM_MONITOR $save_filetype
|
|
#stdscan prepare $sobj $uobj;
|
|
foreach sv $scanvarlist scanstart $scanstartlist scanstep $scansteplist {
|
|
clientput "Scanvar: $sv start: $scanstart, Scan step: $scanstep, Number of points: $numpoints"
|
|
}
|
|
clientput "Datatype: BEAM_MONITOR"
|
|
}] {
|
|
run_mode "normal"
|
|
return -code error $::errorInfo
|
|
}
|
|
} else {
|
|
return -code error "BMONSCAN ABORTED: Instrument not ready"
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Publish ::scan::hmm_count user
|
|
Publish ::scan::hmm_scan_prepare user
|
|
Publish ::scan::hmm_scan_finish user
|
|
Publish ::scan::hmm_scan_collect user
|
|
Publish ::scan::hmm_writepoint user
|
|
Publish ::scan::donothing user
|
|
|
|
Publish ::scan::bm_scan_prepare user
|
|
Publish ::scan::bm_scan_finish user
|
|
Publish ::scan::bm_scan_collect user
|
|
Publish ::scan::bm_writepoint user
|
|
Publish ::scan::bm_count user
|
|
|
|
namespace eval scan {
|
|
namespace export runscan mscan
|
|
VarMake ::scan::runscan_reset_position Text internal
|
|
::scan::runscan_reset_position false
|
|
|
|
# Utility to check the type of an argument
|
|
# returns true or raises an error if the type is invalid
|
|
proc checkarg {arg type errmsg} {
|
|
if {[string length $arg] == 0} {
|
|
error "Not enough arguments"
|
|
}
|
|
if {$type == "varname"} {
|
|
if [ string is alpha [string index $arg 0] ] {
|
|
set type "wordchar"
|
|
} else {
|
|
error $errmsg
|
|
}
|
|
}
|
|
|
|
if [string is $type $arg] {
|
|
return 1
|
|
} else {
|
|
error $errmsg
|
|
}
|
|
}
|
|
|
|
##
|
|
# @brief Sets up and runs an hmscan or bmonscan object from a list of scan variables
|
|
# and parameters
|
|
proc doscan {scanvarlist startlist steplist numpoints mode preset args} {
|
|
variable ic_hmm_datatype
|
|
variable save_filetype
|
|
variable force_scan
|
|
|
|
foreach scanvar $scanvarlist {
|
|
if {[is_drivable $scanvar] == 0} {
|
|
error "The scan variable <$scanvar> must be drivable"
|
|
}
|
|
}
|
|
if {[string is integer $numpoints] != 1} {
|
|
error "Number of points <$numpoints> must be an integer"
|
|
}
|
|
if { $numpoints < 1 } {
|
|
error "Number of points <$numpoints> must not be less than one"
|
|
}
|
|
|
|
set save_filetype data
|
|
foreach {arg val} $args {
|
|
switch $arg {
|
|
"force" {
|
|
if [string is boolean $val] {
|
|
set force_scan $val
|
|
} else {
|
|
error "ERROR: force must be true or false"
|
|
}
|
|
}
|
|
"datatype" {
|
|
set ic_hmm_datatype $val
|
|
}
|
|
"savetype" {
|
|
switch $val {
|
|
"save" {
|
|
set save_filetype data
|
|
}
|
|
"nosave" {
|
|
set save_filetype scratch
|
|
}
|
|
default {
|
|
error "ERROR: $arg $val, valid values for $arg are 'save' or 'nosave'"
|
|
}
|
|
}
|
|
}
|
|
default {
|
|
error "ERROR: $arg should be 'datatype' 'savetype' or 'force'"
|
|
}
|
|
}
|
|
}
|
|
|
|
set det_type [::scan::runscan_cmd -get detector]
|
|
if {$det_type == "histmem"} {
|
|
# hmscan ignores mode and preset, we use FAT_COUNT_METHOD and FAT_COUNT_STOP
|
|
::histogram_memory::count_method $mode
|
|
::histogram_memory::count_size $preset
|
|
hmscan clear
|
|
foreach scanvar $scanvarlist start $startlist step $steplist {
|
|
hmscan add $scanvar $start $step
|
|
}
|
|
} elseif {$det_type == "bmon"} {
|
|
set mode [string tolower $mode]
|
|
switch -glob $mode {
|
|
"time" { set bms_mode "timer" }
|
|
"monitor" { set bms_mode "monitor" }
|
|
default {return -code error "ERROR: mode should be 'time' or 'monitor' not $mode"}
|
|
}
|
|
bmonscan clear
|
|
foreach scanvar $scanvarlist start $startlist step $steplist {
|
|
bmonscan add $scanvar $start $step
|
|
}
|
|
} else {
|
|
return -code error "ERROR: detector type should be 'histmem' or 'bmon' not $det_type"
|
|
}
|
|
if {$det_type == "histmem"} {
|
|
hmscan run $numpoints timer 0
|
|
} else {
|
|
bmonscan run $numpoints $bms_mode $preset
|
|
}
|
|
}
|
|
|
|
## Multi-variable runscan
|
|
proc mscan {scanvar start step args} {
|
|
variable ic_hmm_datatype
|
|
variable reset_position
|
|
variable force_scan
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
variable scaninitposlist
|
|
|
|
set scanvarlist {}
|
|
set startlist {}
|
|
set steplist {}
|
|
set scaninitposlist {}
|
|
|
|
if [ catch {
|
|
set force_scan false
|
|
|
|
set hm_ft_names [array names ::nexus::histmem_filetype_spec]
|
|
|
|
# Default filetype for histogram memory scans
|
|
set ic_hmm_datatype "HISTOGRAM_XYT"
|
|
# Default save uniquely numbered files
|
|
set savetype "save"
|
|
set reset_position [SplitReply [::scan::runscan_reset_position]]
|
|
|
|
checkarg $scanvar varname "Expecting a scan variable name, not $scanvar"
|
|
checkarg $start double "Expecing a float for $scanvar start value, not $start"
|
|
checkarg $step double "Expecing a float for $scanvar step value, not $step"
|
|
lappend scanvarlist $scanvar
|
|
lappend startlist $start
|
|
lappend steplist $step
|
|
for {set argindex 0} {1} {incr argindex 3} {
|
|
set par [lindex $args $argindex]
|
|
if {[string length $par] == 0} {
|
|
error "Not enough arguments"
|
|
} elseif [string is double $par] {
|
|
set numpoints $par
|
|
incr argindex
|
|
break
|
|
}
|
|
set err "Expecting another scan variable name or number of scanpoints instead of $par"
|
|
checkarg $par varname $err
|
|
|
|
lappend scanvarlist [lindex $args $argindex]
|
|
set start [lindex $args $argindex+1]
|
|
if {![string is double $start]} {
|
|
error "Scan variable start value should be a float, not $start"
|
|
}
|
|
lappend startlist $start
|
|
set step [lindex $args $argindex+2]
|
|
if {![string is double $step]} {
|
|
error "Scan variable step value should be a float, not $step"
|
|
}
|
|
lappend steplist $step
|
|
}
|
|
set mode [lindex $args $argindex]
|
|
incr argindex
|
|
checkarg $mode alpha "Expecting mode but got $mode"
|
|
|
|
set preset [lindex $args $argindex]
|
|
incr argindex
|
|
checkarg $preset double "Expecting preset but got $preset"
|
|
foreach scanvar $scanvarlist {
|
|
lappend scaninitposlist [SplitReply [$scanvar]]
|
|
}
|
|
# The {*}[...] below uses the Tcl8.5 expand operator {*} to pass a list as separate arguments
|
|
doscan $scanvarlist $startlist $steplist $numpoints $mode $preset {*}[lrange $args $argindex end]
|
|
} message ] {
|
|
set force_scan false
|
|
return -code error "ERROR [info level 0]\n$message"
|
|
} else {
|
|
set force_scan false
|
|
return $message
|
|
}
|
|
}
|
|
|
|
#TODO Add counter (monitor_1 monitor_2 ... histmem) and filetype BEAM_MONITOR HISTMEM_?
|
|
##
|
|
# @brief Run a histogram memory scan
|
|
# @param filetype one of the histogram filetypes (default=HISTOGRAM_XYT)
|
|
# @param savetype save/nosave (default=save)
|
|
# @param force true/false (default=false)
|
|
proc runscan {scanvar start stop numpoints mode preset args} {
|
|
variable ic_hmm_datatype
|
|
variable save_filetype
|
|
variable reset_position
|
|
variable force_scan
|
|
variable scanvarlist
|
|
variable startlist
|
|
variable steplist
|
|
variable scaninitposlist
|
|
|
|
set scanvarlist {}
|
|
set startlist {}
|
|
set steplist {}
|
|
set scaninitposlist {}
|
|
|
|
if [ catch {
|
|
set force_scan false
|
|
|
|
set hm_ft_names [array names ::nexus::histmem_filetype_spec]
|
|
|
|
# Default filetype for histogram memory scans
|
|
set ic_hmm_datatype "HISTOGRAM_XYT"
|
|
# Default save uniquely numbered files
|
|
set savetype "save"
|
|
set reset_position [SplitReply [::scan::runscan_reset_position]]
|
|
if {[is_drivable $scanvar] == 0} {
|
|
error "The scan variable <$scanvar> must be drivable"
|
|
}
|
|
lappend scanvarlist $scanvar
|
|
lappend startlist $start
|
|
if {[string is integer $numpoints] != 1} {
|
|
error "Number of points <$numpoints> must be an integer"
|
|
}
|
|
if { $numpoints < 1 } {
|
|
error "Number of points <$numpoints> must not be less than one"
|
|
}
|
|
|
|
if {$numpoints == 1} {
|
|
set step 0
|
|
} else {
|
|
set step [expr double($stop - $start)/($numpoints - 1.0)]
|
|
}
|
|
lappend steplist $step
|
|
if {$step == 0 && $numpoints > 1} {
|
|
clientput "WARNING:Scan step is zero and number of points > 1. Adjusting numpoints to one"
|
|
set numpoints 1
|
|
}
|
|
|
|
set save_filetype data
|
|
foreach {arg val} $args {
|
|
switch $arg {
|
|
"force" {
|
|
if [string is boolean $val] {
|
|
set force_scan $val
|
|
} else {
|
|
error "ERROR: force must be true or false"
|
|
}
|
|
}
|
|
"datatype" {
|
|
set ic_hmm_datatype $val
|
|
}
|
|
"savetype" {
|
|
switch $val {
|
|
"save" {
|
|
set save_filetype data
|
|
}
|
|
"nosave" {
|
|
set save_filetype scratch
|
|
}
|
|
default {
|
|
error "ERROR: $arg $val, valid values for $arg are 'save' or 'nosave'"
|
|
}
|
|
}
|
|
}
|
|
default {
|
|
error "ERROR: $arg should be 'datatype' 'savetype' or 'force'"
|
|
}
|
|
}
|
|
}
|
|
|
|
set det_type [::scan::runscan_cmd -get detector]
|
|
if {$det_type == "histmem"} {
|
|
# hmscan ignores mode and preset, we use FAT_COUNT_METHOD and FAT_COUNT_STOP
|
|
::histogram_memory::count_method $mode
|
|
::histogram_memory::count_size $preset
|
|
hmscan clear
|
|
hmscan add $scanvar $start $step
|
|
} elseif {$det_type == "bmon"} {
|
|
set mode [string tolower $mode]
|
|
switch -glob $mode {
|
|
"time" { set bms_mode "timer" }
|
|
"monitor" { set bms_mode "monitor" }
|
|
default {return -code error "ERROR: mode should be 'time' or 'monitor' not $mode"}
|
|
}
|
|
bmonscan clear
|
|
bmonscan add $scanvar $start $step
|
|
} else {
|
|
return -code error "ERROR: detector type should be 'histmem' or 'bmon' not $det_type"
|
|
}
|
|
lappend scaninitposlist [SplitReply [$scanvar]]
|
|
::scan::runscan_cmd -set numpoints $numpoints
|
|
::scan::runscan_cmd -set scan_variable $scanvar
|
|
::scan::runscan_cmd -set scan_start $start
|
|
::scan::runscan_cmd -set scan_stop $stop
|
|
::scan::runscan_cmd -set feedback scan_step $step
|
|
::scan::runscan_cmd -set mode $mode
|
|
::scan::runscan_cmd -set preset $preset
|
|
if {$det_type == "histmem"} {
|
|
hmscan run $numpoints timer 0
|
|
} else {
|
|
bmonscan run $numpoints $bms_mode $preset
|
|
}
|
|
} message ] {
|
|
set force_scan false
|
|
return -code error "ERROR [info level 0]\n$message"
|
|
} else {
|
|
set force_scan false
|
|
return $message
|
|
}
|
|
}
|
|
|
|
}
|
|
namespace import ::scan::runscan
|
|
namespace import ::scan::mscan
|
|
publish runscan user
|
|
publish mscan user
|
|
sicslist setatt runscan privilege internal
|