#!/bin/sh
# \
  exec oagwish "$0" "$@"

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSStandardSetup


# This is an implementation of the downhill simplex method of optimziation.
# It is written to vary EPICS process variables to determine a desired
# result on a readback.  It is a general-purpose routine.


# this procedure is a message-interface procedure.
proc sendMessage {string} {
    puts stdout $string
}

proc setRestore { {popUp 1} } {
   global resetOriginalValues
   if {$popUp} {
       if {[APSYesNoPopUp "Do you want to restore to original settings?"]} {
             set resetOriginalValues 1
       }
    }
} 
# this procedure saves the best point to the log file,
proc logData {pin logFile} {
    upvar $pin p
    global controlPV numcon figureOfMerit tolerance pauseAfterChange
    global initialChange lowerLimit upperLimit iterations
    set log [open $logFile w]
    puts $log "SDDS1"
    puts $log "&parameter name=tolerance type=double &end"
    puts $log "&parameter name=iterations type=long &end"
    puts $log "&parameter name=pauseAfterChange type=double &end"
    puts $log "&column name=controlPV type=string &end"
    puts $log "&column name=initialValue type=double &end"
    puts $log "&column name=lowerLimit type=double &end"
    puts $log "&column name=upperLimit type=double &end"
    puts $log "&column name=initialChange type=double &end"
    puts $log "&data mode=ascii no_row_counts=1 &end"
    
 
    puts $log $tolerance
    puts $log $iterations
    puts $log $pauseAfterChange
    
    for {set i 0} {$i< $numcon } {incr i} {
        if [string length $controlPV($i)]==0 continue
        puts $log "$controlPV($i) $p([expr $i+1]) $lowerLimit($i) $upperLimit($i) \
                   $initialChange($i)"
    }
    close $log  
}

proc getPVAve {} {
   global ReadValue
   global Measurements MeasurementPV Weight DesiredValue 
   global numberToAverage MeasVarList MeasPVList 
   global pauseBetweenReadings
   set RMSAverage 0.0
   sendMessage "Read Measurement Values ..."
   if {[pv getw $MeasVarList]} {
      sendMessage "$errorCode"
      exit 1
   } else {
     for {set i 0} {$i< $Measurements} {incr i} {
        set sum($i) $ReadValue($i)
      }
      set num [expr $numberToAverage-1]
      puts "Average=$numberToAverage"
      set count 0
     if {$num} {
        while {$count < $num} {
           after [expr int($pauseBetweenReadings*1000)]
           pv getw $MeasVarList
           for {set i 0} {$i< $Measurements} {incr i} {
              set sum($i) [expr ($sum($i)+$ReadValue($i))/$numberToAverage]
            }
            incr count
        }
      }
   }
 
   for {set i 0} {$i <$Measurements} {incr i} {   
      set differ($i) [expr $sum($i) - $DesiredValue($i)]
      set RMSAverage [expr $RMSAverage + pow($differ($i),2)*$Weight($i)]
   }
   set ave [expr $RMSAverage/$Measurements]
   return $ave
}

