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

#
# $Log: not supported by cvs2svn $
# Revision 1.1  2003/10/24 20:36:45  shang
# this script was written a year ago, never committed.
#

# first version, Hairong Shang

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)]
APSDebugPath

set CVSRevisionAuthor "\$Revision: 1.2 $ \$Author: emery $"

APSApplication . -name "SwitchBPMPolynomials" -version $CVSRevisionAuthor \
  -overview "switch bpm polynomial between 3-term and 20-term and transfer bpm offsets and setpoint betwen two polynomials"

set SROrbitStatus "Ready."
APSScrolledStatus .status -parent .userFrame -width 60 \
  -textVariable SROrbitStatus 

proc SetMainStatus {text} {
    global SROrbitStatus
    set SROrbitStatus $text
    update
    bell
}

proc MakeConfigFrame {widget args} {
    global hResponseDir vResponseDir 
    global plane Polynomial fromReference
    global SensitiveWidgetList
    global dataDir plane
    APSParseArguments {parent}

    set w $parent$widget.frame
    APSFrame $widget -parent $parent -label "Configuration options" \
      -contextHelp "Frame to specify additional options, such as the directory of the response file, the type of bpm data, validity ranges for the sddscontrollaw tests file."

    if {1} {
    set widgetList [APSTabFrame .planes -parent $parent$widget.frame -label "" \
                      -labelList "Horizontal Vertical" -width 570 -height 100 \
                      -commandList {{setCorrPlane H} {setCorrPlane V}} ]

    pack $parent$widget.frame.planes -side top
    $parent$widget.frame.planes.frame.tn select 0
    lappend SensitiveWidgetList $parent$widget.frame.planes.frame.tn
    set windex 0

    # Horizontal Response Directory
    set tabwidget [lindex $widgetList $windex]
    incr windex
    APSFrame .dir -parent $tabwidget -label "" \
      -contextHelp "Frame to specify directories in which files related to horizontal plane correction are found."
    set w $tabwidget.dir.frame
    APSLabeledEntry .responseDir -parent $w -label "Configuration" \
      -textVariable hResponseDir -width 40 -contextHelp \
      "Name of the directory for the response file for the HORIZONTAL plane which can be used with sddscontrollaw."
    APSButton .install -parent $w.responseDir \
      -text I -packOption "-side right" \
      -command "InstallFile -link h.default -fileVariable hResponseDir" \
      -contextHelp "Installs the directory selected (must be a simple directory, not a link) as the new horizontal response directory."
    APSButton .dir -parent $w.responseDir \
      -text F -packOption "-side right" \
      -command "findDir -dirVariable hResponseDir -filter h.*;GetBPMAndCorrectorType -fileVariable hResponseDir" \
      -contextHelp "Bring up a directory selection dialog box to choose the directory."
    APSFrame .type -parent $w 
    $w.type configure -relief flat -bd 0
    set w $w.type.frame
    APSLabeledEntry .type1 -parent $w -label "bpm type:" \
      -textVariable hBpmType -width 15 -contextHelp \
      "bpm type: DP or plain." -packOption  "-side left"
    APSLabeledEntry .type2 -parent $w -label "corrector type:" \
      -textVariable hCorrectorType -width 15 -contextHelp \
      "corrector type: DP, plain or dynamic." -packOption "-side left"
    APSButton .get -parent $w \
      -text Get -packOption "-side right" \
      -command "GetBPMAndCorrectorType -fileVariable hResponseDir" \
      -contextHelp "get the bpm and corrector type from the configuration file"


    # Vertical Response Directory
    set tabwidget [lindex $widgetList $windex]
    incr windex
    APSFrame .dir -parent $tabwidget -label ""  \
      -contextHelp "Frame to specify directories in which files related to vertical plane correction are found."

    set w $tabwidget.dir.frame
    APSLabeledEntry .responseDir -parent $w -label "Configuration" \
      -textVariable vResponseDir -width 40 -contextHelp \
      "Name of the directory for the response file for the VERTICAL plane which can be used with sddscontrollaw."
    APSButton .install -parent $w.responseDir \
      -text I -packOption "-side right" \
      -command "InstallFile -link v.default -fileVariable vResponseDir" \
      -contextHelp "Installs the directory selected (must be a simple directory, not a link) as the new vertical response file."
    APSButton .dir -parent $w.responseDir \
      -text F -packOption "-side right" \
      -command "findDir -dirVariable vResponseDir -filter v.*;GetBPMAndCorrectorType -fileVariable vResponseDir" \
      -contextHelp "Bring up a directory selection dialog box to choose the directory."

    
    APSFrame .type -parent $w 
    $w.type configure -relief flat -bd 0
    set w $w.type.frame
    APSLabeledEntry .type1 -parent $w -label "bpm type:" \
      -textVariable vBpmType -width 15 -contextHelp \
      "bpm type: DP or plain." -packOption  "-side left"
    APSLabeledEntry .type2 -parent $w -label "corrector type:" \
      -textVariable vCorrectorType -width 15 -contextHelp \
      "corrector type: DP, plain or dynamic." -packOption "-side left"
    APSButton .get -parent $w \
      -text Get -packOption "-side right" \
      -command "GetBPMAndCorrectorType -fileVariable vResponseDir" \
      -contextHelp "get the bpm and corrector type from the configuration file"
    }
    set w $parent$widget.frame
   # APSRadioButtonFrame .plane -parent $w -variable plane -valueList {h v} \
   #   -buttonList {horizontal vertical} -orientation horizontal -label "plane: " \
    #  -commandList {"setCorrPlane H" "setCorrPlane V"}
    APSLabeledOutput .current -parent $w -textVariable CurrentPolynomial \
      -label "Current Polynomial (20 - 20 term;  3 - 3 term): " 
      
    APSRadioButtonFrame .poly -parent $w  -label "Switch Polynomial to: " \
      -variable Polynomial -buttonList {20-term 3-term} \
      -valueList {20 3}  -orientation horizontal \
      -contextHelp "choose the polynomial to switch to." 
 #   APSRadioButtonFrame .from -parent $w -variable fromReference -buttonList {Ref. IOC} \
 #     -valueList {1 0}  -orientation horizontal \
   #   -contextHelp "Apply offsets + setpoints from files or IOC "  -label "Apply from: "
}

proc setCorrPlane {value} {
    global Plane plane Coord coord
    if ![string compare [string toupper $value] "H"] {
        set Plane H
        set plane h
        set coord x
        set Coord X
    } else {
        set Plane V
        set plane v
        set coord y
        set Coord Y
    }
    SetMainStatus "$Plane Plane selected."
    return
}

