#!/usr/bin/expect

# (c) S. Parkin 15/02/19 -- 15/04/24: SADABS-AUTO-RUN - a SADABS automator.
#
# This version of SADABS-AUTO-RUN is customized for SADABS-2014/4.
#
# An 'expect' script that automates runs of George Sheldrick's SADABS absorption 
# correction program.  At present, SADABS-AUTO-RUN is configured to run a SADABS 
# job with largely default parameters but with the even & odd spherical harmonic 
# orders, average muR value, and (possibly) the Laue group number taken from the 
# command line. It is meant to be called by the companion script, 'SADABS-AUTO',
# which is used to figure out the Laue group number used by SADABS, plus a small 
# number of other things.  In this way, SADABS can be made completely automatic. 
# NOTE:  Although SADABS-AUTO-RUN can be used without SADABS-AUTO, the intention 
# is to use them together.
#
# 'Expect' is an extension of Tcl, and is the work of Don Libes at the NIST.
#
# Note:  If you want to see the regular SADABS interactive blurbs whiz by on the
# screen, comment out the next line (this is the default).
# log_user 0

set timeout -1

# An empty temporary file called 'sadabs-auto-temp' is created and used in error 
# trapping.  Basically, if the Laue group number is set too high, then this file 
# is deleted and SADABS-AUTO-RUN exits back to SADABS-AUTO. SADABS-AUTO writes a 
# different message depending on whether the sadabs-auto-temp file is present or 
# absent. 
#
system "touch sadabs-auto-temp"

# Set a few of the numerical inputs as variables. The use of variables for these 
# inputs is so that they can be modified more easily by SADABS-AUTO - the script 
# that calls SADABS-AUTO-RUN.  The variable 'machine_flag' is used to allow data 
# from the X8 Proteum and the kappaCCD machines to be treated differently. 
#
set filename [lindex $argv 0]
set machine_flag [string index $filename 0]
set sadabs_laue_group_number [lindex $argv 1]
set highest_even_order [lindex $argv 2]
set highest_odd_order [lindex $argv 3]
set muR_equivalent [lindex $argv 4]
set weighting_scheme [lindex $argv 5]
set refinement_cycles [lindex $argv 6]
set max_reflections 2000000
set mean_I_over_sigma 1.5
set high_res_for_par_ref 0.1
set g_factor_initial 0.04

# Hmm - who knows how to set restraint_esd_scale ? The SADABS manual from Bruker 
# suggests to use values between 0.001 and 0.005. SADABS itself then states that 
# strong absorption might do better with a larger value.  The default value used 
# for X8 Proteum data appears to be 0.005, but for kappaCCD data it is 0.02. For 
# filenames that begin with a letter 'k' (i.e., kappaCCD data) the esd restraint 
# is therefore set to 0.02.  The values given here can easily be changed. Not so 
# exhaustive tests using high-quality data from the UK X-ray laboratory suggests 
# that it does not make much difference. If you know better, please let me know.
#
if { $highest_even_order <= 4 } { set restraint_esd_scale 0.005 }
if { $highest_even_order == 6 } { set restraint_esd_scale 0.010 }
if { $highest_even_order == 8 } { set restraint_esd_scale 0.020 }
if { $machine_flag == "k" } { set restraint_esd_scale 0.02 }
set high_res_limit 0.1
set g_value_for_rejections 0.0400
set I_minus_mean_I_over_su_ratio 4.0
set p_in_error_model 2.0
#
# For a graphite monochromator, the lambda/2 correction type should be set to 2, 
# and the default correction factor of 0.0015 ought to be fine.  For mirrors, no 
# correction for lambda/2 effects is required.  The kappaCCD diffractometer uses 
# a graphite monochromator, but the X8 Proteum has graded multilayer mirrors.
#
set lambda_over_2_correction_type 0
if { $machine_flag == "k" } { set lambda_over_2_correction_type 2 } 
if { $machine_flag == "k" } { set lambda_over_2_correction_factor 0.0015 }
if { $machine_flag == "x" } { set lambda_over_2_correction_type 0 }
if { $highest_even_order <= 4 } { set no_ref_cycles 25 }
if { $highest_even_order == 6 } { set no_ref_cycles 48 }
if { $highest_even_order == 8 } { set no_ref_cycles 98 }
if { $weighting_scheme == "" } { set weighting_scheme 5 }
if { $refinement_cycles != ""} { set no_ref_cycles $refinement_cycles }
set marquardt_damping_factor 0.0001

