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



set useRC 1

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.70 $ \$Author: soliday $"

APSApplication . -name SROffsetAdjustment -version $CVSRevisionAuthor 
set tcl_precision 4

proc SetMainStatus {text} {
    global mainStatus
    set mainStatus "[exec date +%H:%M:%S]  $text"
    update
}


SetMainStatus "Working..."
APSScrolledStatus .status -parent .userFrame -textVariable mainStatus -width 80 \
        -withButtons 1 -lineLimit 1000
update

exec medm -x -attach -macro RCPV=S:BPMOffsetAdjustmentsRC ./sr/psApp/APSRunControlSingle.adl &

set offsetDir /home/helios/oagData/sr/offsetAdjustmentData
set waveformFileDir  /home/helios/oagData/sr/orbitControllaw/waveforms
set offsetFile $offsetDir/offsetData.gz

if [string compare [file type $offsetFile] link]==0 {
    set linkTo [file readlink $offsetFile]
    SetMainStatus "Using pattern [exec editstring $linkTo -edit=10Z/%/offsetData-//%/.gz//]"
}

if {0} {
APSFrame .buttonRow1 -parent .userFrame -label "Offset Adjustment"
set w .userFrame.buttonRow1.frame
set offsetButtonFrame $w
APSButton .run -parent $w -command RunOffsetAdjustment \
  -text Run -contextHelp "Runs offset adjustment.  May be stopped using Stop button."
APSButton .abort -parent $w -command AbortOffsetAdjustment \
  -text Stop -contextHelp "Stops offset adjustment.  May be resumed using Run button."
APSDisableButton $w.abort.button
APSDisableButton $w.run.button
APSFrame .buttonRow3 -parent .userFrame -label "Bunch Pattern"
set w .userFrame.buttonRow3.frame
#APSButton .6+25x3 -parent $w -command "SwitchOffsetFile -use 6+25x3" \
  -text "Use 6+25x3-36" -contextHelp "Switches to the 6+25x1 file (for 6 BPM bunches plus 25 triplets separated by 36 buckets).  NB: will restart the application."
#APSButton .6+21x1 -parent $w -command "SwitchOffsetFile -use 6+21x1-54" \
  -text "Use 6+21x1-54" -contextHelp "Switches to the 6+21x1-54 file (for 6 BPM bunches plus 21 singlets separated by 54 buckets).  NB: will restart the application."
APSButton .1+22x1 -parent $w -command "SwitchOffsetFile -use 1+22x1-54" \
  -text "Use 1+22x1-54" -contextHelp "Switches to the 1+22x1-54 file (for 23 singlets separated by 54 buckets).  NB: will restart the application."
#APSButton .6+8x7 -parent $w -command "SwitchOffsetFile -use 6+8x7" \
  -text "Use 6+8x7" -contextHelp "Switches to the 6+8x7 file (for 6 BPM bunches plus 8 septuplets opposite).  NB: will restart the application."
APSButton .1+8x7 -parent $w -command "SwitchOffsetFile -use 1+8x7" \
  -text "Use 1+8x7" -contextHelp "Switches to the 1+8x7 file (for 1 BPM bunch plus 8 septuplets opposite).  NB: will restart the application."
APSButton .3+8x7 -parent $w -command "SwitchOffsetFile -use 3+8x7" \
  -text "Use 3+8x7" -contextHelp "Switches to the 3+8x7 file (for 3 BPM bunches plus 8 septuplets opposite).  NB: will restart the application."
APSButton .0+324x1 -parent $w -command "SwitchOffsetFile -use 0+324x1" \
  -text "Use 0+324x1" -contextHelp "Switches to the 0+324x1 file (for 324 buckets with 4 bucket interval).  NB: will restart the application."
}
APSFrame .buttonRow2 -parent .userFrame -label "Data Pool Transfer" 
set w .userFrame.buttonRow2.frame
set dpButtonFrame $w

set XtransferRCPV S:XDPoffsetTransferRC
set YtransferRCPV S:YDPoffsetTransferRC
APSButton .run -parent $w -command RunDPTransfer \
  -text Run -contextHelp "Runs DP transfer.   May be stopped using Stop button."
APSButton .info -parent $w -text Info \
  -command "runControlInfo -runControlPV $XtransferRCPV;runControlInfo -runControlPV $YtransferRCPV" \
  -contextHelp "display the runControl info of DP offset transfer"
APSButton .abort -parent $w -command AbortDPTransfer \
  -text Stop -contextHelp "Stops DP transfer. May be resumed using Run button."
