## \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. # ::scan::reset_position true/false, drive motor back to start position at end of scan #TODO Get rid of duplication in bmonscan and hmscan code MakeScanCommand hmscan bm $cfPath(scan)/scan_common_1.hdd recover.bin MakeScanCommand bmonscan bm $cfPath(scan)/scan_common_1.hdd recover.bin MakeScanCommand scan2 bm $cfPath(scan)/scan_common_1.hdd recover.bin namespace eval scan { variable event; # List of counts variable bmoncounts_array variable bmoncounts_axis variable save_filetype variable reset_position set save_filetype "data" set reset_position "false" variable bmonscanvar_axis_hpath # hpath to values from bmoncounts_array # we use this to get auto-notification on update of bmonscancounts_array_hpath variable bmonscancounts_array_hpath variable scanVariable scan_var scanVarStart 0 scanVarStep 1 proc scan_collect {sobj uobj point} { } ## \brief Aborts scan if a scan variable target position exeeds the limits. proc 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 "ERROR Scan aborted. 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 "ERROR Scan aborted. Final position of $target violates $limit_name $limit for $scan_variable" } } default { error_msg "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 check_scanvar {sobj uobj} { 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] != "configurablevirtualmotor"} { if {[SplitReply [$scan_variable fixed]] >= 0} { return -code error "Scan aborted. $scan_variable position is set to 'fixed'" } set target [expr $scan_start + $NP * $scan_increment] ::scan::check_limit $scan_variable hardlowerlim $target ::scan::check_limit $scan_variable hardupperlim $target ::scan::check_limit $scan_variable softlowerlim $target ::scan::check_limit $scan_variable softupperlim $target } } proc hmm_scan_prepare {sobj uobj} { variable scan_pt_start_time ::scan::check_scanvar $sobj $uobj # stdscan prepare $sobj $uobj; ::scan::hdb_hmscan -set NP [SplitReply [$sobj np]] set vlist [split [$sobj getvarpar 0] = ]; ::scan::hdb_hmscan -set scan_variable [string trim [lindex [split [lindex $vlist 0] . ] 1]] ::scan::hdb_hmscan -set scan_start [lindex $vlist 1]; ::scan::hdb_hmscan -set scan_increment [lindex $vlist 2]; set scan_pt_start_time [sicstime] #FIXME remove dependency on hdb path ::scan::hdb_hmscan -set feedback status BUSY ::histogram_memory::prepare data axis 1 [::scan::hdb_hmscan -set scan_variable] ::hdb::set_save / true ::nexus::newfile data } proc hmm_count {sobj uobj point mode preset} { ::scan::hdb_hmscan -set mode $mode ::scan::hdb_hmscan -set preset $preset; ::scan::hdb_hmscan -set feedback scanpoint $point ::scan::hdb_hmscan -set feedback mode $mode; ::scan::hdb_hmscan -set feedback preset $preset; ::scan::hdb_hmscan -set feedback scan_variable_value [SplitReply [[::scan::hdb_hmscan -set scan_variable]]] ::histogram_memory::count_bm_controlled $mode $preset; } proc hmm_scan_finish {sobj uobj} { variable save_filetype variable reset_position set $save_filetype "data" ::histogram_memory::finish; ::scan::hdb_hmscan -set feedback status IDLE # Make sure that the next save command doesn't overwrite our scan data. # and clear any data links ::nexus::newfile data ::nexus::data clear if {$reset_position == "true"} { set svar [::scan::hdb_hmscan -get scan_variable] set svtype [getatt $svar type] if {$svtype == "motor" || $svtype == "configurablevirtualmotor"} { drive $svar [::scan::hdb_hmscan -get scan_start] } set reset_position "false" } ::histogram_memory::configure_server Filler_defaults } proc bm_scan_finish {sobj uobj} { variable reset_position ::scan::hdb_bmonscan -set feedback status IDLE # Make sure that the next save command doesn't overwrite our scan data. # and clear any data links ::nexus::newfile data ::nexus::data clear if {$reset_position == "true"} { 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] } set reset_position "false" } } #proc hmm_scan_finish {sobj uobj} { # nxclosefile; #} # Add an nxentry for the current scan point #TODO Is this obsolete? proc write_nxentry {nxentryCmd point} { variable scanVarStart; variable scanVarStep; variable scanVariable; variable scan_pt_start_time; set scanVarPos [expr {$scanVarStart + $point * $scanVarStep} ]; save $point # nxreopenfile; # $nxentryCmd nxscript scan_[format "%05d" $point] $scanVariable $scanVarPos $scanVarStep $scan_pt_start_time; # $nxentryCmd nxscript entry1 $point $scanVariable $scanVarPos $scanVarStep $scan_pt_start_time; # nxclosefile; } proc bm_writepoint {sobj uobj pt} { variable bmoncounts_array set bmoncounts_array [string map {\{ "" \} ""} [SplitReply [bmonscan getcounts]]]; ::nexus::save $pt ::scan::hdb_bmonscan -set feedback counts [SplitReply [bm getcounts]]; } #TODO Feedback for Histogram memory scan proc hmm_writepoint {sobj uobj pt} { variable save_filetype # Write hdb tree ::nexus::save $pt } proc donothing {args} {} proc bm_count {sobj uobj point mode preset} { variable event; ::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 bm_scan_prepare {sobj uobj} { variable event; variable bmoncounts_array; variable bmoncounts_axis; variable scan_pt_start_time set bmoncounts_array [list] #TODO Parameterise varindex in some way set varindex 0; ::scan::hdb_bmonscan -set feedback filename [SplitReply [dataFileName]] ::scan::hdb_bmonscan -set NP [SplitReply [$sobj np]]; # set event(hdb_bmonscan/graphics,dim) [::scan::hdb_bmonscan -set NP] set vlist [split [$sobj getvarpar $varindex] = ]; ::scan::hdb_bmonscan -set scan_variable [string trim [lindex [split [lindex $vlist 0] . ] 1]]; ::scan::hdb_bmonscan -set scan_start [lindex $vlist 1]; ::scan::hdb_bmonscan -set scan_increment [lindex $vlist 2]; set scanvar_pts [SplitReply [$sobj getvardata $varindex]] set bmoncounts_axis [string map {\{ "" \} ""} $scanvar_pts] todo_msg "SET START TIME set event(hdb_bmonscan,scan_pt_start_time) [sicstime]" ::scan::hdb_bmonscan -set feedback status BUSY #FIXME remove dependency on hdb path array set bm_fb [::scan::hdb_bmonscan -list feedback] data axis 1 [::scan::hdb_bmonscan -set scan_variable] ::hdb::set_save / true ::hdb::set_save /instrument/detector false ::nexus::newfile data #stdscan prepare $sobj $uobj; } # group=beam_monitor_scan proc hdb_bmonscan_graphics {process args} { set eid hdb_bmonscan/graphics $process $args path beam_monitor_scan prop_list {data false control true nxsave false klass @none type graphdata viewer default rank 1} $process $args kind event node beam_monitor_scan/dim dtype int priv user eventid $eid; $process $args kind event node beam_monitor_scan/point dtype int priv user eventid $eid; $process $args kind event node beam_monitor_scan/lastaxis dtype float priv user eventid $eid; $process $args kind event node beam_monitor_scan/lastdata dtype int priv user eventid $eid; $process $args kind script node beam_monitor_scan/axis dtype floatvarar dlen 100 priv user rscript "set ::scan::bmoncounts_axis" wscript hdbReadOnly prop_list {type axis} $process $args kind script node beam_monitor_scan/data dtype floatvarar dlen 100 priv user rscript "set ::scan::bmoncounts_array" wscript hdbReadOnly prop_list {type data} } } Publish ::scan::scan_collect user Publish ::scan::write_nxentry user Publish ::scan::hmm_count user Publish ::scan::hmm_scan_prepare user Publish ::scan::hmm_scan_finish 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_writepoint user Publish ::scan::bm_count user bmonscan configure script bmonscan function writeheader ::scan::donothing bmonscan function writepoint ::scan::bm_writepoint bmonscan function count ::scan::bm_count #bmonscan function collect ::scan::scan_collect bmonscan function prepare ::scan::bm_scan_prepare bmonscan function finish ::scan::bm_scan_finish #scan2 function writeheader ::scan::donothing #scan2 function writepoint ::scan::nxaddpoint #scan2 function prepare ::scan::hmm_scan_prepare # Configure script mode, then we can configure all the scan callbacks. # The scan list command can be used to check that the callbacks # are properly defined. # A different count callback is defined in the two cases. # scan2 configure script #scan2 function prepare ::histogram_memory::prepare scan2 function count ::histogram_memory::hs_count_hs_controlled #scan2 function collect ::histogram_memory::hs_collect scan2 function finish ::histogram_memory::hs_finish # # That's all, folks... hmscan configure script #hmscan function prepare hdbprepare #hmscan function collect hdbcollect hmscan function writeheader ::scan::donothing hmscan function writepoint ::scan::hmm_writepoint hmscan function count ::scan::hmm_count #hmscan function collect ::scan::scan_collect hmscan function prepare ::scan::hmm_scan_prepare hmscan function finish ::scan::hmm_scan_finish namespace eval scan { command hdb_bmonscan { text:drivable scan_variable float: scan_start float: scan_increment int: NP text:monitor,timer mode float: preset int:0,2 channel} { bmonscan clear # bmonscan configure script bmonscan add $scan_variable $scan_start $scan_increment bmonscan setchannel $channel; set status [catch {bmonscan run $NP $mode $preset} msg] # bmonscan configure soft if {$status == 0} { return $msg } else { return -code error "ERROR [info level 0]" } } ::scan::hdb_bmonscan -addfb text filename text mode float preset float scan_variable_value int scanpoint int counts text status ::scan::hdb_bmonscan -set feedback status IDLE command hdb_hmscan { text:drivable scan_variable float: scan_start float: scan_increment int: NP text:monitor,timer mode float: preset int:0,2 channel} { hmscan clear hmscan add $scan_variable $scan_start $scan_increment hmscan setchannel $channel; set status [catch {hmscan run $NP $mode $preset} msg] if {$status == 0} { return $msg } else { return -code error "ERROR [info level 0]" } } ::scan::hdb_hmscan -addfb text filename text mode float preset float scan_variable_value int scanpoint int counts text status ::scan::hdb_hmscan -set feedback status IDLE } publish ::scan::hdb_bmonscan_graphics user sicslist setatt ::scan::hdb_bmonscan long_name bmonscan sicslist setatt ::scan::hdb_hmscan long_name hmscan