## TODO Put all the nexus macros in the nexus namespace 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_format [SplitReply [SicsDataPostFix]] array set nxmode [list nx.hdf create5 hdf create5 h5 create5 nx5 create5 xml createxml]; ::nexus::gen_nxdict $nexusdic 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,open) false set state(file,new) false } ## \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 set state(file,type) $type set state(file,new) true hsetprop /data currentfiletype UNKNOWN } proc save_data {point} { debug_msg "save point $point in [dataFileName]" ::nexus::nxreopenfile foreach child [hlist /] { if {[::utility::hgetplainprop /$child data] == "true"} { ::nexus::savetree $child $point } } ::nexus::nxclosefile } ## \brief save data collected by last data acquisition command. # # \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. # arg0 '' n scratch data xml hdf # arg1 '' scratch data xml hdf # arg2 '' xml hdf proc save {args} { variable state if {$args == ""} { set point 0 } else { set point [lindex $args 0] } 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, close it with nxclosefile # # preconditions: # none # postconditions: # state(file,open) == true # \see nxclosefile proc nxreopenfile {} { global cfPath variable state variable nxFileOpen variable nexusdic 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 {$state(file,open) == "true"} { nxscript close; set state(file,open) false; set flist [split [SplitReply [dataFileName]] "/"]; set fname [lindex $flist [expr [llength $flist] - 1] ]; clientput "$fname updated" "event"; } } ## \brief Records that a given data source should be linked to nexus data target. # # NOTE: If a link has already been recorded then it does nothing. This allows you to # override default links set by a command. eg A "count" command may link axis_1 to # the run number but a "scan" command which uses the count command can link axis_1 to # a scan variable. # # Usage: # data data_set datsource # Records that /data/data_set should be linked to datsource and sets a data type identifier # data axis 1|2|3|4 datsource # 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 [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 [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 ::nexus::nxreopenfile foreach child [hlist $hpath] { array set p_arr [::utility::hlistplainprop $hpath/$child] if {$p_arr(data) == true && $p_arr(nxsave) == true} { if {[info exists p_arr(nxalias)]} { if {[info exists p_arr(type)] && $p_arr(type) == "nxvgroup"} { if {$p_arr(link) != "@none"} { nxscript makelink $p_arr(nxalias) $p_arr(link) switch -glob $child { "axis_*" { set n [lindex [split $child _] 1] set axes($n) [::utility::hgetplainprop $hpath/$child long_name] nxscript putattribute $p_arr(link) axis $n } "data_set" { nxscript putattribute $p_arr(link) signal 1 set data_set_alias $p_arr(link) } default {error "ERROR: [info level -1]->linkdata, Unsupported data path $hpath/$child"} } } } } } } if {[info exists axes]} { foreach n [lsort [array names axes]] { lappend axes_list $axes($n) } nxscript putattribute $data_set_alias axes [join $axes_list :] } ::nexus::nxclosefile ::nexus::data clear } proc savetree {hpath {pt 0}} { foreach child [hlist /$hpath] { array unset p_arr array set p_arr [::utility::hlistplainprop /$hpath/$child] if {[info exists p_arr(type)] && $p_arr(type) == "nxvgroup"} { return } set data_type [lindex [split [hinfo /$hpath/$child] , ] 0] if {$p_arr(data) == true && $p_arr(nxsave) == true } { if {[info exists p_arr(savecmd)] && [info exists p_arr(nxalias)] } { if {[info exists p_arr(mutable)] && $p_arr(mutable) == "true" } { $p_arr(savecmd) $p_arr(sicsdev) $p_arr(nxalias) $data_type point $pt } else { $p_arr(savecmd) $p_arr(sicsdev) $p_arr(nxalias) $data_type } } elseif {[info exists p_arr(savecmd)] || [info exists p_arr(nxalias)]} { error_msg "/$hpath/$child must have both 'savecmd' and 'nxalias' properties\nThe actual property list for /$hpath/$child is [array get p_arr]" } ::nexus::savetree $hpath/$child $pt } } } # Where do we get the SDS info from for tcl variables? proc save_scalar {args} { todo_msg "Save floats ints, use this for local variables, events and sicsvariable data" # use putfloat $event(...) or uset putslab } proc save_sicsvar {svar nxarg args} { todo_msg "Use this to save tcl arrays, good for beam monitor count arrays" } proc _gen_nxdict {hpath dict_path name nxc} { variable nxdictionary if {[::utility::hgetplainprop /$hpath data] == "false"} { debug_msg "$hpath doesn't have a data property" return } foreach child [hlist /$hpath] { if {[::utility::hgetplainprop /$hpath/$child data] == true} { set nxclass [::utility::hgetplainprop /$hpath/$child klass] if {[string range $nxc 0 1] == "NX"} { ::nexus::_gen_nxdict $hpath/$child $dict_path/$name,$nxc $child $nxclass } else { # else construct SDS name by replacing '/' with '_' in path ::nexus::_gen_nxdict $hpath/$child $dict_path ${name}_$child $nxclass } } } array set p_arr [::utility::hlistplainprop /$hpath] set data_type [lindex [split [hinfo /$hpath] , ] 0] if {$p_arr(data) == "true" && $p_arr(nxsave) == "true" && [info exists p_arr(nxalias)]} { set alias $p_arr(nxalias) if {[info exists p_arr(sdsinfo)]} { if {[info exists p_arr(mutable)] && $p_arr(mutable) == "true"} { set nxdictionary($alias) "$dict_path/SDS $name [$p_arr(sdsinfo) $p_arr(sicsdev) $data_type mutable true]" } else { set nxdictionary($alias) "$dict_path/SDS $name [$p_arr(sdsinfo) $p_arr(sicsdev) $data_type mutable false]" } } elseif {[info exists p_arr(type)] && $p_arr(type) == "nxvgroup"} { set nxdictionary($alias) "$dict_path/NXVGROUP" } } } proc gen_nxdict {nexusdic} { global cfPath variable nxdictionary set nxdict_path $cfPath(nexus)/$nexusdic array unset nxdictionary foreach hp [hlist /] { if {[::utility::hgetplainprop /$hp data] == true} { set nxclass [::utility::hgetplainprop /$hp klass] ::nexus::_gen_nxdict $hp /entry1,NXentry $hp $nxclass } } set fh [open $nxdict_path w] puts $fh "##NXDICT-1.0" puts $fh padim0=0 puts $fh padim1=0 puts $fh padim2=0 foreach {n v} [array get nxdictionary] { puts $fh "$n = $v" } close $fh } proc show_nxdict {} { variable nxdictionary clientput [array get nxdictionary] } proc set_sobj_attributes {} { # SICS commands sicslist setatt nxscript privilege internal; # SICS data objects sicslist setatt nxscript_data privilege internal; # nexus macros sicslist setatt addnxscanentry privilege internal; sicslist setatt bm_addnxscanentry privilege internal; # Set savecmd on SICS objects foreach sobj [lrange [sicslist type motor] 1 end] { sicslist setatt $sobj savecmd ::nexus::motor::save sicslist setatt $sobj sdsinfo ::nexus::motor::sdsinfo } foreach sobj [sicslist type configurablevirtualmotor] { sicslist setatt $sobj savecmd ::nexus::motor::save sicslist setatt $sobj sdsinfo ::nexus::motor::sdsinfo } foreach sobj [sicslist type histmem] { sicslist setatt $sobj savecmd ::nexus::histmem::save sicslist setatt $sobj sdsinfo ::nexus::histmem::sdsinfo } foreach sobj [sicslist type sicsvariable] { sicslist setatt $sobj savecmd ::nexus::sicsvariable::save sicslist setatt $sobj sdsinfo ::nexus::sicsvariable::sdsinfo } foreach sobj [sicslist type singlecounter] { 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::* foreach expt $::nexus::exports { publish $expt user sicslist setatt $expt privilege internal } namespace eval ::nexus::histmem { proc save {hm nxalias data_type args} { set dim0 [SplitReply [$hm configure dim0]] set dim1 [SplitReply [$hm configure dim1]] set dim2 [SplitReply [$hm configure dim2]] nxscript updatedictvar padim0 $dim0 nxscript updatedictvar padim1 $dim1 nxscript updatedictvar padim2 $dim2 set data_start 0 set datalen [expr {$dim0 * $dim1 * $dim2}] set bank 0 if {[lindex $args 0] == "point"} { set index [lindex $args 1] nxscript putslab $nxalias [list $index 0 0 0] [list 1 $dim0 $dim1 $dim2] $hm $data_start $datalen $bank } else { } } proc sdsinfo {hm data_type args} { array set param $args array set hm_prop [attlist $hm] if {$param(mutable) == true} { return " -type NX_INT32 -LZW -rank 4 -dim {-1,\$(padim0),\$(padim1),\$(padim2)}" } else { return " -type NX_INT32 -LZW -rank 3 -dim {\$(padim0),\$(padim1),\$(padim2)}" } } } namespace eval ::nexus::motor { # The save commands are called with the sobj name and nxalias # The sdsinfo commands provide the SDS description for an nxdic # save sphi alias float [point n] proc save {motor nxalias data_type args} { if {[lindex $args 0] == "point"} { set index [lindex $args 1] nxscript_data clear; nxscript_data putfloat 0 [getVal [$motor] ] nxscript putslab $nxalias [list $index] [list 1] nxscript_data } else { if {[getatt $motor type] == "motor"} { nxscript putmot $nxalias $motor } else { nxscript putfloat $nxalias [SplitReply [$motor]] } } } proc sdsinfo {motor data_type args} { array set param $args array set mot_prop [attlist $motor] set dtype [::nexus::hdb2nx_type $data_type] if {$param(mutable) == true} { return " -type $dtype -rank 1 -dim {-1} -attr {units,$mot_prop(units)} -attr {long_name,$mot_prop(long_name)}" } else { return " -type $dtype -attr {units,$mot_prop(units)} -attr {long_name,$mot_prop(long_name)}" } } } namespace eval ::nexus::evcontroller { # The save commands are called with the sobj name and nxalias # The sdsinfo commands provide the SDS description for an nxdic # save sphi alias float [point n] proc save {evc nxalias data_type args} { if {[lindex $args 0] == "point"} { set index [lindex $args 1] nxscript_data clear; nxscript_data putfloat 0 [getVal [$evc] ] nxscript putslab $nxalias [list $index] [list 1] nxscript_data } else { nxscript putfloat $nxalias [SplitReply [$evc]] } } proc sdsinfo {evc data_type args} { array set param $args array set evc_prop [attlist $evc] set dtype [::nexus::hdb2nx_type $data_type] if {$param(mutable) == true} { return " -type $dtype -rank 1 -dim {-1} -attr {units,$evc_prop(units)} -attr {long_name,$evc_prop(long_name)}" } else { return " -type $dtype -attr {units,$evc_prop(units)} -attr {long_name,$evc_prop(long_name)}" } } } 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"} } } } 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] nxscript_data clear; switch $data_type { int {nxscript_data putint 0 $val} float {nxscript_data putfloat 0 $val} default {error "ERROR: [info level -1]->::nexus::sicsvariable::save, unknown type $data_type"} } nxscript putslab $nxalias [list $index] [list 1] nxscript_data } else { switch $data_type { int {nxscript putint $nxalias $val} float {nxscript putfloat $nxalias $val} text {nxscript puttext $nxalias $val} 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 set dtype [::nexus::hdb2nx_type $data_type] if {$param(mutable) == true} { return " -type $dtype -rank 1 -dim {-1}" } else { return " -type $dtype" } } } namespace eval ::nexus::singlecounter { proc save {counter nxalias data_type args} { todo_msg "Save counter: $counter" } proc sdsinfo {counter data_type args} { 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. # dictalias is a global hash which records the alias which the value of # a sics object (eg motors) is written to. The has is indexed by the # objects name. It is useful for making links to datasets. # dim0 = vertical axis on detector # dim1 = horizontal axis on detector 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.28 $}] set nx_content_revision_num [lindex $tmpstr [expr [llength $tmpstr] - 1]] proc getVal {msg} { return [string trim [lindex [split $msg =] 1 ] ] } proc newFileName {postfix} { 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 isotime [string map {: -} [lindex $date_time_arr 1]]; return [format "%s/%s%07d.%s" $dataPath $inst_mnem([instname]) $idNum $postfix] } set dradius 1.25 set ndect 128 set tubedia 0.0254 set pi 3.1415926 set angsep 1.25 # stthmin = (180 - (1.25*127))/2 proc hmm_save {nxobj entryname point} { global dradius ndect angsep dictalias; set dictalias(hmm) hmcounts # dim0 is vertical and dim1 is horizontal set dim0 [SplitReply [hmm configure dim0]]; set dim1 [SplitReply [hmm configure dim1]]; putcommon $nxobj $entryname $point; putcrystal $nxobj; putmonitor $nxobj $point; putsample $nxobj; $nxobj putattribute program_name hmm_mode [SplitReply [hmm_mode]] $nxobj putfloat detangle_degrees [SplitReply [detector_angle_deg]] $nxobj putfloat dheight [SplitReply [detector_active_height_mm]] put_det_haxis_arr $nxobj $dim1; put_det_vaxis_arr $nxobj $dim0; $nxobj puttext dtype [SplitReply [detector_type]] $nxobj puttext ddesc [SplitReply [detector_description]] $nxobj putfloat dradius [SplitReply [detector_radius_mm]] $nxobj puttext dlayout [SplitReply [detector_layout]] set histo_length [SplitReply [hmm_length]] $nxobj updatedictvar padim0 $dim0 $nxobj updatedictvar padim1 $dim1 $nxobj putslab $dictalias(hmm) [list $point 0 0] [list 1 $dim0 $dim1 ] hmm [SplitReply [hmm_start]] $histo_length [SplitReply [hmm_bank]] put_polar_angle $nxobj $point $dim0 $dim1; #TODO replace scandata with generic name $nxobj makelink scandata hmcounts $nxobj makelink scanhoraxis [SplitReply [_hmm_hor_axis_alias]] $nxobj makelink scanvertaxis [SplitReply [_hmm_vert_axis_alias]] $nxobj putattribute [SplitReply [_hmm_vert_axis_alias]] axis 2; $nxobj putattribute [SplitReply [_hmm_hor_axis_alias]] axis 3; } proc hmm_addnxscanentry {nxobj entryname point scanVariable scanVarPos scanVarStep start_time} { global dictalias; set hor_axis [SplitReply [_hmm_hor_axis]] set vert_axis [SplitReply [_hmm_vert_axis]] $nxobj puttext estart $start_time; $nxobj putattribute program_name run_mode hmscan nxscript_data clear; nxscript_data putint 0 $point; $nxobj putslab erun [list $point] [list 1] nxscript_data; hmm_save $nxobj $entryname $point; fillPath $nxobj $scanVariable; $nxobj makelink scanvar $dictalias($scanVariable); $nxobj putattribute $dictalias($scanVariable) axis 1; $nxobj putattribute hmcounts signal 1; $nxobj putattribute hmcounts axes $scanVariable:$vert_axis:$hor_axis; $nxobj puttext eend [sicstime]; } proc bm_save {nxobj entryname point} { global dradius ndect angsep; # $nxobj updatedictvar scan_variable $scanVariable; putcommon $nxobj $entryname $point putcrystal $nxobj putmonitor $nxobj $point putsample $nxobj $nxobj puttext dlayout point #TODO replace scandata with generic name $nxobj makelink scandata bmcounts } proc bm_addnxscanentry {nxobj entryname point scanVariable scanVarPos scanVarStep start_time} { global dictalias; $nxobj puttext estart $start_time; $nxobj putattribute program_name run_mode bmonscan nxscript_data clear; nxscript_data putint 0 $point; $nxobj putslab erun [list $point] [list 1] nxscript_data; bm_save $nxobj $entryname $point; fillPath $nxobj $scanVariable; $nxobj makelink scanvar $dictalias($scanVariable); $nxobj putattribute $dictalias($scanVariable) axis 1; $nxobj putattribute bmcounts signal 1; $nxobj putattribute bmcounts axes $scanVariable; #TODO add dtype ddesc $nxobj puttext eend [sicstime]; } proc putmonitor {nxobj point} { $nxobj puttext mmode [string trim [lindex [split [bm getmode] =] 1]] $nxobj putfloat mpreset [string trim [lindex [split [bm getpreset] =] 1]] # $nxobj putint mdata [string trim [lindex [split [bm getcounts] =] 1]] nxscript_data clear nxscript_data putfloat 0 [SplitReply [bm getcounts]] $nxobj putslab bmcounts [list $point] [list 1] nxscript_data $nxobj putfloat mdistance [SplitReply [bmon_distance]] } proc put_det_haxis_arr {nxobj dim1} { set det_radius_mm [SplitReply [detector_radius_mm]] set det_angle_rad [SplitReply [detector_angle_rad]] set angsep [expr $det_angle_rad / ($dim1-1)] for {set i 0} {$i < $dim1} {incr i} { set col_index($i) [expr int($i)] set xpixel_offset($i) [expr $i*$angsep*$det_radius_mm] } $nxobj putarray dhaxis xpixel_offset $dim1; $nxobj updatedictvar column_index_name [SplitReply [_hmm_hor_channel_name]] $nxobj putintarray dcolindex col_index $dim1; } proc put_det_vaxis_arr {nxobj dim0} { set det_active_height_mm [SplitReply [detector_active_height_mm]] set hsep [expr $det_active_height_mm/($dim0-1)] set det_zero_row [SplitReply [detector_zero_row] ] set det_last_vert_pixel [SplitReply [detector_last_vert_pixel]] set row_zero [expr ($dim0 - 1.0)*$det_zero_row/$det_last_vert_pixel] for {set i 0} {$i < $dim0} {incr i} { set row_index($i) [expr int($i)] set ypixel [expr $det_active_height_mm - ($i+$row_zero)*$hsep] set det_ypixel_offset($i) $ypixel } $nxobj putarray dvaxis det_ypixel_offset $dim0 $nxobj updatedictvar row_index_name vertical_channel_number $nxobj putintarray drowindex row_index $dim0; } proc putsample {nxobj} { $nxobj puttext saname [getVal [Sample]] } proc putcrystal {nxobj} { $nxobj puttext ctype [SplitReply [crystal_type]] $nxobj putfloat clambda [SplitReply [crystal_wavelength_A]] } proc putcommon {nxobj entryName point} { global nx_content_release_tag nx_content_revision_num; $nxobj updatedictvar entryName $entryName $nxobj puttext program_name SICS $nxobj putattribute program_name sics_release [SplitReply [sics_release]] $nxobj putattribute program_name sics_revision [SplitReply [sics_revision_num]] $nxobj putattribute program_name nx_content_release $nx_content_release_tag $nxobj putattribute program_name nx_content_revision $nx_content_revision_num $nxobj puttext etitle [getVal [Title]] $nxobj puttext iname [getVal [Instrument]] $nxobj puttext username [SplitReply [user]] $nxobj puttext useremail [SplitReply [email]] $nxobj puttext userphone [SplitReply [phone]] # NXsource $nxobj puttext sname OPAL $nxobj puttext stype Reactor Neutron Source $nxobj puttext sprobe Neutron putsamplemotors $nxobj $point putslitmotors $nxobj $point putmonomotors $nxobj $point } # This should be called before making a link to a dataset # via a value in the dictalias hash. proc fillPath {nxobj sobj} { set otype [SplitReply [sicslist $sobj type]]; if {$otype == "Motor"} { fillMotPath $nxobj $sobj; } } proc fillMotPath {nxobj motor} { $nxobj updatedictvar mot_name $motor; $nxobj updatedictvar mot_long_name [SplitReply [$motor long_name]]; $nxobj updatedictvar mot_units [SplitReply [$motor units]]; } proc putsamplemotors {nxobj point} { global dictalias; foreach motor { som schi sphi sx sy stth } { fillMotPath $nxobj $motor; set dictalias($motor) nxsample_mot nxscript_data clear; nxscript_data putfloat 0 [getVal [$motor] ]; $nxobj putslab $dictalias($motor) [list $point] [list 1] nxscript_data; } # sth is a virtual motor nxscript_data clear nxscript_data putfloat 0 [getVal [sth ]] set dictalias(sth) sth $nxobj putslab $dictalias(sth) [list $point] [list 1] nxscript_data; } proc putmonomotors {nxobj point} { global dictalias; set instrument [SplitReply [instrument]] if {$instrument == "echidna"} { set extra_mots [list pcx pcr] } elseif {$instrument == "wombat"} { set extra_mots [list oct mf2] } foreach motor " mom mchi mphi mx my mtth $extra_mots" { fillMotPath $nxobj $motor; set dictalias($motor) nxcrystal_mot nxscript_data clear nxscript_data putfloat 0 [getVal [$motor] ] $nxobj putslab $dictalias($motor) [list $point] [list 1] nxscript_data; } # mth is a virtual motor nxscript_data clear nxscript_data putfloat 0 [getVal [mth ]] set dictalias(mth) mth $nxobj putslab $dictalias(mth) [list $point] [list 1] nxscript_data; } proc putslitmotors {nxobj point} { global dictalias; foreach motor {ss1u ss1d ss1l ss1r ss2u ss2d ss2l ss2r } { fillMotPath $nxobj $motor; set dictalias($motor) nxfilter_mot nxscript_data clear nxscript_data putfloat 0 [getVal [$motor] ] $nxobj putslab $dictalias($motor) [list $point] [list 1] nxscript_data; } foreach motor {ss1vg ss1vo ss1hg ss1ho ss2vg ss2vo ss2hg ss2ho } { set dictalias($motor) $motor nxscript_data clear nxscript_data putfloat 0 [getVal [$motor] ] $nxobj putslab $dictalias($motor) [list $point] [list 1] nxscript_data; } } namespace eval data { command gumtree_save {int: 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} { SicsDataPostFix $type } sicslist set ::data::gumtree_type long_name file_format ::data::gumtree_type -set type [SplitReply [SicsDataPostFix]] } Publish addnxscanentry user Publish bm_addnxscanentry user ::nexus::init