proc MakeReferenceFileFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label "Reference files" \
      -contextHelp "Frame to choose reference files for 20-term and 3-term polynomials."
    
    set widgetList [APSTabFrame .files -parent $parent$widget.frame -label "" \
                      -labelList "20-term 3-term" -width 900 -height 230 ]
    pack $parent$widget.frame.files -side top

    $parent$widget.frame.files.frame.tn select 1


    #20-term
    set w0 [lindex $widgetList 0]
    global offsetReferenceFile gainReferenceFile setpointReferenceFile from20TermFile newGainReferenceFile
    APSFrameGrid .grid -parent $w0 -yList {y1 y2 y3 y4}
    set w $w0.grid.y1
    APSLabeledEntry .offsetentry -parent $w -label "Offset:  " \
      -textVariable  offsetReferenceFile -width 80 -contextHelp \
      "name of the 20-term offset reference file"
    APSButton .install -parent $w.offsetentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type OffsetAO -fileVar offsetReferenceFile" \
      -contextHelp "Apply the 20-term offset PVs"
    $w.offsetentry.install.button configure -state disabled
    APSButton .dir -parent $w.offsetentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar offsetReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the offset reference file."

    set w $w0.grid.y2
    APSLabeledEntry .setpointentry -parent $w -label "Setpoint: " \
      -textVariable  setpointReferenceFile -width 80 -contextHelp \
      "name of the 20-term setpoint reference file"
    APSButton .install -parent $w.setpointentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type SetpointAO -fileVar setpointReferenceFile" \
      -contextHelp "Apply the 20-term setpoint PVs"
    $w.setpointentry.install.button configure -state disabled
    APSButton .dir -parent $w.setpointentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar setpointReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the setpoint reference file."
    
    set w $w0.grid.y3
    APSLabeledEntry .gainentry -parent $w -label "Gain:   " \
      -textVariable  gainReferenceFile -width 80 -contextHelp \
      "name of the 20-term gain reference file"
    APSButton .install -parent $w.gainentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type GainAO -fileVar gainReferenceFile" \
      -contextHelp "Apply the 20-term gain PVs"
    $w.gainentry.install.button configure -state disabled
    APSButton .dir -parent $w.gainentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar gainReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the gain reference file."
    set w $w0.grid.y4
    APSLabeledEntry .newgainentry -parent $w -label "Gain    \nAdjustment:" \
      -textVariable  newGainReferenceFile -width 80 -contextHelp \
      "name of the 20-term gain reference file"
    APSButton .install -parent $w.newgainentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type GainAO -fileVar gainReferenceFile" \
      -contextHelp "Apply the 20-term gain PVs"
    $w.newgainentry.install.button configure -state disabled
    APSButton .dir -parent $w.newgainentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar newGainReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the second gain reference file."
 
   #3Term
    global 3TermOffsetReferenceFile 3TermSetpointReferenceFile 3TermGainReferenceFile
    global new3TermGainReferenceFile 3TermGainReferenceFile
    global from3TermFile
    set w0 [lindex $widgetList 1]
    APSFrameGrid .grid -parent $w0 -yList {y1 y2 y3 y4}
    set w $w0.grid.y1
    APSLabeledEntry .offsetentry -parent $w -label "Offset:  " \
      -textVariable  3TermOffsetReferenceFile -width 80 -contextHelp \
      "name of the 3Term offset reference file"
    APSButton .install -parent $w.offsetentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type offset -fileVar 3TermOffsetReferenceFile" \
      -contextHelp "Apply the 3Term offset PVs"
    $w.offsetentry.install.button configure -state disabled
    APSButton .dir -parent $w.offsetentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar offsetReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the offset reference file."
    set w $w0.grid.y2
    APSLabeledEntry .setpointentry -parent $w -label "Setpoint: " \
      -textVariable  3TermSetpointReferenceFile -width 80 -contextHelp \
      "name of the 20-term setpoint reference file"
    APSButton .install -parent $w.setpointentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type SetpointAO -fileVar 3TermSetpointReferenceFile" \
      -contextHelp "Apply the 3-Term setpoint PVs"
    $w.setpointentry.install.button configure -state disabled
    APSButton .dir -parent $w.setpointentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar setpointReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the setpoint reference file."
    
    set w $w0.grid.y3
    APSLabeledEntry .gainentry -parent $w -label "Gain:   " \
      -textVariable  3TermGainReferenceFile -width 80 -contextHelp \
      "name of the 20-term gain reference file"
    APSButton .install -parent $w.gainentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type gain -fileVar 3TermGainReferenceFile" \
      -contextHelp "Apply the 3-Term gain PVs"
    $w.gainentry.install.button configure -state disabled
    APSButton .dir -parent $w.gainentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar 3TermGainReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the gain reference file."

    set w $w0.grid.y4
    APSLabeledEntry .newgainentry -parent $w -label "Gain     \nAdjustment:" \
      -textVariable  new3TermGainReferenceFile -width 80 -contextHelp \
      "name of the 20-term gain reference file"
    APSButton .install -parent $w.newgainentry \
      -text I -packOption "-side right" \
      -command "ApplyFromFile -type GainAO -fileVar gainReferenceFile" \
      -contextHelp "Apply the 20-term gain PVs"
    $w.newgainentry.install.button configure -state disabled
    APSButton .dir -parent $w.newgainentry \
      -text F -packOption "-side right" \
      -command "findFiles -fileVar new3TermGainReferenceFile" \
      -contextHelp "Bring up a file selection dialog box to choose the second gain reference file."

    
}

proc DisableTabs {} {
    global SensitiveWidgetList
    foreach widget $SensitiveWidgetList {
        $widget configure -state disabled
    }
}

proc EnableTabs {} {
    global SensitiveWidgetList
    foreach widget $SensitiveWidgetList {
        $widget configure -state normal
    }
}

proc MakeActionFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label "Action Buttons" \
      -contextHelp "Frame for containing controllaw buttons." -packOption "-side top"

    set w0 $parent$widget.frame
    APSFrameGrid .grid -parent $w0 -xList {x1 x2 x3 x4} 
    set w $w0.grid.x1
    APSFrame .act -parent $w -label "Action for both plane" \
	-contextHelp "contains switch polynomial action buttons" \
	-packOption "-side top"
    set w $w.act.frame
    
    APSButton .start -parent $w -text SWITCH -command \
      "APSFreezeVars [list Plane plane coord Coord]; DisableTabs; SwitchPolynomials; APSUnfreezeVars [list Plane plane coord Coord]; EnableTabs" \
      -contextHelp "Applies offsets, setpoints and gains corresponding to the  selected polynomial above and set the polynomial PVs" \
        -packOption "-side top"
    APSButton .start1 -parent $w -text MultiplyByGain -command \
      "APSFreezeVars [list Plane plane coord Coord]; DisableTabs; MultiplyByGain; APSUnfreezeVars [list Plane plane coord Coord]; EnableTabs" \
      -contextHelp "Apply offsets, setpoints, and gains from files multiplied by values from gain adjustment file for selected polynomial" -packOption "-side top"
    APSButton .start2 -parent $w -text SplitBPMs -command "SplitBPMsByType" -packOption "-side top" \
      -contextHelp "Split the bpms by devicetype for polynomial calcuation (needed if config.sdds changed)"
    
    set w $w0.grid.x2
    APSFrame .setup -parent $w -label "Setup x or y" -packOption "-side top"
    set w $w.setup.frame
    APSButton .setgain -parent $w -text "Apply New Gain" -packOption "-side top" \
      -contextHelp "Apply bpm gains" \
      -command "RestoreBpmGains"
    APSButton .setoffset -parent $w -text "Apply Offset" -packOption "-side top" \
      -contextHelp "Apply bpm offsets and setpoints" \
      -command "RestoreOffsets"

    set w $w0.grid.x3
    APSFrame .setup -parent $w -label "Setup x and y" -packOption "-side top"
    set w $w.setup.frame
    APSButton .poly3 -parent $w -text "Set 3-Poly" \
      -packOption "-side top" \
      -command " ChangePolynomials -poly 3" \
      -contextHelp "set 3-term polynomial"
    lappend DPButtonList $w.poly3.button
    APSButton .poly20 -parent $w -text "Set 20-Poly" \
      -packOption "-side top"  \
      -command " ChangePolynomials -poly 20" \
      -contextHelp "set 20-term polynomial"
    APSButton .setgain -parent $w -text "Apply New Gain" \
      -packOption "-side top" \
      -contextHelp "Apply bpm gains" \
      -command "RestoreBpmGains-inputcoord both"
    APSButton .setoffset -parent $w -text "Apply Offset" -packOption "-side top" \
      -contextHelp "Apply bpm offsets and setpoints" \
      -command "RestoreOffsets -inputcoord both"
    

    set w $w0.grid.x4
    APSFrame .information -parent $w -label "Information" -packOption "-side top"
    set w $w.information.frame
    APSButton .compare1 -parent $w -text "CompareIOCWithPolynomial" -packOption "-side top" \
      -command "CompareReadbackIOCWithPolynomial" \
	-contextHelp "compare the readback with polynormial calculations from reading Vx,Vy"
    APSButton .compare2 -parent $w -text "ComparePolynomials" -packOption "-side top" \
      -command "Compare" \
	-contextHelp "compare 3-term polynomail results with 20-term ref."
}

proc findFiles {args} {
    set fileVar ""
    APSParseArguments {fileVar}
    global $fileVar
    set file [set $fileVar] 
    if ![string length $file] {
        set dir /home/helios/oagData/SCR/snapshots/
    } else {
        set dir [file dir $file]
    }
    set choosedfile [APSFileSelectDialog .chooseInputFile -listDir $dir -pattern *]
    if [string length $choosedfile] {
        set $fileVar $choosedfile
    }
} 