# this procedure is the optimizer itself.
proc amoeba {pin yin ndim ftol funk itmax} {
    # argument lists:
    #    p - starting matrix whose ndim+1 rows are ndim-dimensional 
    #        vectors which define the vertices of the starting simplex;  
    #        dimensions are p(ndim+1,ndim)
    #    y - vector of length ndim+1, containing the values of funk at the
    #        vertex points defined in p
    #    ndim - number of dimensions in the array
    #    ftol - the fractional convergence tolerance required
    #    funk(x) - a function, where x is an ndim-dimensional vector
    #    itmax - maximum number of iterations to take before we bomb out
 
    # pass the arrays by name instead of by value....
    upvar $pin p
    upvar $yin y
    global controlPV saveInitialState resetOriginalValues

    # some initial parameter:  max. allowed dimensions to optimize on, the
    # parameters for vertex expansion and contraction, and the max. number of
    # iterations we allow before bombing out.
    set nmax 20 
    set alpha 1.0
    set beta 0.5
    set gamma 2.0

    set mpts [expr $ndim + 1]
    set iter 0


    while 1 {
        sendMessage "Starting iteration \# $iter of $itmax"
        # write the vertex coordinates and the figures-of-merit
        set tmplist {}
        set tmplist [linsert $tmplist 0 [format %-14s "  results"]]
        for {set i 0 } {$i < $ndim} {incr i} {
           set tmplist [linsert $tmplist [expr $i+1] [format "%-13s" $controlPV($i)]]
        }
        sendMessage $tmplist
        for {set j 1} {$j <= $mpts} {incr j} {
            set templist {}            
            for {set i 1} {$i <= $ndim} {incr i} {
                set templist [linsert $templist $i [format %15.4f $p($j,$i)]]
            }
            set templist [linsert $templist 0 |]
            set templist [linsert $templist 0 [format %10.4f $y($j)]]
            sendMessage $templist
        }
        # determine which points are the worst (highest) and best (lowest)
        set ilo 1
        if { $y(1) > $y(2) } {
            set ihi 1
            set inhi 2
        } else {
            set ihi 2
            set inhi 1
        }
        for {set i 1} {$i <= $mpts} {incr i} {
            if {$y($i) < $y($ilo)} {
                set ilo $i
            }
            if {$y($i) > $y($ihi)} {
                set inhi $ihi
                set ihi $i
            } elseif {$y($i) > $y($inhi)} {
                if {$i != $ihi} {
                    set inhi $i
                }
            }
        }
        puts "ilo $ilo   ihi $ihi   inhi $inhi"
        # return the best point through a list obtained from an array
  
       for {set i 1} { $i <= $ndim } {incr i} {
           set lowest($i) $p($ilo,$i)
        }
       set pp [array get lowest]
 
        # Compute the fractional range from highest to lowest, and return
        # if it's within the specified tolerance
        if { [expr 0 != abs($y($ihi))+abs($y($ilo))] } {
            set rtol [expr 2.0*abs($y($ihi)-$y($ilo))/(abs($y($ihi))+abs($y($ilo)))]
            if {$rtol < $ftol} {
                sendMessage "All points are within the specified tolerance range.\
                             set the state to the best state."
                for {set i 1} { $i <= $ndim } {incr i} {
                   set saveInitialState($i)  $lowest($i)
                }
                set resetOriginalValues 0
                return $pp
            }
        } else {
            # sinc ehte denominator was zero. I don't know what to do here.
        }
        if {$iter == $itmax} {
            
            sendMessage "Exceeding the max. allowed number of iterations!"
            sendMessage "Press Continue button to continue the iteration!"
            return $pp
           
        }
        incr iter
        for {set j 1} {$j <= $ndim} {incr j} {
            set pbar($j) 0
        }
        
        for {set i 1} {$i <= $mpts} {incr i} { 
            if {$i != $ihi} {
                for {set j 1} {$j <= $ndim} {incr j} {
                    set pbar($j) [expr $pbar($j) + $p($i,$j)]
                }
            }
        }
        for {set j 1} {$j <= $ndim} {incr j} {
            set pbar($j) [expr $pbar($j)/$ndim]
            set pr($j) [expr (1.0+$alpha)*$pbar($j)-$alpha*$p($ihi,$j)]
        }
        set ypr [$funk pr]

        if {$ypr <= $y($ilo)} { ;# point was better than best, so do again
            for {set j 1} {$j <= $ndim} {incr j} {
                set prr($j) [expr $gamma*$pr($j)+(1.0-$gamma)*$pbar($j)]
            }
            sendMessage "New point better than current best;  proceeding on vector"
            set yprr [$funk prr]
            
            if {$yprr <= $y($ilo)} {
                sendMessage "Additional extrapolation succeeded"
                for {set j 1} {$j <= $ndim} {incr j} {
                    set p($ihi,$j) $prr($j)
                }
                set y($ihi) $yprr
            } else {
                sendMessage "Additional extrapolation failed"
                for {set j 1} {$j <= $ndim} {incr j} {
                    set p($ihi,$j) $pr($j)
                }
                set y($ihi) $ypr
            }
        } elseif {$ypr >= $y($inhi)} {
            if {$ypr < $y($ihi) } {
                for {set j 1} {$j <= $ndim} {incr j} {
                    set p($ihi,$j) $pr($j)
                }
                set y($ihi) $ypr
                sendMessage "Replacing worst point"
            }
            for {set j 1} {$j <= $ndim} {incr j} {
                set prr($j) [expr $beta*$p($ihi,$j)+(1.-$beta)*$pbar($j)]
            }
            sendMessage "Contracting..."
            set yprr [$funk prr]
           
            if {$yprr < $y($ihi)} {
                for {set j 1} {$j <= $ndim} {incr j} {
                    set p($ihi,$j) $prr($j)
                }
                set y($ihi) $yprr
            } else {
                sendMessage "Contracting around best point"
                for {set i 1} {$i <= $mpts} {incr i} {
                    puts "Operating on point $i"
                    for {set j 1} {$j <= $ndim} {incr j} {
                        set pr($j) [expr 0.5*($p($i,$j)+$p($ilo,$j))]
                        set p($i,$j) $pr($j)
                    }
                    set y($i) [$funk pr]
                    
                }
            }
        } else {
            sendMessage "Replacing high point"
            for {set j 1} {$j <= $ndim} {incr j} {
                set p($ihi,$j) $pr($j)
            }
            set y($ihi) $ypr
        }
    }

}

