#!/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] ITSphase_scan.sdds]
set launchPhase -43
set initialValue -1.5
set finalValue 10
set nToAverage 5
set nPoints 116
set postChangePause 1.0
set interMeasPause 0.2
set analysisMethod rising-edge
set parPVList {LTS:PT3:DC1ARF.VAL L1:LTS:GUN:VP:CO1 L1:LTS:GUN:VP:CO2 L1:AS1:CC:02 L1:PC1:SM:PS:CurrentAI}

APSApplication . -name ITSPCGunPhaseScanAndSet
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 -commandList {"set launchPhase -10" "set launchPhase -50"}

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
    }
}

set ReadPars 0
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 parPVList parValueList
    if $doRun {
        if [catch {exec cavget -list=[join $parPVList ,] -pend=20} parValueList] {
            return -code error "Error reading pv values: $parValueList"
        }
        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/ITSphaseScanTemplate.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 "AddParPVs -outputFile $outputFile;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=LTS:CM1:measChargeCM -points=3
    }
    if $doPlot {
        
        exec sddsplot -layout=1,2 -sep -grap=line \
          -col=L3:KY:DC2AIQ.VAL,LTS:CM1:measChargeCM \
          -string=@SolenoidCurrString,p=0.2,q=.85 \
          -string=@ForwardRFString,p=0.2,q=0.75 \
          "-topline=L3 Phase Setpoint versus Charge - SMOOTHED" "-title=" \
          -grap=sym $outputFile.smo \
          -col=L3:PP:phaseAdjAO,LTS:CM1:measChargeCM \
          "-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 AddParPVs {args} {
    set outputFile ""
    APSParseArguments {outputFile}
    global parPVList parValueList
    set option ""
    foreach pv $parPVList val $parValueList {
        lappend option "-define=par,$pv,$val"
    }
    if [catch {eval exec sddsprocess $outputFile -nowarnings $option -pipe=out \
                 | sddsprocess -pipe=in $outputFile.1  \
                 \"-print=par,SolenoidCurrString,Isd = %.2f A,L1:PC1:SM:PS:CurrentAI\" \
                 \"-print=par,ForwardRFString,Forward RF = %.0f W,LTS:PT3:DC1ARF.VAL\"  } result] {
        return -code "Error in defining parameters to output file: $result"
    }
    exec mv $outputFile.1 $outputFile
}
proc ProcessPCGunPhaseScan {args} {
    set input ""
    set method peak
    set launchPhase 40
    APSStrictParseArguments {input method launchPhase}
    global ReadPars parPVList parValueList
    
    set options ""
    if $ReadPars {
        foreach pv $parPVList val $valueList {
            lappend options "-define=par,$pv,$val"
        }
    }
    switch $method {
        rising-edge {
            set tmpRoot /tmp/[APSTmpString]
            APSAddToTempFileList $tmpRoot.fil $tmpRoot.proc1 $tmpRoot.proc2 
            exec sddsbreak $input -pipe=out -decreaseof=L3:KY:DC2AIQ.VAL \
              | sddsprocess -pipe -process=L3:KY:DC2AIQ.VAL,count,Count  \
              | sddssort -pipe -param=Count,decr \
              | sddsconvert -pipe -topage=1 \
              | sddscombine -pipe -merge \
              | sddsprocess -pipe \
              -process=L3:KY:DC2AIQ.VAL,first,startPhase \
              "-define=col,deltaPhase,L3:KY:DC2AIQ.VAL startPhase -" \
              -filter=column,deltaPhase,0,360 \
              -process=LTS:CM1:measChargeCM,top,CM1Top \
              -process=LTS:CM1:measChargeCM,base,CM1Base \
              "-define=column,CM1Norm,LTS:CM1:measChargeCM CM1Base - CM1Top CM1Base - /" \
              "-process=CM1Norm,zerocrossing,PhaseAdjZ1,func=L3:PP:phaseAdjAO,offset=-0.2" \
              "-process=CM1Norm,zerocrossing,PhaseAdjZ2,func=L3:PP:phaseAdjAO,offset=-0.75" \
              "-define=column,PhaseAdjNorm,L3:PP:phaseAdjAO PhaseAdjZ1 - PhaseAdjZ2 PhaseAdjZ1 - /" \
              | tee $tmpRoot.filt \
              | sddsprocess -pipe=in $tmpRoot.proc1 \
              -filter=column,PhaseAdjNorm,0,1 \
              -process=L3:PP:phaseAdjAO,intercept,phaseAdjIntercept,func=CM1Norm \
              -process=L3:KY:DC2AIQ.VAL,intercept,phaseIntercept,func=CM1Norm
           # puts $tmpRoot.proc2
            exec sddsxref $tmpRoot.filt $tmpRoot.proc1 -leave=* -transfer=param,* -pipe=out \
              | sddsprocess -pipe=in $tmpRoot.proc2 \
              "-define=column,PhaseOffset,L3:KY:DC2AIQ.VAL phaseIntercept - $launchPhase +" \
              "-process=PhaseOffset,zerocrossing,Setpoint,func=L3:PP:phaseAdjAO" \
              "-process=PhaseOffset,zerocrossing,Value,func=LTS:CM1:measChargeCM"
            set newSetting [exec sdds2stream $tmpRoot.proc2 -parameter=Setpoint]
            exec sddsplot -column=L3:PP:phaseAdjAO,LTS:CM1:measChargeCM $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=LTS:CM1:measChargeCM,max,MaxPos,position,functionOf=L3:PP:phaseAdjAO \
                              "-define=parameter,newSetting,$launchPhase 39 / MaxPos +" \
                              | sdds2stream -pipe -parameter=newSetting]
        }
    }
    return $newSetting
}