# **************************** findDir ********************************
proc findDir {args} {
    # General purpose directory selection
    # args is passed to APSFileSelectDialog
    set dirVariable ""
    set trim 0
    APSParseArguments {dirVariable trim}
    global $dirVariable

    set dirName [eval dirSelectDialog .findDirDialog $args]
    if [string length $dirName] {
        # Trim the current working directory from the name
        if $trim {
            set dirName [file tail $dirName]
        }
        set $dirVariable $dirName
    }
}

proc dirSelectDialog {widget args} {
    global dirSelection
    set filter ""
    APSParseArguments {filter}
    if [string length $filter] {
        set dirList [lsort -decreasing [glob -nocomplain $filter]]
    } else {
        set dirList [lsort -decreasing [glob -nocomplain *]]
    }
    APSScrolledListWindow $widget \
      -name "Directory selection" \
      -label "Select a directory" \
      -itemList $dirList \
      -selectionVar dirSelection
    tkwait variable dirSelection
    return $dirSelection
}

proc GetBPMAndCorrectorType {args} {
    set fileVariable ""
    global hCorrectorType vCorrectorType hBpmType vBpmType datapool
    APSParseArguments {fileVariable}
    set plane [string range $fileVariable 0 0]
    global $fileVariable dataDir
    set file $dataDir/[set $fileVariable]/config
    set names [APSGetSDDSParameter -fileName $file -parameter NameType]
    set types [APSGetSDDSParameter -fileName $file -parameter PVType]
    set i [lsearch -exact $names MonitorNames]
    set j [lsearch -exact $names CorrectorNames]
    if {$i==-1 || $j==-1} {
        SetMainStatus "NameType paremeter in config file is not correct!"
        return
    }
    set ${plane}BpmType [lindex $types $i]
    set ${plane}CorrectorType [lindex $types $j]
    set datapool 0
    set type [set ${plane}BpmType]
    if [string compare $type DP]==0 {
	set datapool 1
    }
}

proc ChangePolynomials {args} {
    set poly ""
    
    APSParseArguments {poly}
    switch $poly {
        20 {
            set value 0
        }
        3 {
            set value 1
        }
        default {
            return -code error "Invalid poly type, $type!"
        }
    }
    
    #for other bpms
    set p0SectorList [APSSRGetWorkingP0SectorsList -iocs 1]
    set settingList ""
    foreach sector $p0SectorList {
        foreach type {5mm 8mm 8mmR 19mm P0} {
            lappend settingList "S:bpm${sector}:${type}:PolySelectMO.VAL=$value"
        }
    }
    # puts "$settingList"
    if [catch {exec cavput -list=[join $settingList ,] -pend=30} result] {
        return -code error $result
    }
    #for normal bpms
    if [catch {exec cavput -list=S:bpm -range=beg=1,end=35,interval=2 \
                 -list=:PolynomialSelectMO.VAL=${value} -pend=30
        exec cavput -list=S:bpm -range=beg=36,end=40 \
                 -list=:PolynomialSelectMO.VAL=${value} -pend=30 \
             } result] {
        return -code error "Error in setting polynomial to normal: $result"
    }
}

proc CompareReadbackIOCWithPolynomial {args} {
    global offsetReferenceFile
    set config /home/helios/oagData/sr/BPMStatus/config.sdds
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID CompareIOC -fileList  "$tmpRoot.snap $tmpRoot.req $tmpRoot.req1 $tmpRoot.config"
    APSAddToTmpFileList -ID CompareIOC -fileList  "$tmpRoot.snap.total $tmpRoot.req.total $tmpRoot.readback.snap"
    if [catch {exec sddsprocess $config $tmpRoot.config "-match=col,DeviceType=,!,DeviceType=Xray*,!,&" } result] {
        APSDeleteTmpFileList -ID CompareIOC
        return -code error $result
    }
    APSAddToTmpFileList -ID CompareIOC -fileList  "$tmpRoot.readback $tmpRoot.readback.req"
    if [catch {exec sddsprocess \
                 $offsetReferenceFile -pipe=out \
                 "-match=col,ControlName=*OffsetAO,ControlName=*BM*,!,&,ControlName=*ID*,!,&,ControlName=*:P0*,!,&" | \
                 sddsconvert -pipe -rename=col,ControlName=BPMName | \
                 sddsprocess -pipe=in $tmpRoot.req1 \
                 -edit=col,ControlName,BPMName,%/:ms:x:OffsetAO/:ms.XAVE/%/:ms:y:OffsetAO/:ms.YAVE/
        exec sddsprocess $offsetReferenceFile -pipe=out \
                 "-match=col,ControlName=*OffsetAO,ControlName=*BM*,!,&,ControlName=*ID*,!,&,ControlName=*:P0*,!,&" | \
                 sddsconvert -pipe -rename=col,ControlName=BPMName | \
                 sddsprocess -pipe=in -edit=col,ControlName,BPMName,%/:OffsetAO// $tmpRoot.readback.req
        exec sddscombine $tmpRoot.readback.req $tmpRoot.req1 $tmpRoot.req.total -merge
        exec burtrb -f $tmpRoot.req.total -o $tmpRoot.snap.total
        exec sddsselect $tmpRoot.snap.total $tmpRoot.req1 -match=ControlName $tmpRoot.snap
        exec sddsselect $tmpRoot.snap.total $tmpRoot.readback.req -match=ControlName $tmpRoot.readback.snap } result] {
        APSDeleteTmpFileList -ID CompareIOC
        return -code error $result
    }
    #read the gain
    APSAddToTmpFileList -ID CompareIOC -fileList "$tmpRoot.snap.x $tmpRoot.snap.y $tmpRoot.gain.req $tmpRoot.gain"
    APSAddToTmpFileList -ID CompareIOC -fileList "$tmpRoot.gain1 $tmpRoot.vx $tmpRoot.vy $tmpRoot.vxy"
    if [catch {exec sddsprocess $tmpRoot.snap $tmpRoot.snap.x \
                 -match=col,ControlName=*XAVE -scan=col,Vxk1,ValueString,%lf \
                 -edit=col,DeviceName,ControlName,%/:ms.XAVE//
        exec sddsprocess $tmpRoot.snap $tmpRoot.snap.y \
                 -match=col,ControlName=*YAVE -scan=col,Vyk1,ValueString,%lf  \
                 -edit=col,DeviceName,ControlName,%/:ms.YAVE//
        exec sddsconvert $tmpRoot.snap.x -delete=col,ControlName -pipe=out | \
                 sddsprocess -pipe=in $tmpRoot.gain.req \
                 -edit=col,ControlName,DeviceName,ei/:normal_bi/
        exec burtrb -f $tmpRoot.gain.req -o $tmpRoot.gain } result] {
        APSDeleteTmpFileList -ID CompareIOC
        return -code error $result
    }
    if [catch {exec sddsprocess $tmpRoot.gain $tmpRoot.gain1 \
                 "-edit=col,Value,ValueString,%/\"Hi Gain\"/4/%/\"Lo Gain\"/1/" \
                 -scan=col,gain,Value,%lf "-define=col,Gain,gain 2048 *" \
                 -edit=col,DeviceName,ControlName,%/:normal_bi// 
        exec sddsxref $tmpRoot.snap.x $tmpRoot.gain1 -match=DeviceName -take=Gain -pipe=out | \
                 sddsprocess -pipe=in $tmpRoot.vx "-redefine=col,Vxk1,Vxk1 Gain /"
        exec sddsxref $tmpRoot.snap.y $tmpRoot.gain1 -match=DeviceName -take=Gain -pipe=out | \
                 sddsprocess -pipe=in $tmpRoot.vy "-redefine=col,Vyk1,Vyk1 Gain /"
        exec sddsxref $tmpRoot.vx $tmpRoot.vy -match=DeviceName -take=Vyk1 -pipe=out | \
                 sddsconvert -pipe=in -retain=col,DeviceName,Vxk1,Vyk1 $tmpRoot.vxy } result ] {
        APSDeleteTmpFileList -ID CompareIOC
        return -code error $result
    }
    APSAddToTmpFileList -ID CompareIOC -fileList "$tmpRoot.readback $tmpRoot.readback.x $tmpRoot.readback.y"
    APSAddToTmpFileList -ID CompareIOC -fileList "$tmpRoot.readback.snap $tmpRoot.compare $tmpRoot.bpm"
    if [catch {exec cavget -list=S:bpm1:PolynomialSelectMO -num -pend=10 -printErrors} result] {
	return -code error $result
    }
    if !$result {
	set poly 20
    } else {
	set poly 3
    }
    if [catch {APSCalculatePositionTroughPolynormial -input $tmpRoot.vxy -output $tmpRoot.readback \
                 -bpmType Offset -poly ${poly}} result] {
        return -code error $result
    }
    if [catch {exec sddsconvert $tmpRoot.readback -retain=col,DeviceName,X${poly}Offset -pipe=out \
                 -rename=col,X${poly}Offset=ReadbackPoly | \
                 sddsprocess -pipe=in -edit=col,ControlName,DeviceName,ei/:ms:x/ $tmpRoot.readback.x
        exec sddsconvert $tmpRoot.readback -retain=col,DeviceName,Y${poly}Offset \
                 -rename=col,Y${poly}Offset=ReadbackPoly -pipe=out | \
                 sddsprocess -pipe=in -edit=col,ControlName,DeviceName,ei/:ms:y/ $tmpRoot.readback.y
        exec sddscombine $tmpRoot.readback.x $tmpRoot.readback.y $tmpRoot.poly -merge } result] {
        APSDeleteTmpFileList -ID CompareIOC
        return -code error $result
    }
    APSAddToTmpFileList -ID CompareIOC -fileList "$tmpRoot.readback.snap $tmpRoot.compare $tmpRoot.compare.print"
    APSAddToTmpFileList -ID CompareIOC -fileList "$tmpRoot.ioc $tmpRoot.poly"
    if [catch {exec sddsprocess $tmpRoot.readback.snap $tmpRoot.ioc \
                 -scan=col,ReadbackIOC,ValueString,%lf 
        exec sddsxref $tmpRoot.poly $tmpRoot.ioc -pipe=out -match=ControlName -take=ReadbackIOC -nowarn | \
                 sddsprocess -pipe "-define=col,Diff,ReadbackIOC ReadbackPoly -" \
                 "-filter=col,Diff,-1e-3,1e-3,!" \
		   "-print=par,Title,compare IOC with $poly term polynormial" | \
                 sddsconvert -pipe=in $tmpRoot.compare -retain=col,ControlName,DeviceName,*Readback*,Diff } result] {
       # APSDeleteTmpFileList -ID CompareIOC
        return -code error $result
    }
    if [catch {exec sddsprintout $tmpRoot.compare $tmpRoot.compare.print \
                 -col -par=Title } result] {
        return -code error "$result"
    }
    
    APSFileDisplayWindow .diff -fileName $tmpRoot.compare.print -width 80 -height 30 -printCommand "enscript -r"
}

