355 lines
10 KiB
Tcl
355 lines
10 KiB
Tcl
#----------------------------------------------------------------------------
|
|
# fcircle is a collection of SICS-Tcl macro scripts which help with
|
|
# the running of a four circle diffractometer. The central idea is
|
|
# a data base file which can be manipulated both from SICS and from
|
|
# external programs. The name of this database file is expected to live in
|
|
# the SICS variable dbfile.
|
|
#
|
|
# Mark Koennecke, November 1999
|
|
#---------------------------------------------------------------------------
|
|
|
|
|
|
#----------- fcircleinit
|
|
# fcircleinit must be called from the SICS initialization script and will
|
|
# then install all necessary variables and the commands defined by this
|
|
# script into SICS.
|
|
|
|
proc fcircleinit {} {
|
|
VarMake dbfile Text User
|
|
Publish writepos User
|
|
Publish writerefl User
|
|
Publish clearrefl User
|
|
Publish listrefl User
|
|
Publish updateub User
|
|
Publish setlambda User
|
|
Publish fcentre User
|
|
}
|
|
|
|
#------------fsplit
|
|
# returns the answer part of a SICS reply of the form something = something
|
|
proc fsplit {text} {
|
|
set l [split $text =]
|
|
set t [lindex $l 1]
|
|
return [string trim $t]
|
|
}
|
|
|
|
#----------- locate
|
|
# This is an internal routine and tries to locate a section in the database
|
|
# file. The database file is plain ASCII. There are sections in the file
|
|
# separated by lines starting with ####. The #### is followed by the title
|
|
# name of the section. Then follow lines of section specific data in variable
|
|
# syntax. Another complication is that we need to be able to update the data
|
|
# in the file. In order to do that the whole file is first read into an array
|
|
# before the search is started. This is feasible as we have at max a hundred
|
|
# lines. The array receives a member nl which is the number of lines read.
|
|
# The parameters are:
|
|
# ar the array of lines.
|
|
# fd a file descriptor as created by open
|
|
# keyword the keyword to search for
|
|
# The function returns the line number where the keyword was found on success,
|
|
# else -1 is returned.
|
|
|
|
#proc dbfile {} {
|
|
# return "dbfile = test.db"
|
|
#}
|
|
|
|
proc locate { data keyword} {
|
|
upvar $data ar
|
|
#--------- read file
|
|
set ret [catch {open [fsplit [dbfile]] r} fd]
|
|
if {$ret == 1} {
|
|
set ar(nl) 0
|
|
return -1
|
|
}
|
|
#----- read whole file
|
|
set i 0
|
|
while {[gets $fd line] > 0 } {
|
|
set ar($i) $line
|
|
incr i
|
|
}
|
|
set ar(nl) $i
|
|
close $fd
|
|
#----- start search
|
|
for {set i 0} {$i < $ar(nl)} { incr i} {
|
|
#------ look for delimiter
|
|
set delim [string range $ar($i) 0 3]
|
|
if {[string compare $delim ####] == 0} {
|
|
#----------- check keyword
|
|
if {[string first $keyword $ar($i) ] > 0} {
|
|
return $i
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
#--------------- writerange
|
|
# writerange writes a range of lines from an array created by locate
|
|
# to the file specicified by fd. Ranges are automaticcaly adjusted to
|
|
# data limits
|
|
|
|
proc writerange { data fd start end } {
|
|
upvar $data ar
|
|
#----- adjust ranges
|
|
if {$start < 0} {
|
|
set start 0
|
|
}
|
|
if {$start > $ar(nl) } {
|
|
set start $ar(nl)
|
|
}
|
|
if { $end > $ar(nl) } {
|
|
set end $ar(nl)
|
|
}
|
|
#---- write!
|
|
for {set i $start} {$i < $end} {incr i} {
|
|
puts $fd $ar($i)
|
|
}
|
|
}
|
|
|
|
#----------- writepos
|
|
# writepos writes the current positions of stt, om, ch, ph motors as a A type
|
|
# line into the reflection section of the data base file. This is used after
|
|
# centering an unindexed reflection.
|
|
|
|
proc writepos { } {
|
|
#----- get positions
|
|
set ret [catch {fsplit [stt]} mystt]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
set ret [catch {fsplit [om]} myom]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
set ret [catch {fsplit [ch]} mych]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
set ret [catch {fsplit [ph]} myph]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
#----- find position in file
|
|
set ret [catch {locate data reflections} ind]
|
|
#----- write
|
|
set ret [catch {open [fsplit [dbfile]] w} fd]
|
|
if { $ret == 1} {
|
|
error $fd
|
|
}
|
|
if { $ind < 0 } {
|
|
writerange data $fd 0 $data(nl)
|
|
puts $fd "#### reflections"
|
|
puts $fd [format "A %8.2f %8.2f %8.2f %8.2f" \
|
|
$mystt $myom $mych $myph]
|
|
} else {
|
|
incr ind
|
|
writerange data $fd 0 $ind
|
|
puts $fd [format "A %8.2f %8.2f %8.2f %8.2f" \
|
|
$mystt $myom $mych $myph]
|
|
writerange data $fd $ind $data(nl)
|
|
}
|
|
close $fd
|
|
return OK
|
|
}
|
|
|
|
#------------ writerefl
|
|
# writerefl writes a reflection with indexes. This makes an I record in
|
|
# the reflections list of the database file. This is meant to be used
|
|
# after centering a reflection after the UB-matrix is known
|
|
|
|
proc writerefl { } {
|
|
#----- get positions
|
|
set ret [catch {fsplit [stt]} mystt]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
set ret [catch {fsplit [om]} myom]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
set ret [catch {fsplit [ch]} mych]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
set ret [catch {fsplit [ph]} myph]
|
|
if {$ret == 1} {
|
|
error $myom
|
|
}
|
|
#------ get hkl
|
|
set ret [catch {hkl current} txt]
|
|
if {$ret == 1} {
|
|
error $txt
|
|
}
|
|
set l [split $txt]
|
|
set H [lindex $txt 2]
|
|
set K [lindex $txt 3]
|
|
set L [lindex $txt 4]
|
|
#----- find position in file
|
|
set ret [catch {locate data reflections} ind]
|
|
#----- write
|
|
set ret [catch {open [fsplit [dbfile]] w} fd]
|
|
if { $ret == 1} {
|
|
error $fd
|
|
}
|
|
if { $ind < 0 } {
|
|
writerange data $fd 0 $data(nl)
|
|
puts $fd "#### reflections"
|
|
puts $fd [format "I %5.2f %5.2f %5.2f %8.2f %8.2f %8.2f %8.2f" \
|
|
$H $K $L $mystt $myom $mych $myph]
|
|
} else {
|
|
incr ind
|
|
writerange data $fd 0 $ind
|
|
puts $fd [format "I %5.2f %5.2f %5.2f %8.2f %8.2f %8.2f %8.2f" \
|
|
$H $K $L $mystt $myom $mych $myph]
|
|
writerange data $fd $ind $data(nl)
|
|
}
|
|
close $fd
|
|
return OK
|
|
}
|
|
|
|
#----------- clearrefl
|
|
# clearrefl clears the list of reflections as stored in the database file
|
|
|
|
proc clearrefl {} {
|
|
#----- find position in file
|
|
set ret [catch {locate data reflections} ind]
|
|
#---- nothing to do if no entry
|
|
if {$ind < 0} {
|
|
return "Nothing to do"
|
|
}
|
|
#----- write
|
|
set ret [catch {open [fsplit [dbfile]] w} fd]
|
|
if { $ret == 1} {
|
|
error $fd
|
|
}
|
|
incr ind
|
|
writerange data $fd 0 $ind
|
|
for {set i $ind} {$i < $data(nl)} {incr i} {
|
|
set delim [string range $data($i) 0 3]
|
|
if {[string compare $delim ####] == 0} {
|
|
break
|
|
}
|
|
}
|
|
set ind [expr $ind + $i - 1]
|
|
writerange data $fd $ind $data(nl)
|
|
close $fd
|
|
return OK
|
|
}
|
|
|
|
#-------- listrefl
|
|
# listrefl lists all the entries in the reflection list
|
|
|
|
proc listrefl {} {
|
|
#----- find position in file
|
|
set ret [catch {locate data reflections} ind]
|
|
#---- nothing to do if no entry
|
|
if {$ind < 0} {
|
|
return "Nothing to do"
|
|
}
|
|
#------ list
|
|
incr ind
|
|
for {set i $ind} {$i < $data(nl)} {incr i} {
|
|
set delim [string range $data($i) 0 3]
|
|
if {[string compare $delim ####] == 0} {
|
|
break
|
|
} else {
|
|
ClientPut $data($i)
|
|
}
|
|
}
|
|
return OK
|
|
}
|
|
|
|
#---------- updateub
|
|
# updateub reads a UB matrix from the file and replaces the current SICS
|
|
# UB matrix with the one from the file. To be used after another program
|
|
# created a UB matrix in the first place or after refining the UB matrix
|
|
# following a centering operation.
|
|
# WARNING: this requires that the Tcl internal scan command has been r
|
|
# renamed BEFORE loading the scan command to stscan. Otherwise there is
|
|
# as conflict with the scan routine!
|
|
|
|
proc updateub {} {
|
|
#----- find position in file
|
|
set ret [catch {locate data UB} ind]
|
|
if { $ind < 0} {
|
|
error "ERROR: No UB matrix in database"
|
|
}
|
|
incr ind
|
|
#------ read three lines of UB
|
|
stscan $data($ind) "%f%f%f" ub11 ub12 ub13
|
|
ClientPut $ub11 $ub12 $ub13
|
|
incr ind
|
|
stscan $data($ind) "%f%f%f" ub21 ub22 ub23
|
|
incr ind
|
|
stscan $data($ind) "%f%f%f" ub31 ub32 ub33
|
|
hkl setub $ub11 $ub12 $ub13 $ub21 $ub22 $ub23 $ub31 $ub32 $ub33
|
|
return OK
|
|
}
|
|
|
|
#--------- setlambda
|
|
# setlambda sets the wavelength
|
|
|
|
proc setlambda {newval} {
|
|
set ret [catch {hkl lambda $newval} msg]
|
|
if {$ret == 1} {
|
|
error $msg
|
|
}
|
|
#----- find position in file
|
|
set ret [catch {locate data lambda} ind]
|
|
#----- write
|
|
set ret [catch {open [fsplit [dbfile]] w} fd]
|
|
if { $ret == 1} {
|
|
error $fd
|
|
}
|
|
if { $ind < 0 } {
|
|
writerange data $fd 0 $data(nl)
|
|
puts $fd "#### lambda"
|
|
puts $fd [format " %12.6f" $newval]
|
|
} else {
|
|
incr ind
|
|
writerange data $fd 0 $ind
|
|
puts $fd [format " %12.6f" $newval]
|
|
incr ind
|
|
writerange data $fd $ind $data(nl)
|
|
}
|
|
close $fd
|
|
return OK
|
|
}
|
|
|
|
#------- fcentre
|
|
# fcentre centers a reflection
|
|
proc fcentre {} {
|
|
#----- rough centering
|
|
opti clear
|
|
opti countmode monitor
|
|
opti preset 1000
|
|
opti threshold 30
|
|
opti addvar om .1 25 .10
|
|
opti addvar stt .20 25 .25
|
|
opti addvar ch 1.0 20 1.
|
|
set ret [catch {opti run} msg]
|
|
if {$ret == 1} {
|
|
error $msg
|
|
}
|
|
#----- fine centering
|
|
opti preset 5000
|
|
opti threshold 50
|
|
set ret [catch {opti run} msg]
|
|
if {$ret != 0 } {
|
|
error $msg
|
|
}
|
|
set txt [om]
|
|
set l [split $txt =]
|
|
set tom [lindex $l 1]
|
|
set txt [stt]
|
|
set l [split $txt =]
|
|
set tstt [lindex $l 1]
|
|
set txt [ch]
|
|
set l [split $txt =]
|
|
set tch [lindex $l 1]
|
|
set txt [ph]
|
|
set l [split $txt =]
|
|
set tph [lindex $l 1]
|
|
ClientPut "Two-Theta Omega Chi Phi"
|
|
ClientPut [format "%-10.2f%-10.2f%-10.2f%-10.2f" $tstt $tom $tch $tph]
|
|
storepos
|
|
} |