#!/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)]
APSDebugPath
set CVSRevisionAuthor "\$Author: shang $"

set outputFile [file join [APSGoToDailyDirectory] phase_scan.sdds]
set launchPhase -50
set initialValue -1.5
set finalValue 10
set nToAverage 5
set nPoints 116
set postChangePause 0.2
set interMeasPause 0.2
set analysisMethod peak
APSApplication . -name PCGunPhaseScanAndSet
set status ""
APSScrolledStatus .status -parent .userFrame -textVariable status -height 4 -width 60

APSLabeledEntry .output -parent .userFrame -label "Output file: " \
    -textVariable outputFile -width 60
APSLabeledEntry .lphase -parent .userFrame -label "Launch phase: " \
    -textVariable launchPhase
APSLabeledEntry .npt -parent .userFrame -label "Number of points: " \
    -textVariable nPoints
APSLabeledEntry .init -parent .userFrame -label "Initial phase setpoint: " \
    -textVariable initialValue
APSLabeledEntry .final -parent .userFrame -label "Final phase setpoint: " \
    -textVariable finalValue
APSLabeledEntry .pcp -parent .userFrame -label "Post-change pause (s): " \
    -textVariable postChangePause
APSLabeledEntry .nave -parent .userFrame -label "Number of average: " \
    -textVariable nToAverage 
APSLabeledEntry .imp -parent .userFrame -label "Intermeasurement pause (s): " \
    -textVariable interMeasPause
APSRadioButtonFrame .rb1 -parent .userFrame -label "Analysis method: " \
    -variable analysisMethod -buttonList "peak rising-edge" \
    -valueList "peak rising-edge" -orientation horizontal

APSButton .run -parent .userFrame -text "Run/Analyze/Plot/Set" \
    -command "ChangeButtonState 0; \
    RunPhaseScanAndSet -doRun 1 -doAnalyze 1 -doPlot 1 -doSet 1; \
    ChangeButtonState 1"
APSButton .analyze -parent .userFrame -text "Analyze/Plot/Set" \
    -command "ChangeButtonState 0; RunPhaseScanAndSet -doRun 0 -doAnalyze 1 -doPlot 1 -doSet 1; \
    ChangeButtonState 1"
APSButton .display -parent .userFrame -text "Plot" \
    -command "ChangeButtonState 0; RunPhaseScanAndSet -doRun 0 -doAnalyze 0 -doPlot 1 -doSet 0; \
    ChangeButtonState 1" 

proc ChangeButtonState {state} {
    if $state {
        APSEnableButton .userFrame.run.button 
        APSEnableButton .userFrame.analyze.button
        APSEnableButton .userFrame.display.button
    } else {
        APSDisableButton .userFrame.run.button 
        APSDisableButton .userFrame.analyze.button
        APSDisableButton .userFrame.display.button
    }
}

proc RunPhaseScanAndSet {args} {
    set doSet 0
    set doRun 0
    set doAnalyze 0
    set doPlot 0
    APSStrictParseArguments {doSet doRun doAnalyze doPlot}

    global outputFile launchPhase runDone analysisMethod
    global initialValue finalValue nToAverage nPoints postChangePause interMeasPause
    set runDone 0

    if $doRun {
        if [file exists $outputFile] {
            if [APSMultipleChoice [APSUniqueName .] \
                  -question "$outputFile exists.  What do you want to do?" \
                  -labelList "Abort Overwrite" \
                  -returnList "1 0"] {
                return 
            }
        }
        file delete -force $outputFile
        if [catch {exec cavget -list=L3:AUTO:PH:modeMO} L3AutoPhaseModeOrig] {
            return -code error "$L3AutoPhaseMode"
        }
        if [catch {exec cavput -list=L3:AUTO:PH:modeMO=Disabled} result] {
            return -code error "$result"
        }
        #APSConfigureCameraAndScreenPVs -flagIn 1 -lampOn 0 -flag LI:FL:PG1C1 -cameraType CID \
        #  -actuatorNumber 1 -system Linac -statusCallback "APSSetVarAndUpdate status"
        #if {[catch {exec cavget -list=LI:VD1:syncCaptureRateC -noQuotes} syncCaptureRate] || \
         #     [catch {exec cavput "-list=LI:VD1:syncCaptureRateC=Beam Rate"} result]} {
         #   return -code error "Problem getting or setting linac video synch capture rate: $syncCaptureRate\n$result"
        #}
        
        exec replaceText /home/helios/oagData/linac/PCGun/phaseScan/phaseScanTemplate.exp $outputFile.exp \
          -original=<nAve>,<initialValue>,<finalValue>,<postChangePause>,<interMeasPause>,<nPoints> \
          -replace=$nToAverage,$initialValue,$finalValue,$postChangePause,$interMeasPause,$nPoints 
        APSExecLog [APSUniqueName .] -unixCommand \
          "sddsexperiment $outputFile.exp $outputFile -verbose -summar " \
          -cancelCallback "set runDone 2" \
          -abortCallback "set runDone 2" \
          -callback "set runDone 1" -width 80 
        tkwait variable runDone
#        APSConfigureCameraAndScreenPVs -flagIn 0  -lampOn 0 -flag LI:FL:PG1C1 -cameraType CID \
#          -actuatorNumber 1 -system Linac -statusCallback "APSSetVarAndUpdate status"
        if [catch {exec cavput -list=L3:AUTO:PH:modeMO=$L3AutoPhaseModeOrig} result] {
            return -code error "$result"
        }
        if $runDone!=1 {
            APSSetVarAndUpdate status "Run cancelled"
            return
        }
    }
    
    if $doAnalyze {
        exec sddssmooth $outputFile $outputFile.smo -col=L1:PG1:CM1:measCurrentCC -points=3
    }
    if $doPlot {
        exec sddsplot -layout=1,2 -sep -grap=line \
          -col=L1:PG1:DC1AIQ.VAL,L1:PG1:CM1:measCurrentCC \
          "-topline=L3 Phase Setpoint versus Charge - SMOOTHED" "-title=" \
          -grap=sym $outputFile.smo \
          -col=L3:PP:phaseAdjAO,L1:PG1:CM1:measCurrentCC \
          "-topline=L3 Phase Setpoint versus Charge" "-title=" $outputFile &
        after 1000
    }

    if $doSet {
        set newSetting [ProcessPCGunPhaseScan \
                        -input $outputFile.smo -method $analysisMethod \
                        -launchPhase $launchPhase]
        after 1000

        if [APSQueryToProceed \
              -message "The phase setting has been determined to be $newSetting.  Ok to set?"] {
            if [catch {exec cavget -list=L3:AUTO:PH:modeMO} L3AutoPhaseModeOrig] {
                return -code error "$L3AutoPhaseMode"
            }
            exec cavput -list=L3:AUTO:PH:modeMO=Disabled
            exec cavput -list=L3:PP:phaseAdjAO=$newSetting
            if [string compare $L3AutoPhaseModeOrig Disabled]!=0 {
                after 2000
                exec cavput -list=L1:AUTO:PH:holdAtMeasdBO=1
            }
        }
    }
}