# NOTE: The log_user commands below are used to suppress output to the screen.
#
log_user 0
spawn sadabs14.4 
log_user 1

# The following few lines error trap a situation where too large of a Laue group 
# number was specified on the command line.  
#
expect_before "do you really want to continue" {
  puts "\n"
  puts " FAILED!  You need to use the correct (or a lower) Laue group number. "
  puts " SADABS-AUTO will abort. "
  puts ""
  puts " ** ALERT! -- THE REST OF THE OUTPUT HERE WILL BE GARBAGE! ** "
  puts ""
  system "rm sadabs-auto-temp"
  exit 
}

# The following lines send the spawned SADABS job (largely) default responses to 
# the normal SADABS interactive input requests.
#

expect "Expert mode (Y or N)" { send "Y\r" }
expect "Maximum number of reflections allowed (2000000)" { send "$max_reflections\r" }
expect "Enter listing filename" { send "$filename.abs\r" }
expect "Enter Laue group number " { send "$sadabs_laue_group_number\r" }
expect "Treat Friedel opposites as equivalent" { send "Y\r" }
expect "Use a centrosymmetric point group" { send "Y\r" }
expect "for processing SIR data etc.: " { send "\r" }
expect "Enter filename (/ if no more)" { send "$filename\r" }
expect "Enter filename (/ if no more)" { send "/\r" }
expect { 
  "all other scans:" {
    send "\r"
    exp_continue
  }
  "Enter mean(I/sigma) threshold" {
    send "$mean_I_over_sigma\r"
  }
}
expect "Highest resolution for parameter refinement" { send "$high_res_for_par_ref\r" }
expect "Factor g for initial weighting scheme" { send "$g_factor_initial\r" }
expect "Restraint esd for equal consecutive scale factors" { send "$restraint_esd_scale\r" }
expect "Apply angle of incidence correction" { send "Y\r" }
expect "Enter value of phosphor efficiency" { send "\r" }
expect "Radius in pixels for automatic mask generation" { send "\r" }
expect "Number of refinement cycles" { send "$no_ref_cycles\r" }
expect "Detector (D) or crystal (C) coordinates" { send "C\r" }
expect "Highest even order for spherical harmonics" { send "$highest_even_order\r" }
expect "Highest odd order for spherical harmonics" { send "$highest_odd_order\r" }
expect "Marquardt damping factor" { send "$marquardt_damping_factor\r" }
expect "Allow for crystal decomposition" { send "N\r" }
#expect "B-value dependence on frame number" { send "\r" }
expect "Apply face-indexed absorption corrections" { send "N\r" }
#expect "linear correction to each reflection for radiation damage" { send "\r" }
expect "Repeat parameter refinement (R) or accept (A)" { send "A\r" }
expect "High resolution limit" { send "$high_res_limit\r" }
expect "|I-<I>|/su ratio for rejection" { send "$I_minus_mean_I_over_su_ratio\r" }
expect "g-value for use in:  su^2 = sigma^2 + (g<I>)^2" { send "$g_value_for_rejections\r" }
expect "Repeat parameter refinement (P), repeat rejections (R) or accept (A)" { send "A\r" }
expect "input fixed K and g (11)" { send "$weighting_scheme\r" }
expect "Repeat parameter refinement (P), repeat error model (E) or accept (A)" { send "A\r" }
expect "Write Postscript diagnostic file" { send "N\r" }
expect "Repeat (R), write unmerged .hkl (W)" { send "W\r" }
expect "Reflection output file" { send "$filename.hkl\r" }
expect "Mu*r of equivalent sphere" { send "$muR_equivalent\r" }
expect "Apply lambda/2 correction" { send "$lambda_over_2_correction_type\r" }
if { $machine_flag == "k"} { expect "Correction factor" { send "$lambda_over_2_correction_factor\r" }}
expect " quit (Q)" { send "Q\r" }

#interact