# This procedure sets up parallel lists of PVs and tcl variables
proc addToLists {args} {
    global pvList tclVarList
    APSAddToParallelLists -listNames {pvList tclVarList} \
      -listItems $args
}
#proc addToVarLists {args} {
#    global pvList tclVarList
#    APSAddToParallelLists -listNames {pvList tclVarList} \
#      -listItems $args
#}
proc addToMeasLists {args} {
    global MeasPVList MeasVarList
    APSAddToParallelLists -listNames {MeasPVList MeasVarList} \
      -listItems $args
}

# this procedure obtains the information required to start the optimization
# process.  It reads an sdds data file to obtain the relevant setup and PV
# name information, and sets those into standard variables.
proc getStartingInformation {args} {
    global mode target tolerance figureOfMerit numberToAverage
    global pauseBetweenReadings pauseAfterChange numcon controlPV
    global lowerLimit upperLimit initialChange initialValue
    APSParseArguments {variableFile}
    set filespec $variableFile
    # variables are defined as follows
    #   tolerance - fractional tolerance for solution convergence
    #   figureOfMerit - figure-of-merit PV to read
    #   numberToAverage - number of readings to average
    #   pauseBetweenReadings - pause (in s) between readings of the fom
    #   pauseAfterChange - pause (in s) after change of the controls
    #   numcon - number of control PVs there are to read
    #   controlPV - an array containing the control PV names
    #   lowerLimit - an array containing the lower limits on the PVs
    #   upperLimit - an array containing the upper limits on the PVs
    #   initialChange - an array containin the initial changes to the PVs
    set errs 0 ;# keeps a count of errors encountered during the process
    if [file exists $filespec] {
        # open the data file
        set fd [sdds open $filespec r]
        # retrieve the parameter and column names
        set paramList [sdds getNames $fd parameter]
        set colList [sdds getNames $fd column]
        # determine the optimization mode and target, if any
        if {[lsearch $paramList "mode"] != -1} {
            set mode [sdds getParameter $fd "mode" -page 1]
            sendMessage "Operating mode:  $mode"
            if {$mode == "equal"} {
                if {[lsearch $paramList "target"] != -1} {
                    set target [sdds getParameter $fd target -page 1]
                    sendMessage "target value:  $target"
                } else {
                    incr errs
                    sendMessage "Error:  no target value given"
                    set target "<NONE>"
                }
            }
        }
        # determine the tolerance, if any;  set to default if none.
        if {[lsearch $paramList "tolerance"] != -1} {
            set tolerance [sdds getParameter $fd "tolerance" -page 1]
            sendMessage "solution tolerance:  $tolerance"
        } else {
            set tolerance 0.01
            sendMessage "solution tolerance:  defaulting to $tolerance"
        }
        # get the PV or script name returning the figure-of-merit
        if {[lsearch $paramList "figureOfMerit"] != -1} {
            set figureOfMerit [string trim \
                [sdds getParameter $fd "figureOfMerit" -page 1] "{}" ]
            sendMessage "figure-of-merit defined by $figureOfMerit"
        } else {
            sendMessage "No figure-of-merit PV defined!"
            
 #           incr errs
        }

        # get the pause after changing a control PV
        if {[lsearch $paramList "pauseAfterChange"] != -1} {
           set pauseAfterChange [sdds getParameter $fd "pauseAfterChange" \
               -page 1]
           sendMessage "pause after changing a control PV:  $pauseAfterChange"
        } else {
            set pauseAfterChange 1.0
            sendMessage "No pause after PV change"
        }
        # retrieve the PV name information and limits etc.
        if {[lsearch $colList "controlPV"] != -1} {
            set temp [sdds getColumn $fd "controlPV"]
            set numcon [llength $temp]
            if {$numcon == 0} {
                incr errs
                sendMessage "Error!  No control PVs were defined!"
            } else {
                for {set i 0} {$i < $numcon} {incr i} {
                    set controlPV($i) [lindex $temp $i]
                }
                sendMessage "$numcon control PVs have been loaded:"
                parray controlPV
            } 
        } else {
            sendMessage "Error!  missing controlPV column!"
            incr errs
        }
        # add the lower limits to the array
        if {[lsearch $colList "lowerLimit"] != -1} {
            sendMessage "Defining the lower limits as specified"
            set temp [sdds getColumn $fd "lowerLimit"]
            for {set i 0} {$i < $numcon} {incr i} {
                set lowerLimit($i) [lindex $temp $i]
            }
        } else {
            sendMessage "No lower limits specified"
            for {set i 0} {$i < $numcon} {incr i} {
                set lowerLimit($i) -1.0e27
            }
        }
        parray lowerLimit
        # add the upper limits to the array
        if {[lsearch $colList "upperLimit"] != -1} {
            sendMessage "Defining the upper limits as specified"
            set temp [sdds getColumn $fd "upperLimit"]
            for {set i 0} {$i < $numcon} {incr i} {
                set upperLimit($i) [lindex $temp $i]
            }
        } else {
            sendMessage "No lower limits specified"
            for {set i 0} {$i < $numcon} {incr i} {
                set upperLimit($i) 1.0e27
            }
        }
        parray upperLimit

        # add the initial values to the array
        if {[lsearch $colList "initialValue"] != -1} {
            sendMessage "Defining the initial values as specified"
            set temp [sdds getColumn $fd "initialValue"]
            for {set i 0} {$i < $numcon} {incr i} {
                set initialValue($i) [lindex $temp $i]
            }
        } else {
            sendMessage "No initial value specified"
            for {set i 0} {$i < $numcon} {incr i} {
                set initialValue($i) 0.0
            }
        }
        parray initialValue

        # determine the initial changes to make to the controls
        if {[lsearch $colList "initialChange"] != -1} {
            sendMessage "Defining the initial change parameters"
            set temp [sdds getColumn $fd "initialChange"]
            for {set i 0} {$i < $numcon} {incr i} {
                set initialChange($i) [lindex $temp $i]
            }
        } else {
            sendMessage "No initial change specified;  defaulting to 0.5 \
               in whatever units"
            for {set i 0} {$i < $numcon} {incr i} {
                set initialChange($i) 0.5
            }
        }
        parray initialChange
        sdds close $fd
    }
    return $errs
}