#APSDisableButton $w.abort.button
#APSDisableButton $w.run.button


APSButton .setDP1 -parent $w -text "Set Once From Reference File" -command \
  "APSDisableButton $w.setDP1.button ;\
    APSDisableButton $w.setDP.button ;\
    SetDPOffsets -fromReference 1 ;\
    APSEnableButton $w.setDP1.button ;\
    APSEnableButton $w.setDP.button" \
  -contextHelp "Press to transfer the OffsetAO+SetpointAO from the offset reference file to the AdjustP values in the Data Pool IOC"

APSButton .setDP -parent $w -text "Set Once From IOCs" -command \
  "APSDisableButton $w.setDP1.button ;\
    APSDisableButton $w.setDP.button ;\
    SetDPOffsets -fromReference 0 ;\
    APSEnableButton $w.setDP1.button ;\
    APSEnableButton $w.setDP.button" \
  -contextHelp "Press to transfer the OffsetAO+SetpointAO from the BPM IOCs to the AdjustP values in the Data Pool IOC"

APSButton .setDP2 -parent $w -text "Set Gain Once From IOCs" -command \
  "APSDisableButton $w.setDP1.button ;\
    APSDisableButton $w.setDP.button ;\
    APSDisableButton $w.setDP2.button;\
    APSDisableButton $w.run.button; \
    APSDisableButton $w.abort.button;\
    SetDPGains -fromReference 0 ;\
    APSEnableButton $w.setDP1.button ;\
    APSEnableButton $w.setDP2.button ;\
    APSEnableButton $w.run.button;\
    APSEnableButton $w.abort.button;\
    APSEnableButton $w.setDP.button" \
  -contextHelp "Press to transfer the gains from the BPM IOCs to the gain values in the Data Pool IOC"



proc SwitchOffsetFile {args} {
    set use 6+22x1-52
    APSStrictParseArguments {use}
    global offsetDir offsetFile medmPID

    switch $use {
        6+25x3 -
        6+17x3 -
        6+17x1 -
        6+22x1-52 -
        6+21x1-54 -
        1+22x1-54 -
        6+8x7 -
        1+8x7 -
        3+8x7 -
        0+324x1 {
            if [catch {exec rm $offsetFile
                exec ln -s $offsetDir/dataFiles/offsetData-$use.gz $offsetFile} result] {
                SetMainStatus "Error trying to change offset file: $result"
                return
            }
            SetMainStatus "NB: This window will disappear momentarily to be replaced by a new instance.  DON'T PANIC!"
            APSWaitWithUpdate -waitSeconds 4 -updateInterval 1
            exec SROffsetAdjustment &
            exit
        }
        default {
            SetMainStatus "Bad offset file selection: $use"
            return
        }
    }
}

