Files
sics/site_ansto/instrument/config/scan/scan_common_1.tcl
Ferdi Franceschini d9da95a5df sct_protek608.c
Implements a protocol handler for the protek  608 multimeters which just allows us to read the display.
It reports all elements of the display including the bar graph, it does not provide remote control of the multimeter.  The protocol handler broadcasts a warning to all clients if the auto-off function is enabled.

sct_rfamp.c
This is a protocol handler for the Mirrortron 35V 7A AC Generator (ANSFR-83B).

sinqhttpprot.c
Copied the PSI script context http protocol handler.

sct_orhvpsprot.c
Ordela high voltage power supply protocol handler now catches unknown commands.

sct_eurotherm_2000.tcl
Eurotherm controller for the kowari load frame by Douglas Clowes.

sct_lakeshore_3xx.tcl
Latest update from Arndt.  The two control loops are now independent, settletime and tolerance now work properly.

common_instrument_dictionary.tcl
Make instrument/status saveable.

sct_orhvps_common.tcl
Provides voltage ramping and implements the dhv1 command for the Ordela HVPS via the sct_orhpsprot.c protocol handler.

hmm_configuration_common_1.tcl
Adds new "histmem clockscale" subcommand to get and set the clock scale from the fat_clock_scale FAT parameter.
You can now upload the FAT FRAME_BUFFER and FRAME_DUTYCYCLE parameters to the histogram memory.
The veto commands are now "histmem veto on" and "histmem veto off".

hmm_object.tcl
The axis order for the histmem object has been restore to t,y,x

sct_positmotor_common.tcl
Code has been simplified.

nxscripts_common_1.tcl
Removed obsolete ::nexus::data function.  TOF axis now correctly report time_of_flight instead of "time".

plc_common_1.tcl
Make PLC info saveable.

scan_common_1.tcl
SICS-385 The scan command should check the final scan variable value against he soft upper and lower limits, not against the hard limits.
Make sure that the scan variable axis is saved.

platypus, kowari, quokka hmm_configuration.tcl
Use the HOR and VER entries in the new histmem_axes hash to select the horizontal and vertical axes for the histmem.

kowari motor_configuration.tcl secondary_slit_configuration.tcl
Flatten slits motor structure to match old layout in data files.

quokka commands.tcl
SICS-380 EApPosYmm -> EApPosY

quokka detector.tcl
Use new script context controller for Ordela HVPS

quokka hmm_configuration.tcl
Set detector height to 5.08*192 the same as the width

quokka motor_configuration.tcl
Code cleanup

quokka positmotor_configuration.tcl
Use new positmotor code.

quokka aperture_configuration.tcl
Added attenuation factor column to AttRotLookupTable

quokka parameters.tcl
SICS-380 Refactor nexus, remove redundant parameters.

site_ansto.c
Added the following protocols, Httpl, Protek608, aand RFAmp.

scriptcontext.c
SICS-386 SctActionHandler: set "send" string to NULL when a chain of scripts completes with state=idle.
It turns out that if none of the scripts in the "read chain" call [sct send] each time the chain is executed, then SICS will hammer the device with calls to AsconWrite(). This can be avoided if SctActionHandler sets the 'send' string to NULL before "goto finish" in the idle state. This will be safer and still let you have chains with multiple [sct send] and read scripts.

asyncprotocol.c
Fix platypus memory leak.

devser.c
SICS-387 Started adding code to pass signals on to script context drivers.

ascon.c
AsconTask(): Make sure we return to the AsconIdle state when sending a command which expect no response, also only reconnect if there is a Timeout when there has been an error.

r2888 | ffr | 2010-04-19 14:04:41 +1000 (Mon, 19 Apr 2010) | 90 lines
2012-11-15 17:00:29 +11:00

