#!/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

APSApplication . -name ApplyS37ScraperBump -version 1.0 \
  -overview {Control all that is necessary to create a bump in S37 straight section. There some soft PVs to create. Some sddscontollaws to: 1) put values into the soft PVs, 2) put values into FF magnet PVs. Monitoring is optional, but highly recommended. The SCR file should be the updated one after the P1 bpm offsets are measured.}
set status Working
APSScrolledStatus .status -parent .userFrame -textVariable status -width 80 -height 10
set status Ready

set runControlPVName APS:RunControlSlot0RC

proc OpenBumpSoftPVChannels {args} {
    global bumpValue bumpPreviousValue errorCode
    if [pv linkw bumpValue S37:Bump] {
         set status "Error link S37:Bump: $errorCode"
     }
    if [pv linkw bumpPreviousValue S37:BumpPreviousValue] {
         set status "Error link S37:BumpPreviousValue: $errorCode"
     }
# call bump program whenever the PV S37:Bump is changed
    if {[pv umon bumpValue {CallMakeSRBump}] != 0} {
        set status "umon error $errorCode"
    }
}

proc CallMakeSRBump {args} {
    global bumpValue bumpPreviousValue deltaLimit status  outputDir
    
    
    set status "Calling CallMakeSRBump..."

   # set executable /home/oxygen8/SHANG/epics/extensions/src/SDDSepics/SDDSepics/O.linux-x86_64/makesrbump
    set executable makesrbump
    #set executable /home/oxygen3/EMERY/epics/extensions/src/SDDSepics/SDDSepics/O.linux-x86_64/makesrbump
    # makesrbump only work with changes to bumps. Somehow that got changes in May 2019
    # S37:Bump is not recognized as a PV inside of makesrbump. It is a colum nname for the matrix of correctors.

    # It is important to keep track of the old values in the same GUI. 
    # This is a problem if multiple GUI are trying to work alternatively. No solution
    # for that.
    #set bumpPreviousValue $bumpValue
    set deltaBumpValue [expr $bumpValue - $bumpPreviousValue]
    if {$deltaBumpValue==0} {
        set status "delta bump is zero, no bump is done."
        return
    }
    set status "$executable $outputDir/all.coeff  \
                 -bpmList=S37:Bump -deltaList=$deltaBumpValue \
                 -waveform=/home/helios/oagData/sr/orbitControllaw/waveforms/bumpWaveform.v \
                 -deltaLimit=$deltaLimit -verbose"
    
    set status "calling $executable"
    if [catch {exec $executable $outputDir/all.coeff \
                 -bpmList=S37:Bump -deltaList=$deltaBumpValue \
                 -waveform=/home/helios/oagData/sr/orbitControllaw/waveforms/bumpWaveform.v \
                 -deltaLimit=$deltaLimit -verbose} result] {
        set status "Error with makesrbump: $result"
        return
    } else {
        set status "$result"
    }
    exec sddsmonitor $outputDir/pcasPVs $outputDir/S37ScraperBumpLog.sdds -step=1 -append=topage 
    set bumpPreviousValue $bumpValue
    pv putw bumpPreviousValue
    update
}