proc MakeDPControllawFile {args} {
    # Make a controllaw matrix file that performs updates of DP AdjustP's based on
    # regular OffsetAO+SetpointAO.  The file has one column for each DP AdjustP and
    # two rows for each DP AdjustP.  The matrix has the following form
    # form
    #      ActuatorNames         S1A:P1:ms:x:SetpointAO  S1A:P1:ms:x:OffsetAO  S1A:P2 ...
    # DP:S1A:P1:msAve:x:AdjustP          -1                    -1               0  ...
    # DP:S1A:P2:msAve:x:AdjustP           0                     0              -1   -1   0 ...

    set output ""
    if {[APSStrictParseArguments {output}] || \
          ![string length $output]} {
        return -code error "MakeDPControllawFile: bad arguments"
    }

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.DPBPMs
    foreach plane {H V} xy {x y} {
        # make a list of available DP BPMs for this plane
        if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
		       -filter=column,Nonexistent${plane},0,0 \
		       -nowarnings \
		       | sddssort -pipe=in -col=DeviceName -unique -numericHigh $tmpRoot.DPBPMs} result] {
            return -code error "MakeDPControllawFile: $result"
        }
        if [catch {exec sdds2stream -column=DeviceName $tmpRoot.DPBPMs} DPPVList] {
            return -code error "MakeDPControllawFile: $DPPVList"
        }
        if [catch {sdds open $output.${plane}DPxfer w SDDS_BINARY} fd] {
            return -code error "MakeDPControllawFile: $fd"
        }
        if [catch {sdds defineColumn $fd ActuatorNames -type SDDS_STRING} result] {
            return -code error "MakeDPControllawFile: $result"
        }
        
        set gainPVList ""
        foreach pv $DPPVList {
            if {[string match *ID* $pv] || [string match *BM* $pv]} {
                lappend gainPVList ${pv}.gain
            }
        }
        set DPList [concat $DPPVList $gainPVList]
        set actuatorList  ""
        set bpmCounter 0
        set nBPMs [llength $DPList]
        foreach BPM $DPList {
            lappend actuatorList ${BPM}
            if [string match *gain $BPM] {
                regexp {(.*)\.} $BPM a bpm
                set gain ${bpm}:ms:$xy:GainAO
                if [catch {sdds defineColumn $fd $gain -type SDDS_DOUBLE } result] {
                    return -code error "MakeDPControllawFile: $result"
                }
                set dataList ""
                if $bpmCounter!=0 {
                    eval lappend dataList [APSReplicateItem -item 0 -number $bpmCounter]
                }
                lappend dataList -1
                incr bpmCounter
                if $bpmCounter!=$nBPMs {
                    eval lappend dataList [APSReplicateItem -item 0 -number [expr $nBPMs-$bpmCounter]]
                }
                set data($BPM) $dataList
            } else {
                set setpoint ${BPM}:ms:$xy:SetpointAO
                set offset ${BPM}:ms:$xy:OffsetAO
                if [catch {sdds defineColumn $fd $setpoint -type SDDS_DOUBLE
                    sdds defineColumn $fd $offset -type SDDS_DOUBLE} result] {
                    return -code error "MakeDPControllawFile: $result"
                }
                set dataList ""
                if $bpmCounter!=0 {
                    eval lappend dataList [APSReplicateItem -item 0 -number $bpmCounter]
                }
                lappend dataList -1
                incr bpmCounter
                if $bpmCounter!=$nBPMs {
                    eval lappend dataList [APSReplicateItem -item 0 -number [expr $nBPMs-$bpmCounter]]
                }
                set data($BPM) $dataList
            }
        }
        if [catch {sdds writeLayout $fd
            sdds startPage $fd $nBPMs
            eval sdds setColumn $fd ActuatorNames $actuatorList} result] {
            return -code error "MakeDPControllawFile: $result"
        }
        foreach BPM $DPList {
            if [string match *gain $BPM] {
                regexp {(.*)\.} $BPM a bpm
                set gain ${bpm}:ms:$xy:GainAO
                if [catch {eval sdds setColumn $fd $gain $data($BPM) } result] {
                    return -code error "MakeDPControllawFile: $result"
                }
            } else {
                set setpoint ${BPM}:ms:$xy:SetpointAO
                set offset ${BPM}:ms:$xy:OffsetAO
                if [catch {eval sdds setColumn $fd $setpoint $data($BPM)
                    eval sdds setColumn $fd $offset $data($BPM)} result] {
                    return -code error "MakeDPControllawFile: $result"
                }
            }
        }
        if [catch {sdds writePage $fd
            sdds close $fd} result] {
            return -code error "MakeDPControllawFile: $result"
        }
    }
    # if [catch {exec sddscombine $output.H $output.V -merge -overwrite $output} result] {
    #     return -code error "MakeDPControllawFile: $result"
    # }
    file delete -force $tmpRoot.DPBPMs
}