# this procedure obtains the information of measurements from measurementFile
proc getMeasurementInfo {args} {
    global measurementFile MeasurementPV ReadBackName ReadBackUnits Measurements
    global Weight DesiredValue pauseBetweenReadings numberToAverage 
    APSParseArguments {measurementFile}
    puts $measurementFile
    set errs 0 ;# keeps a count of errors encountered during the process
    if [file exists $measurementFile] {
        # open the data file
        set fd $measurementFile
        if {![APSCheckSDDSFile -fileName $fd]} {
        sendMessage "$fd is not an SDDS file."
        return
    }
 
        # retrieve column names
       set paramList [APSGetSDDSNames -fileName $fd -class parameter]
       if { [lsearch $paramList "pauseBetweenReadings"] != -1 } {
           set pauseBetweenReadings [APSGetSDDSParameter -fileName $fd -parameter \
               pauseBetweenReadings -page 0 ]
       } 
       if {[lsearch $paramList "numberToAverage"] !=-1 } {
            set numberToAverage [APSGetSDDSParameter -fileName $fd -parameter \
               numberToAverage -page 0]
       } else {
            set numberToAverage 1
       }
       set colList [APSGetSDDSNames -fileName $fd -class column]   
       if {[llength $colList]<1} {
          sendMessage "$fd doesn't contain any data columns from which
             to get PV names."
           incr errs
       }
       if {[lsearch -exact $colList "ControlName"]!=-1} {
            set columnName ControlName
        } else {
           sendMessage "$fd doesn't contain any data columns from which to
              get PV names."
            incr errs
        } 
        set names [APSGetSDDSColumn -fileName $fd -column $columnName -page 0]
       if {[llength $names]==0} {
          sendMessage "$fd has no process variable names."
          incr errs
       }
       set Measurements [llength $names]
       for {set i 0} {$i < $Measurements} {incr i} {
            set MeasurementPV($i) [lindex $names $i]
            puts $MeasurementPV($i)
       }
       # add the weight to the array
       if {[lsearch $colList "Weight"] != -1} {
             set temp [APSGetSDDSColumn -fileName $fd -column "Weight" -page 0]
             for {set i 0} {$i < $Measurements} {incr i} {
                set Weight($i) [lindex $temp $i]
              }
        } else {
           sendMessage "No Weight for the measurements specified"
              for {set i 0} {$i < $Measurements} {incr i} {
                  set Weight($i) 1
              }
        }
        
        # add the DesiredValue to the array
       if {[lsearch $colList "DesiredValue"] != -1} {
          set temp [APSGetSDDSColumn -fileName $fd -column "DesiredValue" -page 0]
          for {set i 0} {$i < $Measurements} {incr i} {
             set DesiredValue($i) [lindex $temp $i]
          }
        } else {
            sendMessage "No desired value for measurement PVs specified"
            for {set i 0} {$i < $Measurements} {incr i} {
               set DesiredValue($i) 0
            }
        }
        # add the ReadBackName to the array
        if {[lsearch $colList "ReadbackName"] != -1} {
            set temp [APSGetSDDSColumn -fileName $fd -column "ReadbackName" -page 0]
            for {set i 0} {$i < $Measurements} {incr i} {
                set ReadBackName($i) [lindex $temp $i]
            }
        } else {
           sendMessage "No ReadBackName for the measurements specified"
        }
        # add the ReadBackUnits to the array
        if {[lsearch $colList "ReadbackUnits"] != -1} {
            set temp [APSGetSDDSColumn -fileName $fd -column "ReadbackUnits" -page 0]
            for {set i 0} {$i < $Measurements} {incr i} {
                set ReadBackUnits($i) [lindex $temp $i]
            }
        } else {
             sendMessage "No ReadBackUnits for the measurements specified"
        }
#        sdds close $fd
    }
    return $errs
}