proc ReadSCR {args} {
    # This initializes S37BP1SCRSetpointAO S38AP1SCRSetpointAO
    global SCRreference S37BP1SCRSetpointAO S38AP1SCRSetpointAO magnetFFfile
    set SCRdir /home/helios/oagData/SCR/snapshots/SR

    if ![file exists $SCRdir/$SCRreference] {
        set status "Can't file file $SCRdir/$SCRreference"
        return -code error "Can't file file $SCRdir/$SCRreference"
    }
    if [catch {exec sddsprocess $SCRdir/$SCRreference -pipe=out \
                 -match=col,ControlName=S37B:P1:ms:y:SetpointAO,ControlName=S38A:P1:ms:y:SetpointAO,| \
                 -edit=col,NewControlName,ControlName,2S/:/Ki/:SCRSetpointAO \
                 | sdds2stream -pipe -col=NewControlName,ValueString } results] {
        set status "Error reading $SCRdir/$SCRreference: $results"
    }

    if [pv linkw S37BP1SCRSetpointAO S37B:P1:SCRSetpointAO ] {
        set status "Problem with linking S37BP1SCRSetpointAO to S37B:P1:SCRSetpointAO"
    }
    if [pv linkw S38AP1SCRSetpointAO S38A:P1:SCRSetpointAO ] {
        set status "Problem with linking S38AP1SCRSetpointAO to S38A:P1:SCRSetpointAO"
    }
    set S37BP1SCRSetpointAO [lindex $results 1]
    set S38AP1SCRSetpointAO [lindex $results 3]
    pv putw "S37BP1SCRSetpointAO S38AP1SCRSetpointAO"

    if {[pv umon S37BP1SCRSetpointAO ] != 0} {
        set status "umon error $errorCode"
    }
    if {[pv umon S38AP1SCRSetpointAO ] != 0} {
        set status "umon error $errorCode"
    }
    exec sddsmakedataset /tmp/bpm.reference \
      -col=ControlName,type=string \
      -data=S37B:P1:ms:y:SetpointAO,S38A:P1:ms:y:SetpointAO,S37B:P1:BumpSetpointAO,S38A:P1:BumpSetpointAO \
      -col=Value,type=double \
      -data=$S37BP1SCRSetpointAO,$S38AP1SCRSetpointAO,0,0
    exec sddsprocess $magnetFFfile /tmp/magnet.reference -def=col,Value,0
    exec sddscombine /tmp/bpm.reference /tmp/magnet.reference  /tmp/all.reference -merge -overwrite
}

# proc LaunchControllaw {args} {
#     # sum the SCR and Bump to together to make a regular setpoint
#     exec sddsmakedataset /tmp/combineSCRandBumpPVs \
#       -col=ControlName,type=string \
#       -data=S37B:P1:ms:y:SetpointAO,S38A:P1:ms:y:SetpointAO \
#       -col=S37B:P1:SCRSetpointAO,type=double \
#       -data=1,0 \
#       -col=S37B:P1:BumpSetpointAO,type=double \
#       -data=1,0 \
#       -col=S38A:P1:SCRSetpointAO,type=double \
#       -data=0,1 \
#       -col=S38A:P1:BumpSetpointAO,type=double \
#       -data=0,1 

#     # gain of 0 for testing; gain=-1 otherwise
#     APSExecLog .linkBumps -width 80 -lineLimit 1024 \
#         -unixCommand "sddscontrollaw /tmp/combineSCRandBumpPVs -gain=-1 -proportional -runControlPV=string=APS:RunControlSlot1RC,pingTimeout=10 -runControlDescription=string=CombineBPMsetpoints -verbose -interval=0.5 -infinite"     

#     exec medm -x -attach -macro RCPV=APS:RunControlSlot1RC ./sr/psApp/APSRunControlSingle.adl &
# }

# proc LaunchFeedforward {args} {
#     global  magnetFFfile bpmFFfile energy
#     # the magnet FF table was actually composed from 6 GeV data

# # when we had a feedforward file
# #    exec sddsprocess $magnetFFfile /tmp/magnet.FF.newEnergy \
#       "-redef=col,ActuatorValue,ActuatorValue $energy * 6 /" 
# # a sddscontrollaw file
#     exec sddsprocess $magnetFFfile /tmp/magnet.coeff.newEnergy \
#       "-redef=col,S37:Bump,S37:Bump $energy * 6 /" 

#     exec sddscombine /tmp/magnet.coeff.newEnergy $bpmFFfile /tmp/all.coeff -overWrite -merge