proc RestoreOffsetsFromFile {args} {
    global coord waveformFileDir
    set inputcoord ""
    set datapool 0
    set offsetFile ""
    set setpointFile ""
    APSParseArguments {inputcoord datapool offsetFile setpointFile}
    
    if ![string length $inputcoord] {
        set inputcoord $coord
    }

    switch $inputcoord {
        x {
            set match1 "-match=col,ControlName=*x*OffsetAO"
            set match2 "-match=col,"-match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,&",ControlName=*x*,&"
            set planes x
        }
        y { 
            set match1 "-match=col,ControlName=*y*OffsetAO"
            set match2 "-match=col,"-match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,&",ControlName=*y*,&"
            set planes y 
        }
        both {
            set match1 "-match=col,ControlName=*OffsetAO"
            set match2 "-match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,&"
            set planes {x y}
        }
    }
    SetMainStatus "Restore Offsets and Setpoints in $inputcoord plane from file ..."
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.*"
    APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.ref1 $tmpRoot.ref2 $tmpRoot.snap.$inputcoord"
    if [catch {exec sddsprocess $offsetFile $tmpRoot.ref1 $match1
        exec sddsprocess $setpointFile $tmpRoot.ref2 \
                 $match2
        exec sddscombine $tmpRoot.ref1 $tmpRoot.ref2 \
                 -merge $tmpRoot.snap.$inputcoord -overwrite} result] {
     #   APSDeleteTmpFileList -ID RestoreDPOffsets
        return -code error $result
    }
    APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.offset $tmpRoot.adjust"
    set datapool 1
    if $datapool {
        APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.adjust.x $tmpRoot.adjust.y"
        if [catch {exec sddsprocess $offsetFile $tmpRoot.offset -match=col,ControlName=*OffsetAO \
                     -scan=col,Offset,ValueString,%lf \
                     -edit=col,BPMName,ControlName,%/:OffsetAO// \
                     -edit=col,DeviceName,BPMName,%/:ms:x//%/:ms:y// 
            exec sddsprocess $setpointFile -pipe=out \
                     -match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,& \
                     -scan=col,Setpoint,ValueString,%lf \
                     -edit=col,BPMName,ControlName,%/:SetpointAO// \
                     -edit=col,DeviceName,BPMName,%/:ms:x//%/:ms:y// | \
                     sddsxref -pipe $tmpRoot.offset -match=BPMName -take=Offset | \
                     sddsprocess -pipe "-define=col,Waveform,Offset Setpoint +" | \
                     sddsconvert -pipe=in -retain=col,DeviceName,Waveform,BPMName $tmpRoot.adjust 
            exec sddsprocess $tmpRoot.adjust $tmpRoot.adjust.x -match=col,BPMName=*x 
            exec sddsprocess $tmpRoot.adjust $tmpRoot.adjust.y -match=col,BPMName=*y } result] {
         #   APSDeleteTmpFileList -ID RestoreDPOffsets
            return -code error $result
        }
        set fileList ""
        foreach plane $planes {
            foreach bpmType {p0 id bm rf} {
                if {[string compare $bpmType bm]==0} {
                    if [string compare $plane x]==0 continue
                    set waveformFile $waveformFileDir/bmBpmInfo.sdds
                } else {
                    set waveformFile $waveformFileDir/${bpmType}[string toupper $plane]BpmInfo.sdds
                }
                if [catch {exec sddsconvert $waveformFile -pipe=out \
                             -retain=column,Index,DeviceName -retain=parameter,WaveformPV \
                             | sddsxref -pipe=in $tmpRoot.adjust.$plane -fillIn -nowarning \
                             -match=DeviceName -take=Waveform $tmpRoot.$bpmType \
                         } result] {
                    APSDeleteTmpFileList -ID RestoreDPOffset
                    return -code error $result
                }
                lappend fileList $tmpRoot.$bpmType
            }
        }
        APSAddToTmpFileList -ID RestoreDPOffsets -fileList $fileList
        APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.vectorAdjust.$inputcoord"
        set output $tmpRoot.vectorAdjust.$inputcoord
        if [catch {eval exec sddscombine $fileList -pipe=out \
                     | sddsprocess -pipe=in $output \
                     -reedit=parameter,WaveformPV,%/:Out:/:Adjust:/
            exec sddswput $output} result] {
            # APSDeleteTmpFileList -ID RestoreDPOffsets
            APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
            SetMainStatus "Error!"
            return
        }
    }
    if [catch {exec sddscasr -restore $tmpRoot.snap.$inputcoord } result] {
        return -code error "Error in restoring offset and setpoints, $result"
    }
    SetMainStatus "Restore $inputcoord plane offset+setpoins done!"
}