# This is the procedure that actually performs the PV update, and reads in the
# new value
proc moveAndRead {inlist} {
    upvar $inlist newValue
    global mode target tolerance figureOfMerit numberToAverage
    global pauseBetweenReadings pauseAfterChange numcon controlPV
    global lowerLimit upperLimit initialChange 
    global tclVarList scriptPVAccess
    eval global $tclVarList

    # bell
    # first, perform range-checking on the input information
    for {set i 1} {$i <= $numcon} {incr i} {
        if {[expr $newValue($i)>$upperLimit([expr $i-1])]} {
            bell ; sendMessage "*** requested value out of range;
                                setting to upper limit ***"
            set newValue($i) $upperLimit([expr $i-1])
        } elseif {[expr $newValue($i)<$lowerLimit([expr $i-1])]} {
            bell ; sendMessage "*** requested value out of range;
                               setting to lower limit ***"
            set newValue($i) $lowerLimit([expr $i-1])
        }
        set scriptPVAccess([expr $i - 1]) $newValue($i)
    }
    
 
    # set the control PVs to their new values
    for {set i 0} {$i < $numcon} {incr i} {
        pv putw scriptPVAccess($i)
    }
    # now wait for things to settle down
    # puts "pauseAfterChange=$pauseAfterChange"
    after [expr int($pauseAfterChange*1000)]
#    set sum 0.0
    set lcv 0
    #    sendMessage "Acquiring data..."
    global scriptFOMAccess ReadValue
    set scriptFOMAccess [getPVAve]
#    set sum [expr $sum + $scriptFOMAccess]
    return $scriptFOMAccess
}




# This is where the script starts
set variableFile ""
set measurementFile ""
set logFile ""
set iterations 200
set resetOriginalValues 0
set numberToAverage 1
set figureOfMerit ""
set usage "Usage: amoeba.tcl -measurementFile <file> -variableFile <file> \
    -iterations <number>\[-resetOriginalValues \{0|1\}\]"
set args $argv
APSParseArguments {measurementFile variableFile iterations
 resetOriginalValues}
if {![string length $measurementFile] || ![string length $variableFile]} {
    puts stderr "Error: invalid syntax:\n$usage"
    exit
}


set maxIters $iterations

# Load in and read the optimization parameters
puts "Getting measurement information"
set er1 [getMeasurementInfo -measurementFile $measurementFile]
if {$er1>0} {
    sendMessage "$er1 errors encountered while reading the input measurement file.\
                 Aborting."
    exit
}