#     APSExecLog .launchFF -width 80 -lineLimit 1024 \
#         -unixCommand "sddscontrollaw /tmp/all.coeff -runControlPV=string=APS:RunControlSlot2RC,pingTimeout=10 -runControlDescription=string=BumpFF -verbose -interval=0.5 -infinite -proportional -gain=-1"     
#     exec medm -x -attach -macro RCPV=APS:RunControlSlot2RC ./sr/psApp/APSRunControlSingle.adl &

# }

proc CreateCoefficients {args} {
    global  magnetFFfile bpmFFfile energy outputDir
    # the magnet FF table was actually composed from 6 GeV data
    
    exec sddsprocess $magnetFFfile $outputDir/magnet.coeff.newEnergy \
      "-redef=col,S37:Bump,S37:Bump $energy * 6 /" 

    exec sddscombine $outputDir/magnet.coeff.newEnergy $bpmFFfile $outputDir/all.coeff -overWrite -merge
}

proc LaunchMonitor {args} {
    global  magnetFFfile bpmFFfile energy
    # make a file
    exec sddsprocess /home/helios/oagData/logging/srBPMAve/srBPMAve.mon /tmp/srBPMAve.small.mon \
      -match=col,ControlName=*ms*SetpointAO,ControlName=*ms*OffsetAO,|,ControlName=*mswAve*ErrorCC,|,ControlName=*mswAve*AdjustedCC,|,ControlName=*msAve*x,|,ControlName=*msAve*y,|

    exec sddsprocess /home/helios/oagData/logging/SRDCPS-HVD/SRDCPS-HVD.mon /tmp/SRDCPS-HVD.small.mon \
      -match=col,ControlName=*DacAI 

    exec sddsprocess /home/helios/oagData/logging/SRDCPS-QS/SRDCPS-QS.mon /tmp/SRDCPS-QS.small.mon \
      -match=col,ControlName=*QS* \
      -reedit=col,ControlName,%/Current/Dac/ -reedit=col,ReadbackName,%/Current/Dac/

    exec sddscombine /home/helios/oagData/logging/SRSynchLightMon/SRSynchLightMon.mon /tmp/srBPMAve.small.mon /tmp/SRDCPS-HVD.small.mon /tmp/SRDCPS-QS.small.mon pcasPVs -pipe=out -merge \
      | sddsconvert -pipe -retain=col,ControlName \
      | sddsprocess -pipe -match=col,ControlName=,! | sddssort -pipe=in S37ScraperBump.mon \
      -col=ControlName -unique

    APSExecLog .launchFF -width 80 -lineLimit 1024 \
      -unixCommand "sddsmonitor S37ScraperBump.mon S37ScraperBump -daily -interval=1 -time=6,hours -runControlPV=string=APS:RunControlSlot3RC,pingTimeout=10 -runControlDescription=string=S37BumpMonitor"

}

