#!/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: borland $"

proc setStatus {text} {
    APSSetVarAndUpdate status $text
}

proc GoToDailyDirectory {} {
    global Rootname
    set DD [APSGoToDailyDirectory]
    cd $DD
    set Rootname [file join $DD $Rootname]
}

proc BuildApplication {} {

    APSApplication . -name CorrectLinacDispersionAtFlags

    global status
    set status "This script measures the dispersion in or after the "
    APSScrolledStatus .status -parent .userFrame -textVariable status -height 10 -width 60
    set status "linac using the L3:FS3 and L3:FS5 flags by modulating "
    set status "the L2 PFN.  This script will enable phase loops and "
    set status "suspend power controllaws."

    # output file 
    APSFrame .file -parent .userFrame -label "Output File"
    set w .userFrame.file.frame
    global Rootname DataFileIndex
    set Rootname linacDisp
    set DataFileIndex -1
    APSLabeledEntry .le1 -parent $w -label "Rootname: " -textVariable Rootname \
      -width 60 -contextHelp "Enter the rootname, including the directory name,\
 for output files"
    APSLabeledEntry .le2 -parent $w -label "Index: " -textVariable DataFileIndex \
      -contextHelp "The output file index for the next run is obtained by incrementing\
 this value by 1."
    APSButton .gtdd -parent $w -text "Go to daily dir" -command \
      GoToDailyDirectory -contextHelp "Creates and moves to the daily directory."

    # measurement parameters 
    APSFrame .parameters -parent .userFrame -label "Measurement Parameters"
    set w .userFrame.parameters.frame
    global PFNRange PFNPoints PostChangePause Averages InterMeasPause Sector AutoSetAperture AutoSetROI
    global BeamEnergy LowRes SwappedRes UseFlag
    set PFNRange 0.5
    set PFNPoints 5
    set PostChangePause 10
    set Averages 30
    set InterMeasPause 0.5
    set Sector L2
    set AutoSetAperture 0
    set AutoSetROI 0
    set BeamEnergy 150
    set LowRes 1
    set SwappedRes(L3:FS1) 1
    set SwappedRes(L3:FS2) 0
    set SwappedRes(L3:FS3) 0
    set SwappedRes(L3:FS4) 0
    set SwappedRes(L3:FS5) 0
    set UseFlag(L3:FS1) 1
    set UseFlag(L3:FS2) 1
    set UseFlag(L3:FS3) 1
    set UseFlag(L3:FS4) 1
    set UseFlag(L3:FS5) 1
    APSRadioButtonFrame .rb1 -parent $w -label "Auto-set ROI:      " \
      -valueList "1 0" -buttonList "Yes No" -orientation horizontal \
      -variable AutoSetROI -contextHelp \
      "Select whether to automatically set the region of interest for screen"
    APSRadioButtonFrame .rb2 -parent $w -label "Auto-set Aperture: " \
      -valueList "1 0" -buttonList "Yes No" -orientation horizontal \
      -variable AutoSetAperture -contextHelp \
      "Select whether to automatically set the camera aperture for screen"
    APSRadioButtonFrame .rb3 -parent $w -label "Use low-res:       " \
      -valueList "1 0" -buttonList "Yes No" -orientation horizontal \
      -variable LowRes -contextHelp \
      "Select whether to use low-res cameras for L3:FS2, FS3, FS4, and FS5.  Recommended for RG2 but not for PC gun."
    APSCheckButtonFrame .cb0 -parent $w -label "Flags to use:    " \
      -buttonList {L3:FS2 L3:FS3 L3:FS4 L3:FS5} \
      -variableList {UseFlag(L3:FS2) UseFlag(L3:FS3) \
                        UseFlag(L3:FS4) UseFlag(L3:FS5)} \
      -orientation horizontal -allNone 0 \
      -contextHelp "Can be used if high and low resolution controls are swapped on a flag."
    APSCheckButtonFrame .cb1 -parent $w -label "Swapped H/L Res: " \
      -buttonList {L3:FS1 L3:FS2 L3:FS3 L3:FS4 L3:FS5} \
      -variableList {SwappedRes(L3:FS1) SwappedRes(L3:FS2) SwappedRes(L3:FS3) \
                        SwappedRes(L3:FS4) SwappedRes(L3:FS5)} \
      -orientation horizontal -allNone 0 \
      -contextHelp "Can be used if high and low resolution controls are swapped on a flag."
    APSLabeledEntry .pfnRange -parent $w -label "PFN sweep range (kV): " \
      -textVariable PFNRange -contextHelp \
      "Enter the amount by which to sweep the PFN, centered on the present setpoint." 
    APSLabeledEntry .pfnPoints -parent $w -label "PFN values: " \
      -textVariable PFNPoints -contextHelp \
      "Enter the number of values of the PFN at which to take data."
    APSLabeledEntry .pause -parent $w -label "Post-change Pause (s):" -textVariable \
      PostChangePause -contextHelp \
      "Enter the number of seconds to wait after changing the PFN before taking data.\
  You should allow sufficient time for the phase feedback on L2 to converge."
    APSLabeledEntry .averages -parent $w -label "Readings to Average:" -textVariable \
      Averages -contextHelp "Enter the number of readings to average at each step of each cycle.\
 This is in addition to any averaging the happens in the IOC."
    APSLabeledEntry .interMeasPause -parent $w -label "Pause Between Readings (s):" \
      -textVariable InterMeasPause -contextHelp "Enter the pause between successive readings\
 that are being averaged.  Should match the IOC averaging time, if any, for BPMs."
    APSLabeledEntry .energy -parent $w -label "Beam Energy (MeV): " \
      -textVariable BeamEnergy -contextHelp "Enter the beam energy in MeV."

    global CorrectionGain 
    set CorrectionGain 1.0
    APSLabeledEntry .gain -parent $w -label "Correction gain: " \
      -textVariable CorrectionGain -contextHelp "Energy the correction gain (fractional value)"

    # action buttons
    APSFrame .action -parent .userFrame 
    set w .userFrame.action.frame
    APSButton .run -parent $w -text Run -command \
      { incr DataFileIndex ; \
          APSPerformLinacFlagDispersionMeasurement \
          -rootname [format $Rootname-%03ld $DataFileIndex] \
          -interactive 1 -autoSetROI $AutoSetROI -autoSetAperture $AutoSetAperture \
          -pfnRange $PFNRange -pfnPoints $PFNPoints -postChangePause $PostChangePause \
          -averages $Averages -interMeasPause $InterMeasPause -process 1 -display 1 \
          -useLowRes $LowRes -statusCallback setStatus \
          -swapCameraArray [array get SwappedRes] \
          -useFlagArray [array get UseFlag]} \
      -contextHelp "Begin a measurement.  Data is automatically processed and displayed."
    APSButton .review -parent $w -text Review... -command \
      {ReviewMeasurement -directory [file dirname $Rootname]} \
      -contextHelp "Reviews results of a dispersion measurement."
    APSButton .correct -parent $w -text Correct... -command \
      {CorrectDispersion -gain $CorrectionGain -statusCallback setStatus \
         -directory [file dirname $Rootname] -beamEnergy $BeamEnergy} \
      -contextHelp "Allows correcting the dispersion based on a previous measurement."
}

