From 01890b5cff7d7b504eae75c8d4d74141691faa89 Mon Sep 17 00:00:00 2001 From: Ferdi Franceschini Date: Thu, 16 Aug 2007 15:11:07 +1000 Subject: [PATCH] Initial scratch file support Added support for aliasing data. r2117 | ffr | 2007-08-16 15:11:07 +1000 (Thu, 16 Aug 2007) | 3 lines --- .../config/nexus/nxscripts_common_1.tcl | 244 +++++++++++++----- 1 file changed, 184 insertions(+), 60 deletions(-) diff --git a/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl b/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl index 8e4ed0e0..6a9b365d 100644 --- a/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl +++ b/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl @@ -3,42 +3,76 @@ MakeNXScript sicsdatafactory new nxscript_data namespace eval nexus { variable nxdictionary + variable state set exports [list newfile closefile save data] eval namespace export $exports datafilename + + proc init {} { + variable state + variable nexusdic + array set state {file,new "true" file,open "false" file,type "data" file,format "hdf"} + set nexusdic "nexus.dic" + } + + ## \brief Create a nexus file + # + # \param filetype optional, (data,scratch) default=data + # + # Depends on ::nexus variable nexusdic and sics variable SicsDataPostFix + # preconditions: + # state(file,open) false state(file,new) true + # postconditions: + # state(file,open) true state(file,new) false + # /data/currentfiletype == /data/datatype proc createfile {} { global cfPath variable nexusdic variable state variable nxFileOpen; + if {$state(file,open) == "true"} { + error_msg "Can't create a new file because the current file is still open" + } elseif {$state(file,new) == "false"} { + error_msg "This function should only be called when state(file,new) = true" + } set nxdict_path $cfPath(nexus)/$nexusdic - set file_type [SplitReply [SicsDataSuffix]] + set file_format [SplitReply [SicsDataPostFix]] array set nxmode [list nx.hdf create5 hdf create5 h5 create5 nx5 create5 xml createxml]; - dataFileName [newFileName $file_type] ::nexus::gen_nxdict $nexusdic - nxscript $nxmode($file_type) [SplitReply [dataFileName]] $nxdict_path; + if {$state(file,type) == "scratch"} { + dataFileName [format "scratch.%s" $file_format] + } else { + sicsdatanumber incr; + dataFileName [newFileName $file_format] + } + hsetprop /data currentfiletype [::utility::hgetplainprop /data datatype] + nxscript $nxmode($file_format) [SplitReply [dataFileName]] $nxdict_path; set nxFileOpen true - set state(file,status) open + set state(file,open) false + set state(file,new) false } - ## \brief Sets 'new file' state to true - proc newfile {{type deflt } {nxdic nexus.dic}} { - variable nexusdic + ## \brief Setup file state info for writing a new file. + # + # \param type + # + # postconditions: + # state(file,open) true state(file,new) false + # /data/currentfiletype == UNKNOWN + proc newfile {{type data}} { variable state - if {$type == "deflt"} { - set type [SplitReply [SicsDataSuffix]] - } + + set state(file,type) $type set state(file,new) true - set nexusdic $nxdic + hsetprop /data currentfiletype UNKNOWN } -# Don't overwrite data from a previous SICS session - newfile proc save_data {point} { + debug_msg "save point $point in [dataFileName]" ::nexus::nxreopenfile foreach child [hlist /] { - if {[::utility::hgetplainprop /experiment data] == "true"} { + if {[::utility::hgetplainprop /$child data] == "true"} { ::nexus::savetree $child $point } } @@ -48,49 +82,77 @@ namespace eval nexus { # # \param point experimental point number, this is the array index for mutable # datasets in the nexus file. Optional, default = 0 + # \param filetype optional, (data,scratch) default=data # + # If filetype == scratch then it will create a file called scratch.{xml|hdf} # The save command will create a new file if the newfile state is set to true, or # if the datatype property != the currentfiletype property of the /data hdb node. - proc save {{point 0}} { + # arg0 '' n scratch data xml hdf + # arg1 '' scratch data xml hdf + # arg2 '' xml hdf + proc save {args} { variable state - ::data::gumtree_save -set run_number $point - if {$state(file,new) == "true"} { - createfile - save_data $point - linkdata - hsetprop /data currentfiletype [::utility::hgetplainprop /data datatype] - set state(file,new) false - } else { - if {[::utility::hgetplainprop /data currentfiletype] != [::utility::hgetplainprop /data datatype]} { - createfile - save_data $point - linkdata - hsetprop /data currentfiletype [::utility::hgetplainprop /data datatype] - set state(file,new) false + if {$args == ""} { + set point 0 + } else { + set point [lindex $args 0] } - save_data $point + if {[string is integer $point] == 0} { + error_msg "save index must be an integer" + } elseif {$point < 0} { + error_msg "save index cannot be negative" } + + ::data::gumtree_save -set run_number $point + + set isNewFile [expr {$state(file,new) == "true"}] + set currFileType [::utility::hgetplainprop /data currentfiletype] + set currDataType [::utility::hgetplainprop /data datatype] + set dataTypeChanged [expr {$currFileType != $currDataType}] + + if {$isNewFile || $dataTypeChanged} { + set state(file,new) true + ::nexus::createfile + ::nexus::save_data $point + ::nexus::linkdata + } else { + ::nexus::save_data $point + } + + return } -## \brief Reopen the current file. +## \brief Reopen the current file, close it with nxclosefile +# +# preconditions: +# none +# postconditions: +# state(file,open) == true +# \see nxclosefile proc nxreopenfile {} { global cfPath + variable state variable nxFileOpen variable nexusdic - if {$nxFileOpen == "false"} { - nxscript reopen [SplitReply [dataFileName]] $cfPath(nexus)/$nexusdic; - set nxFileOpen true; + if {$state(file,open) == "false"} { + nxscript reopen [SplitReply [dataFileName]] $cfPath(nexus)/$nexusdic + set state(file,open) true } } ## \brief Close the current file. You can reopen it with nxreopenfile # +# preconditions +# none +# postconditions +# state(file,open) == false # \see nxreopenfile proc nxclosefile {} { + variable state variable nxFileOpen; - if {$nxFileOpen == "true"} { + if {$state(file,open) == "true"} { nxscript close; - set nxFileOpen false; + set state(file,open) false; set flist [split [SplitReply [dataFileName]] "/"]; set fname [lindex $flist [expr [llength $flist] - 1] ]; clientput "$fname updated" "event"; @@ -110,40 +172,73 @@ proc nxclosefile {} { # Records that /data/axisn should be linked to datsource # data clear # Clears all link targets and sets the data type identifier to unknown +# data alias , remove alias +# data alias , set as an alias for unless it has already been defined. proc data {args} { + variable state + set dpath /data set opt [lindex $args 0] + set arglist [lrange $args 1 end] + switch $opt { "axis" { + debug_msg "'axis' case of switch" set axnum [lindex $args 1] if {[string is integer $axnum] == 0} { error "ERROR: [info level -1]->data, index for data axis should be an integer, not $axnum" } set hp $dpath/axis_$axnum if {[::utility::hgetplainprop $hp link] == "@none"} { - hsetprop $hp link [lindex $args 2] + hsetprop $hp link [getatt [lindex $args 2] id] hsetprop $hp long_name [getatt [lindex $args 2] long_name] } } "data_set" { + debug_msg "'data_set' case of switch" hsetprop $dpath datatype [lindex [info level -1] 0] set hp $dpath/data_set if {[::utility::hgetplainprop $hp link] == "@none"} { - hsetprop $hp link [lindex $args 1] + hsetprop $hp link [getatt [lindex $args 1] id] hsetprop $hp long_name [getatt [lindex $args 1] long_name] } } "clear" { + debug_msg "'clear' case of switch" foreach child [hlist $dpath] { hsetprop $dpath/$child link @none hsetprop $dpath/$child long_name @none } } + "alias" { + debug_msg "'alias' case of switch" + set alias_name [lindex $arglist 0] + set alias_target [lindex $arglist 1] + switch $alias_target { + "" { + if {[info exists state(data,alias,$alias_name)]} { + definealias $alias_name + set state(data,alias,$alias_name) @none + } + } + default { + if {[info exists state(data,alias,$alias_name)]} { + if { $state(data,alias,$alias_name) == "@none" } { + definealias $alias_name $alias_target + } + } else { + definealias $alias_name $alias_target + } + return + } + } + } default {error "ERROR: [info level -1]->data, Unsupported option $opt"} } } # Internal commands # All experimental data of interest is linked under the data group + ## \brief Links data and axis into /data group proc linkdata {} { array unset axes set hpath /data @@ -174,8 +269,9 @@ proc data {args} { } if {[info exists axes]} { foreach n [lsort [array names axes]] { - nxscript putattribute $data_set_alias axes [set axes($n)] + lappend axes_list $axes($n) } + nxscript putattribute $data_set_alias axes [join $axes_list :] } ::nexus::nxclosefile ::nexus::data clear @@ -280,7 +376,6 @@ proc data {args} { sicslist setatt nxscript_data privilege internal; # nexus macros - sicslist setatt nxcreatefile privilege internal; sicslist setatt addnxscanentry privilege internal; sicslist setatt bm_addnxscanentry privilege internal; @@ -305,6 +400,10 @@ proc data {args} { sicslist setatt $sobj savecmd ::nexus::singlecounter::save sicslist setatt $sobj sdsinfo ::nexus::singlecounter::sdsinfo } + foreach sobj [sicslist kind script] { + sicslist setatt $sobj savecmd ::nexus::script::save + sicslist setatt $sobj sdsinfo ::nexus::script::sdsinfo + } } } namespace import ::nexus::* @@ -376,7 +475,11 @@ namespace eval ::nexus { proc hdb2nx_type {dtype} { switch $dtype { int {return NX_INT32} + intar {return NX_INT32} + intvarar {return NX_INT32} float {return NX_FLOAT32} + floatar {return NX_FLOAT32} + floatvarar {return NX_FLOAT32} text {return NX_CHAR} default {error "ERROR: [info level -1]->hdb2nx_type, Unknown type $dtype"} } @@ -385,6 +488,7 @@ namespace eval ::nexus { namespace eval ::nexus::sicsvariable { proc save {svar nxalias data_type args} { + array set attribute [attlist $svar] set val [SplitReply [$svar]] if {[lindex $args 0] == "point"} { set index [lindex $args 1] @@ -403,6 +507,9 @@ namespace eval ::nexus::sicsvariable { default {error "ERROR: [info level -1]->::nexus::sicsvariable::save, unknown type $data_type"} } } + if {[info exists attribute(units)]} { + nxscript putattribute $nxalias units $attribute(units) + } } proc sdsinfo {svar data_type args} { array set param $args @@ -422,6 +529,34 @@ namespace eval ::nexus::singlecounter { todo_msg "Get sdsinfo for counter: $counter" } } + +namespace eval ::nexus::script { +##\brief Save command for hdb nodes associated with a tcl macro +# +# The macro must return a 1D associative array when called with -arrayname. + proc save {script nxalias data_type args} { + array set attribute [attlist $script] + set darray [$script -arrayname] + set size [array size $darray] + switch $data_type { + "intar" - "intvarar" { + nxscript putintarray $nxalias $darray $size + } + "floatar" - "floatvarar" { + nxscript putarray $nxalias $darray $size + } + } + if {[info exists attribute(units)]} { + nxscript putattribute $nxalias units $attribute(units) + } + } + proc sdsinfo {script data_type args} { + set dtype [::nexus::hdb2nx_type $data_type] + set darray [$script -arrayname] + set size [array size $darray] + return " -type $dtype -rank 1 -dim {$size}" + } +} # TODO Return filename from nxcreatefile and call nxreopen nxclose etc # TODO Make an nxscript namespace for all this. @@ -433,7 +568,7 @@ namespace eval ::nexus::singlecounter { set tmpstr [string map {"$" ""} {$Name: not supported by cvs2svn $}] set nx_content_release_tag [lindex $tmpstr [expr [llength $tmpstr] - 1]] -set tmpstr [string map {"$" ""} {$Revision: 1.25 $}] +set tmpstr [string map {"$" ""} {$Revision: 1.26 $}] set nx_content_revision_num [lindex $tmpstr [expr [llength $tmpstr] - 1]] @@ -442,27 +577,17 @@ proc getVal {msg} { } proc newFileName {postfix} { -array set inst_mnem {quokka QKK womba WBT echidna ECH kowari KWR koala KOL taipan TPN platypus PLP pelican PLN} - - sicsdatanumber incr; + array set inst_mnem {quokka QKK wombat WBT echidna ECH kowari KWR koala KOL taipan TPN platypus PLP pelican PLN} +# sicsdatanumber incr; set idNum [SplitReply [sicsdatanumber]]; set dataPath [SplitReply [sicsdatapath]]; set prefix [SplitReply [sicsdataprefix]]; set date_time_arr [split [sicstime] " "] - set isodate [lindex $date_time_arr 0]; + set isodate [lindex $date_time_arr 0]; set isotime [string map {: -} [lindex $date_time_arr 1]]; return [format "%s/%s%07d.%s" $dataPath $inst_mnem([instname]) $idNum $postfix] } -proc nxcreatefile {nxdic {type nx.hdf}} { - global nxFileOpen cfPath nexusdic; - - set nexusdic $nxdic - array set nxmode [list nx.hdf create5 h5 create5 nx5 create5 xml createxml]; - dataFileName [newFileName $type] - nxscript $nxmode($type) [SplitReply [dataFileName]] $cfPath(nexus)/$nexusdic; - set nxFileOpen true -} set dradius 1.25 @@ -702,19 +827,18 @@ proc putslitmotors {nxobj point} { namespace eval data { command gumtree_save {int: run_number} { - save $run_number + ::nexus::save $run_number } sicslist setatt ::data::gumtree_save long_name save array set param [::data::gumtree_save -list param] ::utility::mkData $param(run_number) run_number instrument privilege READ_ONLY mutable true control false command gumtree_type {text:nx.hdf,xml type} { - SicsDataSuffix $type + SicsDataPostFix $type } - sicslist set ::data::gumtree_type long_name file_type - ::data::gumtree_type -set type [SplitReply [SicsDataSuffix]] + sicslist set ::data::gumtree_type long_name file_format + ::data::gumtree_type -set type [SplitReply [SicsDataPostFix]] } -Publish nxcreatefile user Publish addnxscanentry user Publish bm_addnxscanentry user - +::nexus::init