proc MakeOffsetCompFeedforwardFile {args} {
    # Make a feedforward input file that performs offset compensation.  The file has one
    # page for each BPM that is compensated.  The offset variation data is all relative to
    # 0 at 102mA.  We must add the nominal offset for each BPM (from the SCR file) to
    # get a table of offset vs intensity.  For P0 BPMs, the intensity is S35DCCT.
    # For other BPMs, the intensity is S5:BP5:sum.

    set input ""
    set output ""
    APSStrictParseArguments {input output} 
    set referenceFile /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz 

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.offsets $tmpRoot.full $tmpRoot.P0 $tmpRoot.PN

    if [catch {exec sddsprocess $referenceFile -pipe=out \
		  "-match=col,ControlName=S38*,!" \
                 -match=column,ControlName=*OffsetAO \
                 -match=column,ControlName=*ID*,ControlName=*BM*,|,! \
                 -scan=column,DCOffset,ValueString,%le,type=double \
                 | sddsconvert -pipe -retain=column,ControlName,DCOffset \
                 | sddstranspose -pipe \
                 | sddsconvert -pipe -retain=column,*OffsetAO -edit=column,*,%/OffsetAO/DCOffset/ \
                 -delete=param,* \
                 | sddsexpand -pipe=in $tmpRoot.offsets} result] {
        return -code error "MakeOffsetCompFeedforwardFile: $result"
    }
    set offsetList [exec sddsquery -parameter $tmpRoot.offsets]

    set redefineOptions ""
    set bpmList ""
    foreach offset $offsetList {
        set bpm [os editstring %/:ms//%/:DCOffset// $offset]
        lappend bpmList $bpm
        lappend redefineOptions "-redefine=column,$bpm,$offset $bpm +"
    }
    if [catch {eval exec sddsxref $input $tmpRoot.offsets -pipe=out -leave=* -transfer=param,*DCOffset \
                 | sddsprocess -pipe $redefineOptions \
                 | sddsconvert -pipe -delete=param,* \
                 | sddssort -pipe -column=S35DCCT,incr \
                 | sddsseparate -pipe \
                 -copy=S35DCCT,*sum -group=ActuatorValue,[join $bpmList ,] \
                 | sddsprocess -pipe=in $tmpRoot.full \
                 -edit=parameter,ActuatorName,ActuatorValueSourceColumn,%/:x/:ms:x/%/:y/:ms:y/ei/:OffsetAO/ } result] {
        return -code error "MakeOffsetCompFeedforwardFile: $result"
    }
    
    if [catch {exec sddsprocess $tmpRoot.full -pipe=out \
                 -match=parameter,ActuatorName=*P0* \
                 | sddsconvert -pipe -delete=column,*sum \
                 -rename=column,S35DCCT=ReadbackValue \
                 | sddsprocess -pipe=in $tmpRoot.P0 \
                 -print=parameter,ReadbackName,S-DCCT:CurrentM
        exec sddsprocess $tmpRoot.full -pipe=out \
                 -match=parameter,ActuatorName=*P0*,! \
                 | sddsconvert -pipe -delete=column,S35DCCT \
                 -rename=column,S8B:P5:sum=ReadbackValue \
                 | sddsprocess -pipe=in $tmpRoot.PN \
                 -print=parameter,ReadbackName,S8B:P5:scdu:ave_sum.VAL
        exec sddscombine $tmpRoot.P0 $tmpRoot.PN $output -overwrite} result] {
        return -code error "MakeOffsetCompFeedforwardFile: $result"
    }
    file delete  $tmpRoot.full $tmpRoot.P0 $tmpRoot.PN $tmpRoot.offsets
}

proc SetDPOffsets {args} {
    set fromReference 0
    APSStrictParseArguments {fromReference}
    SetMainStatus "Working."
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID SetDPOffsets -fileList "$tmpRoot.offset \
       $tmpRoot.adjust $tmpRoot.snap \
	    $tmpRoot.req $tmpRoot.adjust.x $tmpRoot.adjust.y $tmpRoot.all"
    if !$fromReference {
        if [catch {exec sddsprocess \
                     /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz \
                     $tmpRoot.req \
                     -match=col,ControlName=*OffsetAO,ControlName=*SetpointAO,|,ControlName=*FTSetpointAO,!,&
            exec burtrb -f $tmpRoot.req -o $tmpRoot.snap} result] {
            APSDeleteTmpFileList -ID SetDPOffsets
            APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
            SetMainStatus "Error!"
            return
        }
        set snapshot $tmpRoot.snap
    } else {
        set snapshot /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz 
    }
    if [catch {exec sddsprocess $snapshot $tmpRoot.offset \
                 -match=col,ControlName=*OffsetAO \
                 -edit=col,BPMName,ControlName,%/:ms//%/:OffsetAO// \
                 -scan=col,Offset,ValueString,%lf 
        exec sddsprocess $snapshot -pipe=out \
                 -match=col,ControlName=*SetpointAO,ControlName=*FTSetpointAO,!,& \
                 -edit=col,BPMName,ControlName,%/:ms//%/:SetpointAO// \
                 -scan=col,Setpoint,ValueString,%lf \
                 | sddsconvert -pipe -retain=column,BPMName,Setpoint \
                 | sddsxref -pipe $tmpRoot.offset -match=BPMName -take=Offset \
                 | sddsprocess -pipe \
                 "-define=column,Waveform,Offset Setpoint +,units=mm" \
                 "-edit=column,DeviceName,BPMName,%/:x//%/:y//" \
                 | sddsconvert -pipe=in $tmpRoot.adjust \
                 -retain=column,BPMName,Waveform,DeviceName
        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 SetDPOffsets
        APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
        SetMainStatus "Error!"
        return
    }
    set fileList ""
    global waveformFileDir
    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 SetDPOffsets -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 SetDPOffsets
                APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
                SetMainStatus "Error!"
                return
            }
            lappend fileList $tmpRoot.$plane.$bpmType
        }
    }
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe=in $tmpRoot.all \
                 -reedit=parameter,WaveformPV,%/:Out:/:Adjust:/
        exec sddswput $tmpRoot.all} result] {
        APSDeleteTmpFileList -ID SetDPOffsets
        APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
        SetMainStatus "Error!"
        return
    }

    SetMainStatus "Done."
    APSDeleteTmpFileList -ID SetDPOffsets
}