proc APSPerformLinacFlagDispersionMeasurement {args} {
    global apsPerformLinacFlagDispersionMeasurementControl
    set apsPerformLinacFlagDispersionMeasurementControl 0

    set rootname ""
    set interactive 1
    set pfnRange 1
    set pfnPoints 7
    set postChangePause 2
    set averages 10
    set interMeasPause 1
    set process 0
    set display 0
    set statusCallback APSNoOp 
    set autoSetROI 1
    set autoSetAperture 1
    set abortVariable ""
    set useLowRes 0
    set swapCameraArray ""
    set useFlagArray ""
    set args0 $args
    if {[APSStrictParseArguments {rootname interactive pfnRange pfnPoints useLowRes \
                                    postChangePause averages interMeasPause process display \
                                    statusCallback autoSetROI autoSetAperture abortVariable \
                                    swapCameraArray useFlagArray}] || \
          ![llength $useFlagArray] || \
          ![string length [set rootname [string trim $rootname]]] || \
          $pfnRange<0 || $pfnPoints<1 || $postChangePause<0 || $averages<0 || \
          $interMeasPause<0} {
        return -code error "APSPerformLinacFlagDispersionMeasurement: parameter error: $args0"
    }
    set sector L2
    if [llength $swapCameraArray] {
        array set swapCamera $swapCameraArray
    } 
    array set useFlag $useFlagArray
    if [string length $abortVariable] {
        global $abortVariable
    }
    # check for prior existence of the output 
    if {[llength [glob -nocomplain $rootname.*.*]]} {
        if {$interactive && \
              [APSMultipleChoice [APSUniqueName .] -question \
                 "$rootname is use already.  What do you want to do?" \
                 -returnList {1 0} -labelList {Abort Overwrite}]} {
            return
        }
        eval file delete -force [glob -nocomplain $rootname.*.*]
    }

    # create the input file for sddsexperiment
    set tmpFile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID PerformLinacDispersionMeasurement \
      -fileList $tmpFile
    set halfRange [expr $pfnRange/2.0]
    exec replace /home/helios/oagData/linac/dispersionMeasurement/flagDispersionTemplate.exp \
      $tmpFile \
      -original=<points>,<halfRange>,<averages>,<postChangePause>,<interMeasPause> \
      -replace=$pfnPoints,$halfRange,$averages,$postChangePause,$interMeasPause

    # enable phase control loop on ${sector}
    if [catch {exec cavput -list=${sector}:AUTO:PH:holdAtMeasdBO=1} result] {
        return -code error "APSPerformLinacFlagDispersionMeasurement: $result"
    }
    # save state of power control loop on ${sector}
#    if [catch {exec cavget -list=L:${sector}StabilizerRC.SUSP -cavputform} ControllawState] {
#        return -code error "APSPerformLinacFlagDispersionMeasurement: $ControllawState"
#    }
    if [catch {exec cavget -list=L:${sector}Stabilizer:SDDS.SUSP -cavputform} ControllawState] {
        return -code error "APSPerformLinacFlagDispersionMeasurement: $ControllawState"
    }
    # suspend power control loop on ${sector} 
#    if [catch {exec cavput -list=L:${sector}StabilizerRC -list=.SUSP=1} result] {
#        return -code error "APSPerformLinacFlagDispersionMeasurement: $result"
#    } 
    if [catch {exec cavput -list=L:${sector}Stabilizer:SDDS -list=.SUSP=1} result] {
        return -code error "APSPerformLinacFlagDispersionMeasurement: $result"
    } 

    # run the experiment 
    foreach flag {L3:FS1 L3:FS2 L3:FS3 L3:FS4 L3:FS5} lowres {1 0 0 0 0} {
        if !$useFlag($flag) continue
        if {$useLowRes && !$lowres} {
            set lowres 1
        }
        set fileExten H
        if $lowres {
            set fileExten L
        }
        if {[llength $swapCameraArray]} {
            if $swapCamera($flag) {
                # for cameras that have L and H swapped.
                if $lowres {
                    set lowres 0
                } else {
                    set lowres 1
                }
            }
        }
        if $lowres {
            set whichCamera L
        } else {
            set whichCamera H
        }
        # configure flag
        if {[string length $abortVariable] && [set $abortVariable]} {
            eval file delete -force [glob -nocomplain $rootname.L3:FS?.?]
            return -code error "APSPerformLinacFlagDispersionMeasurement: aborted."
        }
        APSConfigureCameraAndScreenPVs -flagIn 1 -system Linac \
          -flag $flag -actuatorNumber 1 -statusCallback $statusCallback \
          -lampOn 0 -ignoreFlagReadback 1 -cameraType CCD${whichCamera}
        if [catch {exec cavput -list=LI:VD1: \
                     -list=imageSourceC=Original,cameraTrigDelayPD.GATE=Enable,twoHzFrameDelayC=0} result] {
            return -code error "Problem setting up video system: $result"
        }
        set val "Beam Rate"
        if [catch {exec cavput -list=LI:VD1:syncCaptureRateC=$val} result] {
            return -code error "Problem setting up video system: $result"
        }
        set val "2 Hz"
        if [catch {exec cavput -list=LI:VD1:bkgndCaptureRateC=$val} result] {
            return -code error "Problem setting up video system: $result"
        }
        set val "Specific Frame"
        if [catch {exec cavput -list=LI:VD1:bkgndCaptureModeC=$val} result] {
            return -code error "Problem setting up video system: $result"
        }
        set val "2 Hz-Frame \#"
        if [catch {exec cavput -list=LI:VD1:captureModeC=$val} result] {
            return -code error "Problem setting up video system: $result"
        }
        after 5000
        if {$autoSetROI && \
              [catch {APSSetLinacFlagROI -flagList $flag -lowres $lowres \
                        -statusCallback $statusCallback \
                        -factor 2 -xMinSize 450 -yMinSize 40 -alreadyInserted 1} result]} {
            return -code error "Problem setting up screen: $result"
        }
        if {$autoSetAperture &&
            [catch {APSSetBCCameraAperture -flagList $flag -lowres $lowres \
                      -abortVariable $abortVariable \
                      -statusCallback $statusCallback -tries 4 -alreadyInserted 1} result]} {
            return -code error "Problem setting up screen: $result"
        }
        if [catch {exec cavput -list=LI:VD1:imageSourceC=Subtracted} result] {
            return -code error "Problem setting up screen: $result"
        }
        if $interactive {
            set w [APSUniqueName .]
            global apsPerformLinacFlagDispersionMeasurementControl
            set apsPerformLinacFlagDispersionMeasurementControl 0
            APSExecLog $w -width 100 \
              -unixCommand "sddsexperiment $tmpFile $rootname.$flag.$fileExten -verbose -summarize" \
              -callback {set apsPerformLinacFlagDispersionMeasurementControl done} \
              -abortCallback {set apsPerformLinacFlagDispersionMeasurementControl abort} \
              -cancelCallback {set apsPerformLinacFlagDispersionMeasurementControl cancel}
            tkwait variable apsPerformLinacFlagDispersionMeasurementControl
            switch $apsPerformLinacFlagDispersionMeasurementControl {
                abort -
                cancel {
                    file delete -force $rootname
                    catch {exec cavput -list=$ControllawState}
                    return -code error "Experiment aborted."
                }
                default {
                    destroy $w
                }
            }
        } else {
            if [catch {exec sddsexperiment $tmpFile $rootname.$flag.$fileExten} result] {
                catch {exec cavput -list=$ControllawState}
                return -code error "APSPerformLinacFlagDispersionMeasurement: $result"
            }
        }
        # remove flag
        APSConfigureCameraAndScreenPVs -flagIn 0 -system Linac \
          -flag $flag -actuatorNumber 1 -statusCallback $statusCallback \
          -lampOn 0 -ignoreFlagReadback 1 -cameraType CCD${whichCamera}
    }

    # should probably do something if there is an error here
    catch {exec cavput -list=$ControllawState}
    
    if {$process && \
          [catch {APSProcessLinacFlagDispersionMeasurement -rootname $rootname \
                    -display $display -sector $sector} result]} {
        return -code error "APSPerformLinacFlagDispersionMeasurement: $result"
    }
}