proc RestoreOffsets {args} {
    global Polynomial fromReference plane CurrentPolynomial
    global offsetReferenceFile setpointReferenceFile
    global 3TermOffsetReferenceFile 3TermSetpointReferenceFile
    global hBpmType vBpmType coord
    
    set inputcoord ""
    APSStrictParseArguments {inputcoord}
    if ![string length $inputcoord] {
        set inputcoord $coord
    }
    if ![string length $Polynomial] {
        SetMainStatus "The polynomial is not choosen!"
        return
    }
    switch $inputcoord {
        x {
            set plane h
        }
        y {
            set plane v
        }
	both {
	    set plane h
	}
    }
    GetBPMAndCorrectorType -fileVariable ${plane}ResponseDir
    set bpmType [set ${plane}BpmType]
    if ![string compare $bpmType DP] {
        set datapool 1
    } else {
        set datapool 0
    }
    
    GetPolynomial
    if {$CurrentPolynomial == $Polynomial && !$fromReference} {
        return -code error "The current polynomial is $poly, can not switch to itself from IOC!"
    }
    switch $Polynomial {
        20 {
            #note that transfer from 3 term to 20 term, therefore, the ref. files belong 3-term
            set offsetFile $3TermOffsetReferenceFile
            set setpointFile $3TermSetpointReferenceFile
        }
        3 {
            #note that transfer from 20 term to 3 term, therefore, the ref. files belong 3-term
            set offsetFile $offsetReferenceFile
            set setpointFile $setpointReferenceFile
        }
        default {
            return -code error "Unknow polynomial (should be 20 or 3)"
        }
    }
    if {$CurrentPolynomial == $Polynomial && $fromReference} {
        if [catch {RestoreOffsetsFromFile -inputcoord $inputcoord -datapool $datapool \
                     -offsetFile $offsetFile -setpointFile $setpointFile } result] {
            return -code error $result
        }
        #SetMainStatus "Restore offsets done."
        return
    }
    if [catch {TransferOffsetsFromPolynomial -inputcoord $inputcoord -offsetFile $offsetFile \
                 -setpointFile $setpointFile -datapool $datapool} result] {
        return -code error $result
    }
    
}
   
proc GetPolynomial {args} {
    global CurrentPolynomial
    
    if [catch {exec cavget -list=S:bpm1:PolynomialSelectMO -num -pend=10 -printErrors} result] {
        return -code error $result
    }
    if !$result {
        set CurrentPolynomial 20
    } else {
        set CurrentPolynomial 3
    }
}

proc TransferOffsetsFromPolynomial {args} {
    global offsetResultsFile adjustResultsFile CurrentPolynomial Polynomial
    global 3TermOffsetResultsFile 3TermAdjustResultsFile
    global dataDir hResponseDir plane vResponseDir

    set datapool 0
    set offsetFile ""
    set setpointFile ""
    set inputcoord ""
    APSStrictParseArguments {inputcoord setpointFile offsetFile datapool}
    
    SetMainStatus "Transfer offsets+setpoints from $CurrentPolynomial term to $Polynomial term ..." 
    #create files
    if [catch {CalculateOffsetsFromPolynomial -offsetFile $offsetFile \
                 -setpointFile $setpointFile -switchTo $Polynomial} result] {
        return -code error $result
    }
   
    switch $Polynomial {
        20 {
            set offset $offsetResultsFile
            set adjust $adjustResultsFile
        }
        3 {
            set offset $3TermOffsetResultsFile
            set adjust $3TermAdjustResultsFile
        }
    }
    if [string compare $inputcoord both]==0 {
	if [catch {exec sddscasr -restore $offset} result] {
	    return -code error $result
	}
	if [catch {exec sddswput $adjust} result] {
	    return -code error $result
	}
	SetMainStatus "done."
	return
    }

    APSAddToTmpFileList -ID TransferOffsetsFromPolynomial -fileList "$offset.$inputcoord"
    set config $dataDir/[set ${plane}ResponseDir]/config
    if [catch {exec sddsprocess $offset -match=col,ControlName=*${inputcoord}* \
                 $offset.$inputcoord} result] {
        return -code error $result
    }
    set Coord [string toupper $inputcoord]
   
    APSAddToTmpFileList -ID TransferOffsetsFromPolynomial -fileList "$adjust.$Coord"
    set datapool 1
    if $datapool {
        if [catch {exec sddsprocess $adjust -match=par,WaveformPV=*${Coord}* $adjust.$Coord 
            exec sddswput $adjust.$Coord} result] {
            return -code error $result
        }
    }
    if [catch {exec sddscasr -restore $offset.$inputcoord } result] {
        return -code error $result
    }
    SetMainStatus "Transfer offsets from $CurrentPolynomial term to $Polynomial term done!"
}