proc ProcessPCGunPhaseScan {args} {
    set input ""
    set method peak
    set launchPhase 40
    APSStrictParseArguments {input method launchPhase}

    switch $method {
        rising-edge {
            set tmpRoot /tmp/[APSTmpString]
            APSAddToTempFileList $tmpRoot.fil $tmpRoot.proc1 $tmpRoot.proc2 
            exec sddsbreak $input -pipe=out -decreaseof=L1:PG1:DC1AIQ.VAL \
              | sddsprocess -pipe -process=L1:PG1:DC1AIQ.VAL,count,Count  \
              | sddssort -pipe -param=Count,decr \
              | sddsconvert -pipe -topage=1 \
              | sddsprocess -pipe \
              -process=L1:PG1:DC1AIQ.VAL,first,startPhase \
              "-define=col,deltaPhase,L1:PG1:DC1AIQ.VAL startPhase -" \
              -process=L1:PG1:CM1:measCurrentCC,top,CM1Top \
              -process=L1:PG1:CM1:measCurrentCC,base,CM1Base \
              "-define=column,CM1Norm,L1:PG1:CM1:measCurrentCC CM1Base - CM1Top CM1Base - /" \
              "-process=CM1Norm,zerocrossing,PhaseAdjZ1,func=L3:PP:phaseAdjAO,offset=-0.05" \
              "-process=CM1Norm,zerocrossing,PhaseAdjZ2,func=L3:PP:phaseAdjAO,offset=-0.75" \
              "-define=column,PhaseAdjNorm,L3:PP:phaseAdjAO PhaseAdjZ1 - PhaseAdjZ2 PhaseAdjZ1 - /" \
              | sddsprocess -pipe -process=L1:PG1:CM1:measCurrentCC,max,PeakPos,position,functionof=deltaPhase \
              -process=deltaPhase,zerocrossing,ZeroPos,function=L1:PG1:CM1:measCurrentCC \
              | sddsprocess -pipe "-define=par,deltaPhase1,ZeroPos PeakPos > ? ZeroPos : 0" \
              "-define=par,deltaPhase2,ZeroPos PeakPos > ? 360 : PeakPos" \
              | sddsprocess -pipe -filter=col,deltaPhase,deltaPhase1,deltaPhase2 \
              | tee $tmpRoot.filt \
              | sddsprocess -pipe=in $tmpRoot.proc1 \
              -filter=column,PhaseAdjNorm,0,1 \
              -process=L3:PP:phaseAdjAO,intercept,phaseAdjIntercept,func=CM1Norm \
              -process=L1:PG1:DC1AIQ.VAL,intercept,phaseIntercept,func=CM1Norm
            
            exec sddsxref $tmpRoot.filt $tmpRoot.proc1 -leave=* -transfer=param,* -pipe=out \
              | sddsprocess -pipe=in $tmpRoot.proc2 \
              "-define=column,PhaseOffset,L1:PG1:DC1AIQ.VAL phaseIntercept - $launchPhase +" \
              "-process=PhaseOffset,zerocrossing,Setpoint,func=L3:PP:phaseAdjAO" \
              "-process=PhaseOffset,zerocrossing,Value,func=L1:PG1:CM1:measCurrentCC"
            set newSetting [exec sdds2stream $tmpRoot.proc2 -parameter=Setpoint]

            exec sddsplot -column=L3:PP:phaseAdjAO,L1:PG1:CM1:measCurrentCC $tmpRoot.filt $tmpRoot.proc1 \
              -graph=line,vary -parameter=phaseAdjIntercept,CM1Base -graph=sym,scale=2,subtype=1 $tmpRoot.proc1 \
              -parameter=Setpoint,Value -graph=sym,scale=2,subtype=1 $tmpRoot.proc2 \
              -topline=@Setpoint &
        }
        default {
            set newSetting [exec sddsprocess $input -pipe=out \
                              -process=L1:PG1:CM1:measCurrentCC,max,MaxPos,position,functionOf=L3:PP:phaseAdjAO \
                              "-define=parameter,newSetting,$launchPhase 39 / MaxPos +" \
                              | sdds2stream -pipe -parameter=newSetting]
        }
    }
    return $newSetting
}