proc SetDPGains {args} {
    set fromReference 0
    # APSStrictParseArguments {fromReference}
    SetMainStatus "Working."
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID SetDPOffsets -fileList "$tmpRoot.gain $tmpRoot.snap \
	    $tmpRoot.req $tmpRoot.gain.x $tmpRoot.gain.y $tmpRoot.all"
    
    if [catch {exec sddsprocess \
                 /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz \
                 $tmpRoot.req \
                 -match=col,ControlName=*OffsetAO -reedit=col,ControlName,%/OffsetAO/GainAO.VAL/
        exec burtrb -f $tmpRoot.req -o $tmpRoot.snap} result] {
        #  APSDeleteTmpFileList -ID SetDPGains
        APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
        SetMainStatus "Error!"
        return
    }
    set snapshot $tmpRoot.snap
    if [catch {exec sddsprocess $snapshot -pipe=out \
                 -edit=col,BPMName,ControlName,%/:ms//%/:GainAO.VAL// \
                 -scan=col,Waveform,ValueString,%lf \
                 "-edit=column,DeviceName,BPMName,%/:x//%/:y//" \
                 | 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 SetDPGains
        APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
        SetMainStatus "Error!"
        return
    }
    set fileList ""
    global waveformFileDir
    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 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
                APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
                SetMainStatus "Error!"
                return
            }
            lappend fileList $tmpRoot.$plane.$bpmType
        }
    }
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe=in $tmpRoot.all \
                 -reedit=parameter,WaveformPV,%/:Out:/:Gain:/
        exec sddswput $tmpRoot.all} result] {
        # APSDeleteTmpFileList -ID SetDPGains
        APSAlertBox [APSUniqueName .] -errorMessage "Error: $result"
        SetMainStatus "Error!"
        return
    }

    SetMainStatus "Done."
    # APSDeleteTmpFileList -ID SetDPGains
}


proc SetButtonMode {widget runEnabled} {
    if $runEnabled {
        APSDisableButton $widget.abort.button
        APSEnableButton $widget.run.button
    } else {
        APSEnableButton $widget.abort.button
        APSDisableButton $widget.run.button
    }
}


set offsetAdjustmentPID ""
proc AbortOffsetAdjustment {} {
    global offsetButtonFrame offsetAdjustmentPID
    if ![string length $offsetAdjustmentPID] return
    eval exec kill -9 [pid [lindex $offsetAdjustmentPID 0]]
    SetMainStatus "Aborting."
  #  SetButtonMode $offsetButtonFrame 1
}

proc RunOffsetAdjustment {} {
    global OffsetFFData offsetButtonFrame offsetAdjustmentPID
    if ![string length $OffsetFFData] {
        SetMainStatus "No offset data!"
        return
    }
  #  SetButtonMode $offsetButtonFrame 0
    clearRCRecord -PV S:BPMOffsetAdjustmentsRC
    set unixCommand "sddsfeedforward $OffsetFFData -interval=30 \
       -verbose -infiniteLoop -runControlPV=string=S:BPMOffsetAdjustmentsRC,pingTimeout=30 \
       -runControlDescription=FFOffsetCompensation"
    if {0} {
    set offsetAdjustmentPID \
      [APSExecLog [APSUniqueName .] -name "Offset adjustment" -width 80 -lineLimit 5000 -height 15 \
         -unixCommand $unixCommand \
         -callback "SetButtonMode $offsetButtonFrame 1" \
         -abortCallback "SetButtonMode $offsetButtonFrame 1" \
         -cancelCallback "SetButtonMode $offsetButtonFrame 1" ]
    }
    set offsetAdjustmentPID \
      [APSExecLog [APSUniqueName .] -name "Offset adjustment" -width 80 -lineLimit 5000 -height 15 \
         -unixCommand $unixCommand  ]
}