465 lines
16 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
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::bm_scan_collect {sobj uobj point} {
set vlist [split [$sobj getvarpar 0] = ];
set w(NP) $point
set sv [string trim [lindex [split [lindex $vlist 0] . ] 1]]
set header [format "%-4.4s %-9.9s %-14s %-7.7s" NP $sv Counts Time]
set varval [SplitReply [$sv]]
set counts [SplitReply [bm getcounts]]
set time [SplitReply [bm gettime]]
set data [format "%-4d %-9.3f %-14d %-7.2f" $point $varval $counts $time]
clientput $header
clientput $data
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 vlist [split [$sobj getvarpar 0] = ];
set w(NP) $point
set sv [string trim [lindex [split [lindex $vlist 0] . ] 1]]
set header [format "%-4.4s %-9.9s %-14s %-7.7s" NP $sv Counts Time]
set varval [SplitReply [$sv]]
set counts [SplitReply [::histogram_memory::total_counts]]
set time [SplitReply [::histogram_memory::time]]
set data [format "%-4d %-9.3f %-14d %-7.2f" $point $varval $counts $time]
clientput $header
clientput $data
for {set bmn 1} {$bmn <= $::counter::isc_numchannels} {incr bmn} {
set bmon bm$bmn
clientput "Monitor $bmn [SplitReply [$bmon getcounts]]"
}
}
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
}]
} 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'"
} elseif {$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 vlist [split [$sobj getvarpar 0] = ]
set scanstart [lindex $vlist 1]
set scanstep [lindex $vlist 2]
::scan::runscan_cmd -set feedback status BUSY
run_mode "hmscan"
set ::histogram_memory::histmem_axes(SVAR) [SplitReply [sicslist [::scan::runscan_cmd -set scan_variable] hdb_path] ]
::nexus::newfile $ic_hmm_datatype $save_filetype
clientput "Scan 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 [[::scan::runscan_cmd -set scan_variable]]]
# 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
set $save_filetype "data"
::histogram_memory::stop
::scan::runscan_cmd -set feedback status IDLE
run_mode "normal"
# 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"
set svar [::scan::runscan_cmd -get scan_variable]
set svtype [getatt $svar type]
if {$svtype == "motor" || $svtype == "configurablevirtualmotor"} {
drive $svar [::scan::runscan_cmd -get scan_start]
}
}
# ::histogram_memory::configure_server Filler_defaults
}
proc ::scan::bm_scan_finish {sobj uobj} {
variable reset_position
::scan::hdb_bmonscan -set feedback status IDLE
run_mode "normal"
# 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"
set svar [::scan::hdb_bmonscan -get scan_variable]
set svtype [getatt $svar type]
if {$svtype == "motor" || $svtype == "configurablevirtualmotor"} {
drive $svar [::scan::hdb_bmonscan -get scan_start]
}
}
}
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 [[::scan::hdb_bmonscan -set scan_variable]]]
::monitor::count $mode $preset
}
proc ::scan::bm_scan_prepare {sobj uobj} {
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 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 [::scan::hdb_bmonscan -set scan_variable] hdb_path] ]
::nexus::newfile BEAM_MONITOR data
#stdscan prepare $sobj $uobj;
clientput "Scan 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
VarMake ::scan::runscan_reset_position Text internal
::scan::runscan_reset_position false
#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
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"
}
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"
}
::histogram_memory::count_method $mode
::histogram_memory::count_size $preset
if {$numpoints == 1} {
set step 0
} else {
set step [expr double($stop - $start)/($numpoints - 1.0)]
}
if {$step == 0 && $numpoints > 1} {
clientput "WARNING:Scan step is zero and number of points > 1. Adjusting numpoints to one"
set numpoints 1
}
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'"
}
}
}
hmscan clear
hmscan add $scanvar $start $step
# hmscan ignores mode and preset, we use FAT_COUNT_METHOD and FAT_COUNT_STOP
::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
hmscan run $numpoints timer 0
} 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
publish runscan user
sicslist setatt runscan privilege internal