Files
sics/fcircle.tcl
2000-02-07 10:38:55 +00:00

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
}