proc APSProcessLinacFlagDispersionMeasurement {args} {
    set rootname ""
    set display 0
    set sector L2
    if {[APSStrictParseArguments {rootname display sector}] || \
          ![string length [set rootname [string trim $rootname]]]} {
        return -code error "APSProcessLinacDispersionMeasurement: parameter error"
    }
    if [string match L\[12345\] $sector]==0 {
        return -code error "APSProcessLinacDispersionMeasurement: sector is invalid: $sector"
    }
    set fileList [lsort [glob -nocomplain $rootname.L3:FS?.\[HL\]]]
    if [llength $fileList]<2 {
        return -code error "Too few files match $rootname.L3:FS?.\[HL\]: $fileList"
    }
    set flagList [eval os editstring Z.%/.H//%/.L// $fileList]
    set cameraList [eval os editstring 2Z. $fileList] 
    set fileList ""

    foreach flag $flagList camera $cameraList {
        setStatus "Processing data for $flag"
        if [catch {exec sddsprocess /home/helios/oagData/TransportLineEmittance/BCCameraCal.sdds \
                     -pipe=out -match=col,FlagName=$flag \
                     | sdds2stream -pipe -column=${camera}x,${camera}y} dataList] {
            return -code error "APSProcessLinacFlagDispersionMeasurement: $dataList"
        }
        set xCal [lindex $dataList 0]
        set yCal [lindex $dataList 1]
        
        exec sddsoutlier $rootname.$flag.$camera -pipe=out \
            -stDevLimit=2 -passes=1 -columns=xRawCentroid,yRawCentroid \
          | sddsprocess -pipe \
          "-defi=col,xCentroid,xRawCentroid $xCal * 1e6 /,units=m" \
          "-defi=col,yCentroid,yRawCentroid $yCal * 1e6 /,units=m" \
          | sddsbreak -pipe -change=L2PFNVoltage \
          | sddsprocess -pipe \
            -process=L2PFNVoltage,ave,L2PFNVoltage \
            -process=?Centroid,ave,%s \
            -process=?Centroid,sigma,%sSigma \
          | sddscollapse -pipe \
          | sddsmpfit -pipe -terms=2 -indep=L2PFNVoltage -depen=?Centroid \
          -sigmaDepen=%sSigma \
          | tee $rootname.$flag.$camera.fit \
          | sddscollapse -pipe \
          | sddsprocess -pipe=in $rootname.$flag.proc \
          -retain=col,?CentroidSlope* -print=col,Flag,$flag
        foreach plane {x y} {
            lappend plotOptList -column=L2PFNVoltage,${plane}Centroid,${plane}CentroidSigma -graph=error \
              $rootname.$flag.$camera.fit -column=L2PFNVoltage,${plane}CentroidFit \
              $rootname.$flag.$camera.fit -end
        }
        lappend fileList $rootname.$flag.proc
    }
    eval exec sddscombine $fileList $rootname.proc  -overwrite -merge

    if $display {
        eval exec sddsplot $plotOptList &
        exec sddsplot $rootname.proc \
          -col=Flag,xCentroidSlope,xCentroidSlopeSigma -graph=error,subtype=0 \
          -legend=spec=x \
          -col=Flag,yCentroidSlope,yCentroidSlopeSigma -graph=error,subtype=1 \
          -legend=spec=y &
        exec sddsprintout -col=Flag -col=*Slope* $rootname.proc $rootname.print
        APSFileDisplayWindow [APSUniqueName .] \
          -deleteOnClose 1 -width 100 -fileName $rootname.print
    }
}

proc ChooseMeasurement {args} {
    set directory ""
    if {[APSStrictParseArguments {directory}]} {
        return -code error "ChooseMeasurement: parameter error"
    }
    if {![string length $directory] || ![file exists $directory] || \
          ![file isdirectory $directory]} {
        set directory [pwd]
    }
    set fileList [lsort [glob -nocomplain $directory/*.L3:FS1.L $directory/*.L3:FS1.H]]
    if ![llength $fileList] {
        return -code error "No files found."
    }
    set item [APSChooseItemFromList \
                -name "data set choice" -returnIndices 0 \
                -itemList [eval os editstring 100Z/%/.L3:FS1././%/.H//%/.L// $fileList]]
    return $item
}

proc ReviewMeasurement {args} {
    set directory ""
    if {[APSStrictParseArguments {directory}]} {
        return -code error "ReviewMeasurement: parameter error"
    }
    set rootname [ChooseMeasurement -directory $directory]
    if ![string length $rootname] {
        return 
    }
    APSProcessLinacFlagDispersionMeasurement -rootname [file rootname $rootname] \
      -display 1 
}

proc ChooseRefLattice {} {
    global OAGGlobal
    set latticeList [lsort [glob -nocomplain \
                              $OAGGlobal(LinacLatticesDirectory)/L1O_L3FS5/2001-1219/*-dZ*]]
    set chicaneList [eval os editstring 100Z/ $latticeList]
    if ![llength $latticeList] {
        return -code error "No lattice files found!"
    }
    set latticeDir [APSChooseItemFromList \
                      -name "Choose reference lattice" \
                      -itemList $chicaneList \
                      -returnList $latticeList -returnIndices 0]
    return $latticeDir
}

proc CorrectDispersion {args} {
    set directory ""
    set gain 0.5
    set beamEnergy 150
    set statusCallback APSNoOp
    if {[APSStrictParseArguments {directory beamEnergy gain statusCallback}]} {
        return -code error "CorrectDispersion: parameter error"
    }
    if ![string length [set rootname [ChooseMeasurement -directory $directory]]] {
        return 
    }
    if ![file exists $rootname.proc] {
        return -code error "Not found: $rootname.proc"
    }

    if ![string length [set refLattice [ChooseRefLattice]]] {
        return 
    }
    set latticeParentDir [file dirname $refLattice]

    setStatus "Correcting dispersion based on measurement $rootname"
    setStatus "and lattice [file tail $refLattice]."
    
    set flagList [APSGetSDDSColumn -column Flag -fileName $rootname.proc]
    set etaList  [APSGetSDDSColumn -column xCentroidSlope -fileName $rootname.proc]
    set etaSigmaList  [APSGetSDDSColumn -column xCentroidSlopeSigma -fileName $rootname.proc]

    foreach possibleFlag {FS1 FS2 FS3 FS4 FS5} {
        set $possibleFlag:eta 0
        set $possibleFlag:weight 0
    }
    foreach flag $flagList eta $etaList etaSigma $etaSigmaList {
        set $flag:eta $eta
        set $flag:weight [expr 1./$etaSigma]
    }
    foreach flag {2 3 4 5} {
        set L3FS${flag}Ratio [expr [set L3:FS${flag}:eta]/${L3:FS1:eta}]
        set L3FS${flag}Weight [expr [set L3:FS${flag}:weight]/${L3:FS1:weight}]
    }

    set tmpRoot /tmp/[APSTmpString]
    global apsCorrectDispersionElegantDone
    set apsCorrectDispersionElegantDone 0
    APSExecLog [APSUniqueName .] \
      -unixCommand "elegant $latticeParentDir/matcheta.ele \
-macro=latticeDir=$latticeParentDir,startingFile=$refLattice/transverse.param \
-macro=twissReference=$refLattice/transverse.twi,rootname=$tmpRoot \
-macro=L3FS2Weight=$L3FS2Weight,L3FS3Weight=$L3FS3Weight,L3FS4Weight=$L3FS4Weight,L3FS5Weight=$L3FS5Weight \
-macro=L3FS2Ratio=$L3FS2Ratio,L3FS3Ratio=$L3FS3Ratio,L3FS4Ratio=$L3FS4Ratio,L3FS5Ratio=$L3FS5Ratio" \
      -callback "set apsCorrectDispersionElegantDone 1" \
      -abortCallback "set apsCorrectDispersionElegantDone 2" \
      -cancelCallback "set apsCorrectDispersionElegantDone 2" \
      -width 100 -height 20
    tkwait variable apsCorrectDispersionElegantDone
    if $apsCorrectDispersionElegantDone!=1 {
        return 
    }
    exec sddsplot -parameter=Step,optimizationFunction \
      $tmpRoot.finOpt -graph=line,type=1 -mode=y=log,y=spec &

    if [catch {exec sddsprocess $refLattice/transverse.param -pipe=out \
                 -match=col,ElementName=L3:QM\[12\] -match=col,ElementParameter=K1 \
                 | sddssort -pipe -column=ElementName \
                 | sdds2stream -pipe -column=ParameterValue} nominalK1List] {
        return -code error "CorrectDispersion: $nominalK1List"
    }
    if [catch {exec sddsprocess $tmpRoot.param -pipe=out \
                 -match=col,ElementName=L3:QM\[12\] -match=col,ElementParameter=K1 \
                 | sddssort -pipe -column=ElementName \
                 | sdds2stream -pipe -column=ParameterValue} newK1List] {
        return -code error "CorrectDispersion: $newK1List"
    }
    # setStatus "nominal K1: $nominalK1List"
    # setStatus "new K1    : $newK1List"

    # calibration of quad in 1/m^2/A 
    set calFactor [expr $beamEnergy/299.79*7.730000e-02/0.0420458]
    set deltaQM1 [expr ([lindex $nominalK1List 0]-[lindex $newK1List 0])*$calFactor*$gain]
    set deltaQM2 [expr ([lindex $nominalK1List 1]-[lindex $newK1List 1])*$calFactor*$gain]
    set choice [ APSQueryToProceed -message \
                   "Predicted required delta current is $deltaQM1 for L3:QM1 and $deltaQM2 for L3:QM2.  Do you want to install/condition to this?" ]
    if {$choice} {
        if [catch {exec cavget -list=L3:QM -list=1,2 -list=:CurrentAO} startList] {
            return -code error "CorrectDispersion: $startList"
        }
        if [catch {exec cavput -list=L3:QM \
                     -list=1=[expr [lindex $startList 0]+$deltaQM1],2=[expr [lindex $startList 1]+$deltaQM2] \
                     -list=:StandardizeSUB.G
            after 1000
            exec cavput -list=L3:QM -list=1,2 -list=:StandardizeSUB.F=0
            after 1000
            exec cavput -list=L3:QM -list=1,2 -list=:StandardizeSUB.PROC=1} result] {
            return -code error "$result"
        }
        eval $statusCallback "{Conditioning L3:QM1 and L3:QM2}"
    }
}

BuildApplication