proc MakeSetupFrame {widget args} {
    global energy outputFile SCRreference FFfile
    APSStrictParseArguments {parent}
    APSFrame $widget -parent $parent -label "Setup of soft PVs and initial conditions"
    set w $parent$widget.frame

    APSLabeledEntry .bpmffFile -parent $w \
      -label "BPM feedforward file:" -textVariable bpmFFfile \
      -contextHelp "Enter a name for the bpm feedforward file. Required columns are ReadbackValue ActuatorValue. Parameters are ReadbackName ActuatorName" -width 60

    APSLabeledEntry .magnetffFile -parent $w \
      -label "Magnet coefficient file:" -textVariable magnetFFfile \
      -contextHelp "Enter a name for the manget coefficient file. Required are ControlName and S37:Bump. The values of ControlName are the dependent PVs. The values under the S37:Bump columns are the coefficinect. Coefficients will be modified by the energy entered." -width 60

    APSLabeledEntry .scr -parent $w \
      -label "SR SCR file for reference orbit:" -textVariable SCRreference \
      -contextHelp "Uses the S37B:P1 and S38A:P1 bpm setpoint from this file as reference orbit, i.e. bumps will be created relative to these."  -width 60

    APSLabeledEntry .energy -parent $w \
      -label "Energy (GeV):" -textVariable energy \
      -contextHelp "Energy of beam. Coefficients will be scaled from 7 GeV to this energy." -width 15

    APSFrame  .firstRow -parent $w
    set w1 $w.firstRow.frame
    APSFrame  .secondRow -parent $w
    set w2 $w.secondRow.frame

    APSButton .setup -parent $w1 -text "Start soft PVs" -command {
        if [catch {exec cavget -list=$runControlPVName.RUN} pcasRunning] {
            set status "Error reading pcas status: $pcasRunning"
        } else {
            if {$pcasRunning == 1} {
                set status "sddspcas is already running, do not need to start."
                return
            } else {
                if [catch {StartSoftPVs} result] {
                   set status "$result" 
                }
            }
        }
        OpenBumpSoftPVChannels
        exec medm -x -attach -macro RCPV=$runControlPVName ./sr/psApp/APSRunControlSingle.adl &

    } -contextHelp "Sets up sddspcas for running S37 scraper bump relative to SCR."

    APSButton .readscr -parent $w1 -text "Read SCR" -command ReadSCR  -contextHelp "Reads the SCR file and put values into the :SCRsetpointAO soft PVs. This also creates /tmp coefficient and reference files for the feedforward process"

#    APSButton .launchSumControllaw -parent $w1 -text "Launch controllaw" -command LaunchControllaw -contextHelp "Launches a controllaw that continually adds the :SCRsetpointAO and :Bumpsetpoints soft PVs to make the regular :ms:y:Setpoint PV"

#     APSButton .launchFF -parent $w1 -text "Launch feedforward" -command LaunchFeedforward -contextHelp "Launches a feedforward that continually checks the bump amplitude and sets both soft PVs for P1 bump setpoints and FF PVs for correctors and skew quadrupoles."
    APSButton .createCoeff -parent $w1 -text "Create coefficients" -command CreateCoefficients -contextHelp "Create coefficients (file /tmp/all.coeff) that makesrbump will use on demand from a change in S37:Bump, which sets both soft PVs for P1 bump setpoints and FF PVs for correctors and skew quadrupoles."

     APSButton .launchMonitor -parent $w1 -text "Launch monitor" -command LaunchMonitor -contextHelp "Launches a sddsmonitor for beam size, orbit, corrector and softPVs. The output file is in the directory from which the GUI is launched, which could be the root directory if you pressed the restart button under the file menu. Preferably you should start in the daily directory."

   APSButton .stop1 -parent $w2 -text "Stop soft PVs" -command {
        exec caput $runControlPVName.ABRT 1
        after 1000
        exec caput $runControlPVName.CLR 1
    } -contextHelp "Stops measurements."

    APSButton .info -parent $w2 -text "Info on run controls" -command {
        exec medm -x -attach -macro RCPV=$runControlPVName ./sr/psApp/APSRunControlSingle.adl &
        exec medm -x -attach -macro RCPV=APS:RunControlSlot1RC ./sr/psApp/APSRunControlSingle.adl &
        exec medm -x -attach -macro RCPV=APS:RunControlSlot2RC ./sr/psApp/APSRunControlSingle.adl &
        exec medm -x -attach -macro RCPV=APS:RunControlSlot3RC ./sr/psApp/APSRunControlSingle.adl &
    } -contextHelp "Brings up medm of run control."

}