proc CalculateOffsetsFromPolynomial {args} {
    #output results file which contains both planes
    global Polynomial waveformFileDir fromReference
    global offsetResultsFile adjustResultsFile
    global 3TermOffsetResultsFile 3TermAdjustResultsFile
    global offsetReferenceFile setpointReference
    global 3TermOffsetReferenceFile 3TermSetpointReferenceFile
    
    set offsetFile ""
    set setpointFile ""
    set switchTo ""
    APSStrictParseArguments {setpointFile offsetFile switchTo}
    
    switch $switchTo {
        20 {
            set fromPoly 3
            set outputoffset $offsetResultsFile
            set outputadjust $adjustResultsFile
        }
        3 {
            set fromPoly 20
            set outputoffset $3TermOffsetResultsFile
            set outputadjust $3TermAdjustResultsFile
        }
        default {
            return -code error "Unknown polynomial!"
        }
    }
  
     #if files have already been created and they are newer than the referencefile, return
   # if {[file exist $outputoffset] && \
   #       [file exist $outputadjust] && [file mtime $outputoffset] > [file mtime $offsetFile] && \
    #      [file mtime $outputoffset] > [file mtime $setpointFile] } {
     #   return
   # }
    set tmpRoot /tmp/[APSTmpString]
    if !$fromReference {
        APSAddToTmpFileList -ID DPOffsetCalculation -fileList  "$tmpRoot.snap $tmpRoot.req"
        if [catch {exec sddsprocess \
                     $setpointFile $tmpRoot.req \
                     "-match=col,ControlName=*OffsetAO,ControlName=*SetpointAO,|,ControlName=*FTSetpointAO,!,&"
            exec burtrb -f $tmpRoot.req -o $tmpRoot.snap} result] {
            APSDeleteTmpFileList -ID SetDPOffsets
            return -code error $result
        }
        set snapshot $tmpRoot.snap
    } else {
        APSAddToTmpFileList -ID DPOffsetCalculation -fileList  "$tmpRoot.snap $tmpRoot.ref1 $tmpRoot.ref2"
        if [catch {exec sddsprocess $offsetFile $tmpRoot.ref1 \
                     -match=col,ControlName=*OffsetAO
            exec sddsprocess $setpointFile $tmpRoot.ref2 \
                     -match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,&
            exec sddscombine $tmpRoot.ref1 $tmpRoot.ref2 -merge $tmpRoot.snap } result] {
            APSDeleteTmpFileList -ID SetDPOffsets
            return -code error $result
        }
        set snapshot $tmpRoot.snap
    }
    #get offset and setpoint value from the normal polynomial mode
    if [catch {exec sddsprocess $snapshot $tmpRoot.offset \
                 -match=col,ControlName=*OffsetAO \
                 -edit=col,BPMName,ControlName,%/:ms//%/:OffsetAO// \
                 -scan=col,Offset,ValueString,%lf } result] {
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList $tmpRoot.offset
    if [catch {exec sddsprocess $snapshot $tmpRoot.setpoint \
                 "-match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,&" \
                 -edit=col,BPMName,ControlName,%/:ms//%/:SetpointAO// \
                 -scan=col,Setpoint,ValueString,%lf  } result] {
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList $tmpRoot.setpoint
    if [catch {exec sddsxref $tmpRoot.offset $tmpRoot.setpoint -match=BPMName -pipe=out -nowarnings | \
                 sddsprocess -pipe=in "-define=col,Adjust,Offset Setpoint +" $tmpRoot.adjust} result] {
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList $tmpRoot.adjust
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.xoffset $tmpRoot.yoffset"
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.xadjust $tmpRoot.yadjust"
    if [catch {exec sddsprocess $tmpRoot.offset -match=col,BPMName=*x \
                 -pipe=out -edit=col,DeviceName,BPMName,%/:x// | \
                 sddsconvert -pipe -rename=col,Offset=XOffset | \
                 sddsconvert -pipe=in -retain=col,DeviceName,XOffset $tmpRoot.xoffset
        exec sddsprocess $tmpRoot.offset -match=col,BPMName=*y  -pipe=out \
                 -edit=col,DeviceName,BPMName,%/:y// | \
                 sddsconvert -pipe -rename=col,Offset=YOffset | \
                 sddsconvert -pipe=in -retain=col,DeviceName,YOffset $tmpRoot.yoffset
        
        exec sddsxref $tmpRoot.xoffset $tmpRoot.yoffset -match=DeviceName $tmpRoot.offset.sdds } result] {
        return -code error $result
    }
     #for setpoint + offset (adjust)
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.xoffset $tmpRoot.yoffset $tmpRoot.xadjust $tmpRoot.yadjust"
    
    if [catch {exec sddsprocess $tmpRoot.adjust -match=col,BPMName=*x \
                 -pipe=out -edit=col,DeviceName,BPMName,%/:x// | \
                 sddsconvert -pipe -rename=col,Adjust=XAdjust | \
                 sddsconvert -pipe=in -retain=col,DeviceName,XAdjust $tmpRoot.xadjust
        exec sddsprocess $tmpRoot.adjust -match=col,BPMName=*y  -pipe=out \
                 -edit=col,DeviceName,BPMName,%/:y// | \
                 sddsconvert -pipe -rename=col,Adjust=YAdjust | \
                 sddsconvert -pipe=in -retain=col,DeviceName,YAdjust $tmpRoot.yadjust
        
        exec sddsxref $tmpRoot.xadjust $tmpRoot.yadjust -match=DeviceName $tmpRoot.adjust.sdds } result] {
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.offset.sdds $tmpRoot.adjust.sdds"
    #calculate counts from $fromPoly
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.Vxy.offset $tmpRoot.Vxy.adjust"
   
    if [catch {APSCalculateCountsFromPolynomial -input $tmpRoot.offset.sdds -poly $fromPoly \
                 -output $tmpRoot.Vxy.offset \
                 -bpmType Offset} result] {
        return -code error "APSCalculateCountsFromPolynomial: $result"
    }
    if [catch {APSCalculateCountsFromPolynomial -input $tmpRoot.adjust.sdds \
                 -output $tmpRoot.Vxy.adjust -poly $fromPoly \
                 -bpmType Adjust} result] {
        return -code error $result
    }
     #calculate offset and adjust of $Polynomial
    if [catch {APSCalculatePositionTroughPolynormial -input $tmpRoot.Vxy.offset -output $tmpRoot.offset \
                 -bpmType Offset -poly $Polynomial } result] {
        return -code error $result
    }
    if [catch {APSCalculatePositionTroughPolynormial -input $tmpRoot.Vxy.adjust -output $tmpRoot.adjust \
                 -bpmType Adjust -poly $Polynomial} result] {
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.offset $tmpRoot.adjust"
    if [catch {exec sddsxref $tmpRoot.offset $tmpRoot.adjust -match=DeviceName -pipe=out | \
                 sddsprocess -pipe "-define=col,X${Polynomial}Setpoint,X${Polynomial}Adjust X${Polynomial}Offset -" \
                 "-define=col,Y${Polynomial}Setpoint,Y${Polynomial}Adjust Y${Polynomial}Offset -" | \
                 sddsconvert -pipe=in -retain=col,DeviceName,X${Polynomial}Setpoint,Y${Polynomial}Setpoint \
                 $tmpRoot.setpoint } result] {
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.adjust $tmpRoot.adjust.x $tmpRoot.adjust.y $tmpRoot.offset.x"
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.offset.y $tmpRoot.setpoint.x $tmpRoot.setpoint.y"
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.result1 $tmpRoot.result2"
    if [catch {exec sddsprocess $tmpRoot.offset -pipe=out \
                 -edit=col,ControlName,DeviceName,ei/:ms:x:OffsetAO/ \
                 -print=col,ValueString,%le,X${Polynomial}Offset | \
                 sddsconvert -pipe=in $tmpRoot.offset.x -delete=col,*Offset
        exec sddsprocess $tmpRoot.offset -pipe=out \
                 -edit=col,ControlName,DeviceName,ei/:ms:y:OffsetAO/ \
                 -print=col,ValueString,%le,Y${Polynomial}Offset  | \
                 sddsconvert -pipe=in $tmpRoot.offset.y -delete=col,*Offset
        exec sddsprocess $tmpRoot.setpoint -pipe=out \
                 -edit=col,ControlName,DeviceName,ei/:ms:x:SetpointAO/ \
                 -print=col,ValueString,%le,X${Polynomial}Setpoint  | \
                 sddsconvert -pipe=in $tmpRoot.setpoint.x -delete=col,*Setpoint
        exec sddsprocess $tmpRoot.setpoint -pipe=out \
                 -edit=col,ControlName,DeviceName,ei/:ms:y:SetpointAO/ \
                 -print=col,ValueString,%le,Y${Polynomial}Setpoint  | \
                 sddsconvert -pipe=in $tmpRoot.setpoint.y -delete=col,*Setpoint
        exec sddscombine $tmpRoot.offset.x  $tmpRoot.offset.y -merge -pipe=out | \
                 sddsprocess -pipe=in $tmpRoot.result1 \
                 -print=col,ControlType,pv  \
                 -print=col,Lineage,- \
                 -define=col,Count,1,type=long 
        exec sddscombine  $tmpRoot.setpoint.x $tmpRoot.setpoint.y -merge -pipe=out | \
                 sddsprocess -pipe=in $tmpRoot.result2 \
                 -print=col,ControlType,pv  \
                 -print=col,Lineage,- \
                 -define=col,Count,1,type=long  
        exec sddscombine $tmpRoot.result1 $tmpRoot.result2 -merge $outputoffset -overwrite \
             } result ] {
        return -code error $result
    }
    
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.${Polynomial}offset  $tmpRoot.${Polynomial}setpoint "
    
    if [catch {exec sddsconvert $tmpRoot.adjust -retain=col,DeviceName,X${Polynomial}Adjust \
                 -rename=col,X${Polynomial}Adjust=Waveform $tmpRoot.adjust.x
        exec sddsconvert $tmpRoot.adjust -retain=col,DeviceName,Y${Polynomial}Adjust \
                 -rename=col,Y${Polynomial}Adjust=Waveform  $tmpRoot.adjust.y } result] {
        return -code error $result
    }
    
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList "$tmpRoot.adjust.x $tmpRoot.adjust.y"
    set fileList ""
    foreach plane {x y} {
        foreach bpmType {p0 id bm rf} {
            if {[string compare $bpmType bm]==0} {
                if [string compare $plane x]==0 continue
                set waveformFile $waveformFileDir/bmBpmInfo.sdds
            } else {
                set waveformFile $waveformFileDir/${bpmType}[string toupper $plane]BpmInfo.sdds
            }
            APSAddToTmpFileList -ID DPOffsetCalculation -fileList $tmpRoot.$plane.$bpmType
            if [catch {exec sddsconvert $waveformFile -pipe=out \
                         -retain=column,Index,DeviceName -retain=parameter,WaveformPV \
                         | sddsxref -pipe=in $tmpRoot.adjust.$plane -fillIn -nowarning \
                         -match=DeviceName -take=Waveform $tmpRoot.$plane.$bpmType \
                     } result] {
                APSDeleteTmpFileList -ID 1
                return -code error $result
            }
            lappend fileList $tmpRoot.$plane.$bpmType
        }
    }
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe=in $outputadjust \
                 -reedit=parameter,WaveformPV,%/:Out:/:Adjust:/ } result] {
        APSDeleteTmpFileList -ID SetDPOffsets
        
        return -code error $result
    }
    APSAddToTmpFileList -ID DPOffsetCalculation -fileList $fileList
   # APSDeleteTmpFileList -ID DPOffsetCalculation
}

proc RestoreBpmGains {args} {
    global waveformFileDir newGainReferenceFile Polynomial CurrentPolynomial
    global coord hResponseDir vResponseDir
    global new3TermGainReferenceFile hBpmType vBpmType 

    set inputcoord ""
    APSStrictParseArguments {inputcoord}
    
    if ![string length $inputcoord] {
        set inputcoord $coord
    }
    switch $inputcoord {
        x {
            set plane h
            set planes x
            set match "-match=col,ControlName=*x*GainAO"
        }
        y {
            set plane v
            set planes y
            set match "-match=col,ControlName=*y*GainAO"
        }
        both {
            set planes {x y}
            set plane h
            set match "-match=col,Controlame=*GainAO"
        }
    }
    GetPolynomial
    SetMainStatus "Restore gain for $CurrentPolynomial -term polynomial"
    switch $CurrentPolynomial {
        20 {
            set refFile $newGainReferenceFile
        }
        3 {
            set refFile $new3TermGainReferenceFile
        }
        default {
            return -code error "Unknown polynomial given!"
        }
    }
    if ![file exist $refFile] {
        return -code error "$refFile does not exist!"
    }
    GetBPMAndCorrectorType -fileVariable ${plane}ResponseDir
    set bpmType [set ${plane}BpmType]
    if ![string compare $bpmType DP] {
        set datapool 1
    } else {
        set datapool 0
    }
    SetMainStatus "Restore bpm gains in $inputcoord plane ..."

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID RestoreBpmGains -fileList $tmpRoot.gain.$inputcoord
    if [catch {exec sddsprocess $refFile $tmpRoot.gain.$inputcoord $match } result] {
        APSDeleteTmpFileList -ID RestoreBpmGains
        return -code error $result
    }
    if [catch {exec sddscasr -restore $tmpRoot.gain.$inputcoord }  result] {
        #APSDeleteTmpFileList -ID RestoreBpmGains
        return -code error $result
    }
    set datapool 1
    if $datapool {
        APSAddToTmpFileList -ID RestoreBpmGains -fileList "$tmpRoot.gain $tmpRoot.gain.x $tmpRoot.gain.y"
        if [catch {exec sddsprocess $refFile -pipe=out \
                     -match=column,ControlName=*GainAO \
                     -edit=col,BPMName,ControlName,%/:GainAO// \
                     "-edit=column,DeviceName,BPMName,%/:ms:x//%/:ms:y//" \
                     -scan=col,Waveform,ValueString,%lf \
                     | sddsconvert -pipe=in $tmpRoot.gain \
                     -retain=column,BPMName,Waveform,DeviceName 
            exec sddsprocess $tmpRoot.gain $tmpRoot.gain.x -match=col,BPMName=*x 
            exec sddsprocess $tmpRoot.gain $tmpRoot.gain.y -match=col,BPMName=*y \
                 } result] {
            APSDeleteTmpFileList -ID RestoreBpmGains
            return -code error $result
        }
        
        set fileList ""
        APSAddToTmpFileList -ID RestoreBpmGains -fileList "$tmpRoot.gain"
        foreach plane $planes {
            foreach bpmType {p0 id bm rf} {
                if {[string compare $bpmType bm]==0} {
                    if [string compare $plane x]==0 continue
                    set waveformFile $waveformFileDir/bmBpmInfo.sdds
                } else {
                    set waveformFile $waveformFileDir/${bpmType}[string toupper $plane]BpmInfo.sdds
                }
                APSAddToTmpFileList -ID SetDPGains -fileList $tmpRoot.$plane.$bpmType
                if [catch {exec sddsconvert $waveformFile -pipe=out \
                             -retain=column,Index,DeviceName -retain=parameter,WaveformPV \
                             | sddsxref -pipe=in $tmpRoot.gain.$plane -fillIn -nowarning \
                             -match=DeviceName -take=Waveform $tmpRoot.$plane.$bpmType \
                         } result] {
                    APSDeleteTmpFileList -ID SetDPGains
                    SetMainStatus "error: $result"
                    return
                }
                lappend fileList $tmpRoot.$plane.$bpmType
            }
        }
        APSAddToTmpFileList -ID RestoreBpmGains -fileList $fileList
        set output $tmpRoot.vectorgain.$inputcoord
        APSAddToTmpFileList -ID RestoreBpmGains -fileList $output
        if [catch {eval exec sddscombine $fileList -pipe=out \
                     | sddsprocess -pipe=in $output \
                     -reedit=parameter,WaveformPV,%/:Out:/:Gain:/
            exec sddswput $output} result] {
            APSDeleteTmpFileList -ID SetDPGains
            
            return -code error $result
        }
    }
    
    SetMainStatus "Done."
}



proc SplitBPMsByType {} {
    global polyDir
    set refFile /home/helios/oagData/sr/BPMStatus/config.sdds
    if [catch {exec sddsprocess $refFile $polyDir/stdBpm.sdds \
                 -match=col,DeviceType=Std
        exec sddsprocess $refFile $polyDir/8mmRotBpm.sdds \
                 -match=col,DeviceType=*Rot
        exec sddsprocess $refFile $polyDir/5mmBpm.sdds \
                 "-match=col,DeviceType=5???"
        exec sddsprocess $refFile $polyDir/8mmBpm.sdds \
                 "-match=col,DeviceType=8???"
        exec sddsprocess $refFile $polyDir/EMWBpm.sdds \
                 -match=col,DeviceType=19mm } result] {
        return -code error $result
    }
}

proc MultiplyByGain {args} {
    global gainReferenceFile offsetReferenceFile setpointReferenceFile 
    global offsetResultsFile adjustResultsFile Polynomial 3TermOffsetResultsFile
    global 3TermOffsetReferenceFile 3TermSetpointReferenceFile Polynomial
    global newGainReferenceFile new3TermGainReferenceFile 3TermGainReferenceFile
    
    switch $Polynomial {
        3 {
            #note that transfer from 3 term to 20 term, therefore, the ref. files belong 3-term
            set offsetFile $3TermOffsetReferenceFile
            set setpointFile $3TermSetpointReferenceFile
            set gainFile $3TermGainReferenceFile
            set newGainFile $new3TermGainReferenceFile
        }
        20 {
            #note that transfer from 20 term to 3 term, therefore, the ref. files belong 3-term
            set offsetFile $offsetReferenceFile
            set setpointFile $setpointReferenceFile
            set gainFile $gainReferenceFile
            set newGainFile $newGainReferenceFile
        }
        default {
            return -code error "MultiplyByGain: Unknow polynomial (should be 20 or 3)"
        }
    }
    if {![file exist $gainFile] || ![file exist $newGainFile] || \
          ![file exist $new3TermGainReferenceFile] } {
        return -code error "second gain file or gain or offset or setpoint file is not given!"
    }
    SetMainStatus "Multiply offset and setpoints by new gain from $Polynomial term reference..."

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.gain $tmpRoot.offset $tmpRoot.setpoint $tmpRoot.gain3 $tmpRoot.gain4"
    APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.offsetgain $tmpRoot.setpointgain $tmpRoot.gain1 $tmpRoot.gain2"
    if [catch {exec sddsprocess $gainFile -match=col,ControlName=*GainAO \
                 -scan=col,Gain1,ValueString,%lf \
                 -edit=col,BPMName,ControlName,%/:GainAO// \
                 "-filter=col,Gain1,0,0,!" $tmpRoot.gain1 \
             } result] {
        return -code error "MultiplyByGain(sddsprocess1): $result"
    }
    # newGainFile is really a gain multiplicative adjustment file.
    if [catch {exec sddsprocess $newGainFile -match=col,ControlName=*GainAO \
                 -scan=col,Gain2,ValueString,%lf \
                 -edit=col,BPMName,ControlName,%/:GainAO// $tmpRoot.gain2\
             } result] {
        return -code error "MultiplyByGain(sddsprocess2): $result"
    }
    
    # the new gain file is actaually a gain adjustment file,
    # so we mutliply the gain2 values with the gain1 values.
    if [catch {exec sddsxref $tmpRoot.gain2 $tmpRoot.gain1 -pipe=out \
                 -match=BPMName -take=Gain1 -noWarnings \
                 | sddsprocess -pipe=in $tmpRoot.gain3 "-define=col,Gain,Gain2 Gain1 *"\
             } result] {
        return -code error "MultiplyByGain(sddsxref1): $result"
    }
    
    if [catch {exec sddsselect $tmpRoot.gain2 $tmpRoot.gain1 -invert \
                 -noWarning -match=ControlName -pipe=out \
                 | sddsprocess -pipe=in $tmpRoot.gain4 -noWarning \
                 -define=col,Gain,0 \
             } result] {
        return -code error "MultiplyByGain(sddsselect1): $result"
    }
    
    if [catch {exec sddscombine $tmpRoot.gain4 $tmpRoot.gain3 $tmpRoot.gain \
                 -merge -overwrite\
             } result] {
        return -code error "MultiplyByGain(sddscombine1): $result"
    }
    
    if [catch {exec sddsprocess $offsetFile -match=col,ControlName=*OffsetAO \
                 -scan=col,Offset,ValueString,%lf \
                 -edit=col,BPMName,ControlName,%/:OffsetAO// $tmpRoot.offset\
             } result] {
        return -code error "MultiplyByGain(sddsprocess3): $result"
    }
    
    if [catch {exec sddsprocess $setpointFile \
                 -match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,& \
                 -scan=col,Setpoint,ValueString,%lf \
                 -edit=col,BPMName,ControlName,%/:SetpointAO// $tmpRoot.setpoint\
             } result] {
        return -code error "MultiplyByGain(sddsprocess3): $result"
    }
    
    if [catch {exec sddsxref $tmpRoot.offset $tmpRoot.gain -pipe=out \
                 -match=BPMName -take=Gain -noWarning \
                 | sddsprocess -pipe=in "-define=col,Value,Offset Gain *" \
                 -reprint=col,ValueString,%le,Value $tmpRoot.offsetgain\
             } result] {
        return -code error "MultiplyByGain(sddsxref2): $result"
    }
    
    if [catch {exec sddsxref $tmpRoot.setpoint $tmpRoot.gain -pipe=out \
                 -match=BPMName -take=Gain -noWarning \
                 | sddsprocess -pipe=in "-define=col,Value,Setpoint Gain *" \
                 -reprint=col,ValueString,%le,Value $tmpRoot.setpointgain \
             } result] {
        return -code error "MultiplyByGain(sddsxref3): $result"
    }
   
    # create a gain file from reference gain and adjustment gain
    if [catch {exec sddsxref $gainFile $tmpRoot.gain -pipe=out \
                 -match=ControlName -take=Gain -noWarning \
                 | sddsprocess -pipe=in $tmpRoot.adjustedgain \
                 -reprint=col,ValueString,%le,Gain \
             } result] {
        return -code error "MultiplyByGain(sddsxref4): $result"
    }
    
    if [catch {exec sddscasr -restore $tmpRoot.offsetgain} result] {
        return -code error "MultiplyByGain(burtwb1): $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.setpointgain} result] {
        return -code error "MultiplyByGain(burtwb2): $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.adjustedgain} result] {
        return -code error "MultiplyByGain(burtwb3): $result"
    }
}

proc Compare {args} {
    global setpointReferenceFile gainReferenceFile offsetReferenceFile
    global 3TermOffsetResultsFile Polynomial
    
    #generate 3-term offsets file
    if [catch {CalculateOffsetsFromPolynomial -offsetFile $offsetReferenceFile \
                 -setpointFile $setpointReferenceFile -switchTo $Polynomial} result] {
        return -code error $result
    }
    if [catch {exec sddsprocess $setpointReferenceFile /tmp/Setpoint \
		   "-match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,&" 
	exec sddsprocess $offsetReferenceFile /tmp/Offset -match=col,ControlName=*OffsetAO
	exec sddscombine /tmp/Setpoint /tmp/Offset -merge -overwrite -pipe=out | \
		   sddsprocess -pipe=in -scan=col,Value20,ValueString,%lf  \
		   /tmp/Offset20 } result] {
	return -code error $result
    }
    if [catch {exec sddsxref $3TermOffsetResultsFile /tmp/Offset20 -match=ControlName -take=Value20 \
		   -pipe=out | sddsprocess -pipe -scan=col,Value3,ValueString,%lf \
		   "-define=col,Diff,Value3 Value20 -"  | \
		   sddsconvert -pipe=in -retain=col,ControlName,Diff /tmp/diff1
	exec sddsprocess /tmp/diff1 /tmp/diffOffset -match=col,ControlName=*OffsetAO \
		   -edit=col,BPMName,ControlName,%/:OffsetAO//
	exec sddsprocess /tmp/diff1 -pipe=out -match=col,ControlName=*SetpointAO \
		   -edit=col,BPMName,ControlName,%/:SetpointAO// | \
		   sddsconvert -pipe -rename=col,Diff=Diff1 | \
		   sddsxref -pipe /tmp/diffOffset -match=BPMName -take=Diff  | \
		   sddsprocess -pipe "-define=col,totalDiff,Diff1 Diff +" \
		   "-filter=col,totalDiff,-1e-3,1e-3,!" | \
		   sddsconvert -pipe -retain=col,BPMName,totalDiff  \
		   | sddsprintout -pipe=in -col /tmp/Difference } result] {
	return -code error $result
    }
    APSFileDisplayWindow .diff -fileName /tmp/Difference -width 80 -height 30 -printCommand "enscript -r"
}
proc SwitchPolynomials {args} {
    global plane coord Polynomial offsetResultsFile adjustResultsFile
    global 3TermOffsetResultsFile 3TermAdjustResultsFile datapool CurrentPolynomial
    global 3TermOffsetReferenceFile 3TermSetpointReferenceFile
    global offsetReferenceFile setpointReferenceFile
    global offsetResultsFile adjustResultsFile
      
    GetPolynomial
    if {$CurrentPolynomial==$Polynomial} {
	SetMainStatus "Can not switch to the same polynomials."
	return
    }
    SetMainStatus "Switch from $CurrentPolynomial term to $Polynomial term ..."
    switch $Polynomial {
        20 {
            #note that transfer from 3 term to 20 term, therefore, the ref. files belong 3-term
            set offsetFile $3TermOffsetReferenceFile
            set setpointFile $3TermSetpointReferenceFile
	    set offset $offsetResultsFile
            set adjust $adjustResultsFile
        }
        3 {
            #note that transfer from 20 term to 3 term, therefore, the ref. files belong 3-term
            set offsetFile $offsetReferenceFile
            set setpointFile $setpointReferenceFile
	    set offset $3TermOffsetResultsFile
            set adjust $3TermAdjustResultsFile
        }
        default {
            return -code error "Unknow polynomial (should be 20 or 3)"
        }
    }

    #create files
    if [catch {CalculateOffsetsFromPolynomial -offsetFile $offsetFile \
                 -setpointFile $setpointFile -switchTo $Polynomial} result] {
        return -code error $result
    }
    if [catch {exec sddscasr -restore $offset} result] {
	SetMainStatus "Error: $result"
    }
    #set datapool adjusts
    set datapool 1
    if $datapool {
	if [catch {exec sddswput $adjust} result] {
	    SetMainStatus "Error:$result"
	    return
	}
    }
    
    if [catch {ChangePolynomials -poly $Polynomial} result] {
        SetMainStatus "$result"
        return
    }
    SetMainStatus "done."
}

#globals
set waveformFileDir /home/helios/oagData/sr/orbitControllaw/waveforms
set setpointReferenceFile /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz
set gainReferenceFile /home/helios/oagData/SCR/snapshots/SBPMs/SBPMs-Preferred.gz
set offsetReferenceFile /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz
set polyDir /home/helios/oagData/sr/bpmCalibration/bpmPolynomials
set from20TermFile 1

set newGainReferenceFile ""
set new3TermGainReferenceFile ""

set 3TermOffsetReferenceFile $offsetReferenceFile
set 3TermSetpointReferenceFile $setpointReferenceFile
set 3TermGainReferenceFile $gainReferenceFile
set from3TermFile 1

set dataDir /home/helios/oagData/sr/orbitControllaw/lattices/default
cd $dataDir
set hResponseDir h.default
set vResponseDir v.default
set plane h
set Polynomial ""
set fromReference 1
set tmpFile /tmp/[APSTmpString]
#offsetResultsFile contains both offset and setpoint
set offsetResultsFile $tmpFile.offset
set adjustResultsFile $tmpFile.adjust
set 3TermOffsetResultsFile $tmpFile.3offset
set 3TermAdjustResultsFile $tmpFile.3adjust

APSAddToTmpFileList -ID SwitchBPMPolynomials -fileList "$offsetResultsFile $adjustResultsFile"
APSAddToTmpFileList -ID SwitchBPMPolynomials -fileList "$3TermOffsetResultsFile $3TermAdjustResultsFile"

#create widgets
GetBPMAndCorrectorType -fileVariable hResponseDir
GetBPMAndCorrectorType -fileVariable vResponseDir
GetPolynomial
setCorrPlane H
MakeConfigFrame .config -parent .userFrame
MakeReferenceFileFrame .reference -parent .userFrame
MakeActionFrame .act -parent .userFrame
#SplitBPMsByType
set Polynomial 3

#set new3TermGainReferenceFile /home/oxygen/SAJAEV/oagscratch/bpmGains-newTiming.scr