set dpTransferPID ""
proc AbortDPTransfer {} {
    global dpButtonFrame dpTransferPID
    if ![string length $dpTransferPID] return
    SetMainStatus "Aborting."
    eval exec kill -9 [pid [lindex $dpTransferPID 0]]
    set dpTransferPID ""
    SetButtonMode $dpButtonFrame 1
}


proc RunDPTransfer {} {
    global dpTransferPIDX dpButtonFrame DPXferData dpTransferPIDY

    if {![string length $DPXferData] ||
        ![file exist $DPXferData.HDPxfer] || ![file exist $DPXferData.VDPxfer] } {
        SetMainStatus "Error, DP transfer files has not been created."
        return
    }
    set wfDir /home/helios/oagData/sr/orbitControllaw/waveforms
    SetButtonMode $dpButtonFrame 0
    global XtransferRCPV
    clearRCRecord -PV $XtransferRCPV
    exec medm -x -attach -macro RCPV=$XtransferRCPV \
      ./sr/psApp/APSRunControlSingle.adl &
    set unixCommandx "sddscontrollaw $DPXferData.HDPxfer -gain=1 -proportional \
-interval=1 -infinite -verbose -runControlPV=string=$XtransferRCPV,pingTimeout=30 -runControlDescription=string=DPTransferForXPlane -waveforms=$wfDir/adjust_gainXBpmInfo.sdds,actuator"

    set dpTransferPID \
      [APSExecLog [APSUniqueName .] -name "DPX Transfer" -width 95 -lineLimit 5000 -height 15 \
         -unixCommand $unixCommandx \
        -callback "SetButtonMode $dpButtonFrame 1" \
        -cancelCallback "SetButtonMode $dpButtonFrame 1" \
        -abortCallback "SetButtonMode $dpButtonFrame 1" ]

    global YtransferRCPV
    clearRCRecord -PV $YtransferRCPV
    
    exec medm -x -attach -macro RCPV=$YtransferRCPV \
      ./sr/psApp/APSRunControlSingle.adl &
    set unixCommandy "sddscontrollaw $DPXferData.VDPxfer -gain=1 -proportional \
  -interval=1 -infinite -verbose -runControlPV=string=$YtransferRCPV,pingTimeout=30 -runControlDescription=string=DPTransferForYPlane -waveforms=$wfDir/adjust_gainYBpmInfo.sdds,actuator"

    set dpTransferPIDY \
      [APSExecLog [APSUniqueName .] -name "DPY Transfer" -width 95 -lineLimit 5000 -height 15 \
         -unixCommand $unixCommandy \
        -callback "SetButtonMode $dpButtonFrame 1" \
        -cancelCallback "SetButtonMode $dpButtonFrame 1" \
        -abortCallback "SetButtonMode $dpButtonFrame 1" ]
}

proc clearRCRecord {args} {
    set PV ""
    if {[APSStrictParseArguments {PV}] || ![string length $PV]} {
        return -code error "clearRCRecord: bad arguments"
    }
    set status [exec cavget -list=$PV.RUN]
    if $status {
        exec cavput -list=$PV.ABRT=1
        exec cawait -waitfor=$PV.RUN,equal=0
    }
    exec cavput -list=$PV.CLR=1
}

proc runControlInfo {args} {
    set runControlPV ""
    APSParseArguments {runControlPV}
    if [catch {exec medm -x -attach -macro "RCPV=$runControlPV" \
                 /usr/local/iocapps/adlsys/sr/psApp/APSRunControlSingle.adl & \
             } result ] {
        return -code error  $result
    }
}

set OffsetFFData /home/helios/oagData/feedForwardFiles/SRoffsetAdjustment/OffsetFF
set OffsetFFData /tmp/OffsetFF
#APSAddToTempFileList $OffsetFFData
if 1 {
    SetMainStatus "Making offset adjustment data file..."
    update
    if [catch {MakeOffsetCompFeedforwardFile -input $offsetFile -output $OffsetFFData} result] {
        SetMainStatus "Error: $result"
        set OffsetFFData ""
    } else {
      #  APSEnableButton $offsetButtonFrame.run.button
    }
}

if 1 {
    SetMainStatus "Making Data Pool transfer file..."
    update
    set DPXferData /tmp/[APSTmpString]
    if [catch {MakeDPControllawFile -output $DPXferData} result] {
        SetMainStatus "Error: $result"
        set DPXferData ""
    } else {
        APSEnableButton $dpButtonFrame.run.button
        APSAddToTempFileList "$DPXferData.HDPxfer $DPXferData.VDPxfer"
    }
}

SetMainStatus "Ready."