proc MakeControlFrame {widget args} {
    global delta bumpValue deltaLimit
    APSStrictParseArguments {parent}
    APSFrame $widget -parent $parent -label "Control of y-bump in S37 using soft PV S37:Bump"
    set w $parent$widget.frame

    APSLabeledEntry .bump -parent $w -label "Bump value (mm) (PV S37:Bump):" -textVariable bumpValue -width 25 -contextHelp "Linked to the soft PV S37:Bump. Type in a new value or use buttons below. One can change PV S37:Bump, and this tcl variable will follow."
    APSLabeledEntry .step -parent $w -label "Bump change delta (mm)" -textVariable delta -width 25 -contextHelp "Configures the increment buttons below to change the bump amplitude"
    bind $w.bump.entry  <Return> {pv put bumpValue}

    APSLabeledEntry .deltaLimit -parent $w -label "Corrector Delta Limit (A)" -textVariable deltaLimit -width 25 -contextHelp "Largest corrector change in feedforward bump used by makesrbump"

    APSButton .plus  -parent $w -text "Apply +delta"  -command {set bumpValue [expr $bumpValue + $delta]; pv putw bumpValue}  -contextHelp "Increases the bump amplitude by amount delta above"
    APSButton .minus -parent $w -text "Apply -delta"  -command {set bumpValue [expr $bumpValue - $delta]; pv putw bumpValue}  -contextHelp "Decreases the bump amplitude by amount delta above"

}

proc MakeReadbackFrame {widget args} {
    global S37BP1SCRSetpointAO S38AP1SCRSetpointAO S37BP1BumpSetpointAO S38AP1BumpSetpointAO S37BP1SetpointAO S38AP1SetpointAO magnetFFfile
    APSStrictParseArguments {parent}
    
    APSFrame $widget -parent $parent -label "Readback of FF variables"
    set w $parent$widget.frame

    APSLabeledOutput .bp1SCR \
      -parent $w \
      -label "S37B:P1:SCRSetpointAO (mm)"  -width 30 \
      -textVariable S37BP1SCRSetpointAO  \
      -contextHelp "Value of S37B:P1:SCRSetpointAO from SCR file"
    APSLabeledOutput .ap1SCR \
      -parent $w \
      -label "S38A:P1:SCRSetpointAO (mm)"  -width 30 \
      -textVariable S38AP1SCRSetpointAO  \
      -contextHelp "Value of S38A:P1:SCRSetpointAO from SCR file"

   APSLabeledOutput .bp1Bump \
      -parent $w \
      -label "S37B:P1:BumpSetpointAO (mm)"  -width 30 \
      -textVariable S37BP1BumpSetpointAO  \
      -contextHelp "Value of S37B:P1:BumpSetpointAO for given bump amplitude"
    APSLabeledOutput .ap1Bump \
      -parent $w \
      -label "S38A:P1:BumpSetpointAO (mm)"  -width 30 \
      -textVariable S38AP1BumpSetpointAO  \
      -contextHelp "Value of S38A:P1:BumpSetpointAO for given bump amplitude"


   APSLabeledOutput .bp1 \
      -parent $w \
      -label "S37B:P1:ms:y:SetpointAO (mm)"  -width 30 \
      -textVariable S37BP1SetpointAO  \
      -contextHelp "Value of regular S37B:P1:ms:y:SetpointAO"
    APSLabeledOutput .ap1 \
      -parent $w \
      -label "S38A:P1:ms:y:SetpointAO (mm)"  -width 30 \
      -textVariable S38AP1SetpointAO  \
      -contextHelp "Value of regular S38A:P1:ms:y:SetpointAO"
    set pvList {S37B:P1:SCRSetpointAO S38A:P1:SCRSetpointAO S37B:P1:BumpSetpointAO S38A:P1:BumpSetpointAO \
                  S37B:P1:ms:y:SetpointAO S38A:P1:ms:y:SetpointAO}
    set varList {S37BP1SCRSetpointAO S38AP1SCRSetpointAO S37BP1BumpSetpointAO S38AP1BumpSetpointAO  \
                   S37BP1SetpointAO S38AP1SetpointAO}
    if [pv linkw $varList $pvList] {
        set status "problem link pvs $pvList"
    }
    
    pv umon $varList
   
    if [catch {exec sdds2stream -col=ControlName $magnetFFfile} FFpvs] {
        set status "Problem with sdds2stream $FFpvs"
        return -code error "Problem with sdds2stream $FFpvs"
    }
    set index 0
    foreach item $FFpvs {
        global var${index}
        set var${index} 0
        if {[pv linkw var${index} $item ]} {
            set status "Problem with pv link $item"
        }
        if {[pv umon var${index} ] != 0} {
            set status "umon error $errorCode"
        }
        APSLabeledOutput .var${index} \
          -parent $w \
          -label "$item"  -width 30 \
          -textVariable var${index}  \
          -contextHelp "Value of FF PV $item"
        incr index
    }
}