puts "Getting the variable file information"
set er [getStartingInformation -variableFile $variableFile]
if {$er>0} {
    sendMessage "$er errors encountered while reading the input variable file.\
                 Aborting."
    exit
}

#sendMessage "Figure-of-merit variable:  $figureOfMerit"

# create the linked lists for accessing these PVs
# add the linked lists of measurement PV
for {set i 0} {$i < $Measurements} {incr i} {
    addToMeasLists $MeasurementPV($i) ReadValue($i)
}
# add the linked lists of the control PVs
for {set i 0} {$i < $numcon} {incr i} {
    addToLists $controlPV($i) scriptPVAccess($i)    
}

# link the lists
sendMessage "Linking to variable pvs..."
if [pv linkw $tclVarList $pvList] {
    sendMessage "$errorCode"
    exit 1
}
sendMessage "Linking to measurement pvs..."
if [pv linkw $MeasVarList $MeasPVList] {
    sendMessage "$errorCode"
    exit 1
}

#if {[lsearch $figureOfMerit "-script"] == -1} {
#    pv getw scriptFOMAccess
#    sendMessage "Initial value of FOM: $scriptFOMAccess"
#} else {
#    sendMessage "Accessing script for initial figure-of-merit reading..."
#    sendMessage "[lrange $figureOfMerit 1 end]"
#    set scriptFOMAccess [eval exec [lrange $figureOfMerit 1 end]]
    
    set scriptFOMAccess [getPVAve]
#}

sendMessage "Readback PV:  $figureOfMerit initial value --> $scriptFOMAccess"
for {set i 0} {$i < $numcon} {incr i} {
#    pv getw scriptPVAccess($i)
    set scriptPVAccess($i) $initialValue($i)
#    set saveInitialState($i) $scriptPVAccess($i)
    sendMessage "Control PC:  $controlPV($i) initial value -->\
        $scriptPVAccess($i)"
}



# define the initial array of vertex coordinates, to be passed to 
# the optimizer, and calculate the function values on those points
for {set i 1} {$i <= [expr $numcon + 1]} {incr i} {
    sendMessage "Setting up point $i"
    for {set j 1} {$j <= $numcon} {incr j} {
        set pin($i,$j) $scriptPVAccess([expr $j -1])
        if {$i == [expr $j + 1]} {
            set pin($i,$j) [expr $pin($i,$j) + $initialChange([expr $j-1])]
        }
        # and also check for range limits
        if {[expr $pin($i,$j)>$upperLimit([expr $j-1])]} {
            set pin($i,$j) [expr $upperLimit([expr $j-1]) - $initialChange([expr $j-1])]
            sendMessage "Point $i,$j above upper range limit ... \
                         lowering to limit-initialchange"
        } elseif {[expr $pin($i,$j)<$lowerLimit([expr $j-1])]} {
            set pin($i,$j) [expr $lowerLimit([expr $j-1]) + $initialChange([expr $j-1])]
            sendMessage "Point $i,$j below lower range limit ... 
                         lowering to limit+initialchange"
        }
    }
}
sendMessage "Initial array creation completed."

for {set i 1} {$i <= [expr $numcon + 1]} {incr i} {
    for {set j 1} {$j <= $numcon} {incr j} {
        set vertex($j) $pin($i,$j)
    }
    sendMessage "Performing initial setting and acquistion on point $i"
    set yin($i) [moveAndRead vertex]
  
}

sendMessage "Initial vertex point calculation completed."

# This section sets up a logfile output

set resultList [amoeba pin yin $numcon $tolerance moveAndRead $maxIters]

#logdata
array set resultArray $resultList
# logData resultArray $logFile


proc RestoreValues {} {
    global numcon pauseAfterChange initialValue scriptPVAccess tclVarList pvList
    sendMessage "Restoring to original settings..."
    after [expr int($pauseAfterChange*1000)] 
    for {set i 0} {$i < $numcon} {incr i} {
        set scriptPVAccess($i) $initialValue($i)
#        pv putw scriptPVAccess($i)
    }
    pv putw $tclVarList
    parray initialValue
    sendMessage "Restoration completed ... have a nice day!"
    
}

# set resetOriginalValues 1
if {$resetOriginalValues} {
    RestoreValues
    after [expr int($pauseAfterChange*1000)]  
#    for {set i 0} {$i < $numcon} {incr i} {   
#        pv getw scriptPVAccess($i)
#    }
    pv getw $tclVarList
    parray scriptPVAccess
}

exit