proc StartSoftPVs {args} {
    global runControlPVName softPVFile
    # five PVs to create
    exec sddsmakedataset pcasPVs \
      -column=ControlName,type=string \
      -data=S37:Bump,S37:BumpPreviousValue,S37B:P1:BumpSetpointAO,S38A:P1:BumpSetpointAO,S37B:P1:SCRSetpointAO,S38A:P1:SCRSetpointAO
# this step of clearing the run control is critical (even though the
# RC.MSG is *aborted* because sddspcas will hang up. :/
    
    if [catch {exec cavput -list=$runControlPVName.CLR=1} result] {
        set status "Error clearing sddspcas: $result"
    }

    if [catch {exec sddspcas $softPVFile -runControlPV=string=$runControlPVName,ping=4 \
                 "-runControlDescription=string=S37 scraper bump pcas" -standalone &} result] {
        set status "Error starting sddspcas: $result"
    } else {
        set status "sddspcas started."
        
    }
}

set outputFile ""
set energy 6
set magnetFFfile /home/helios/SR/daily/2019/05/20/2/LowerEnergy/coeff.magnets
set bpmFFfile    /home/helios/SR/daily/2019/05/20/2/LowerEnergy/coeff.bpm
set outputDir [APSGoToDailyDirectory -subdirectory S37ScraperBump]
set softPVFile $outputDir/pcasPVs
set SCRreference "SR2019-343-1209-210803.gz"

if ![file exist $softPVFile] {
    exec sddsmakedataset $softPVFile \
      -column=ControlName,type=string \
      -data=S37:Bump,S37:BumpPreviousValue,S37B:P1:BumpSetpointAO,S38A:P1:BumpSetpointAO,S37B:P1:SCRSetpointAO,S38A:P1:SCRSetpointAO
}

exec cavput -list=S37B,S38A -list=:P1:ms:y:SetpointAO. -list=DRVL=-10,DRVH=10 
# avoid any problems with limits

set delta 0.5

catch {exec medm -x -cleanup -attach -dg +500+50 -macro RCPV=$runControlPVName \
         /usr/local/iocapps/adlsys/sr/psApp/APSRunControlSingle.adl &}

if [catch {exec cavget -list=$runControlPVName.RUN} pcasRunning] {
    set status "Error reading pcas status: $pcasRunning"
} else {
    if {$pcasRunning == 1} {
        puts stderr "sddspcas for S37ScraperBump is already running, exit..."
        puts stderr "if you want to start a new GUI, please kill the sddspcas for S37ScraperBump first!"
        exit 1
    } else {
        if [catch {StartSoftPVs} result] {
            set status "$result" 
        }
    }
}
after 1000
set deltaLimit 4.5
MakeSetupFrame    .setup    -parent .userFrame
MakeControlFrame  .control  -parent .userFrame
MakeReadbackFrame .readback -parent .userFrame
OpenBumpSoftPVChannels
set oldBumpValue [exec cavget -list=S37:Bump]
CreateCoefficients
set status Ready.

# **************************** Emacs Editing Sequences *****************
# Local Variables:
# mode: tcl
# End:
