
proc APSMpSRCollectGapFFTableInfo {args} {
    return "This procedure is for measuring and installing new lookup tables for id gap feedforward"
}

proc APSMpSRCollectGapFFTableInitDialog {frame} {
    global APSMpSRCollectGapFFTable CUSectorList IDUseFlag
    set APSMpSRCollectGapFFTable(closeInterval) 3
    set  CUdataDir /home/helios/oagData/feedForwardFiles/IDgap
    if [catch {exec sddsprocess $CUdataDir/cantingLogic.sdds -pipe=out \
                 -filter=col,TreatedAsCU,1,1 \
                 | sdds2stream -pipe -col=Sector} CUSectorList] {
        return -code error "APSSRGetIDGapInfo: $CUSectorList"
    }
    global checkButtonVariableList entryVariableList checkButtonCommandList IDDeviceLimit AllIDList lockedIDList
    if [catch {APSSRGetDeviceLimits -default 1 -initial 1 -gapVar APSMpSRCollectGapFFTable} result] {
        return -code error "APSMpSRCollectGapFFTableInitDialog: $result"
    }
    APSSRGapSetThresholds -IDList $AllIDList -thresholdVar APSMpSRCollectGapFFTable
    APSFrame .f1 -parent $frame -name "Select ID gaps for brief scanning"
    set buttonNameList [APSCheckButtonEntryFrame .idselect -parent $frame.f1.frame -orientation vertical \
                          -limitPerRow 7 -buttonList $AllIDList \
                          -variableList $checkButtonVariableList -allNone 1\
                          -entryVariableList $entryVariableList -label "Select ID gap for brief scanning." \
                          -commandList $checkButtonCommandList]
    set parent $frame.f1.frame
    APSFrameGrid .grid -parent $parent.idselect.frame.frame5 -yList {y1 y2}
    APSButton .default -parent $parent.idselect.frame.frame5.grid.y1 -text "default" -command "APSSRResetDefaultSelection -selectType default" -size small 
    APSButton .defaulta -parent $parent.idselect.frame.frame5.grid.y2 -text "default a" -command "APSSRResetDefaultSelection -selectType defaultA" -size small
    APSButton .defaultb -parent $parent.idselect.frame.frame5.grid.y2 -text "default b" -command "APSSRResetDefaultSelection -selectType defaultB"  -size small
    set lockedIDList  [APSSRGetLockedIDDevices]
    APSSRDisableLockedIDDeviceSelect -IDList $AllIDList -buttonNameList $buttonNameList -lockedIDList $lockedIDList
    
    APSFrame .par -parent $frame -label "Gap Scan Parameters"
    APSFrameGrid .grid -parent $frame.par.frame -xList {x1 x2} 
    set w1 $frame.par.frame.grid.x1
    set w2 $frame.par.frame.grid.x2
    APSLabeledEntry .max -parent $w1 -label "Maximum gap value (mm):" -width 10 \
      -textVariable APSMpSRCollectGapFFTable(maxGap) -contextHelp "Enter the maximum gap for the scan."
    set APSMpSRCollectGapFFTable(minGap) ""
    APSLabeledEntry .min -parent $w2 -label "Minimum gap value (mm):" -width 10 \
      -textVariable APSMpSRCollectGapFFTable(minGap) \
      -contextHelp "Enter the minimum gap for the scan. If not given, the device limit will be used."
    bind $w2.min.entry <Return> "APSSRSetAllMinGaps -var APSMpSRCollectGapFFTable"
    APSLabeledEntry .maxStep -parent $w1 -width 10  -label "Maximum step value (mm):" \
      -textVariable APSMpSRCollectGapFFTable(maxStep) \
      -contextHelp "Enter the maximum step for the scan."
    APSLabeledEntry .minStep -parent $w2 -width 10 -label "Minimum step value (mm):" \
      -textVariable APSMpSRCollectGapFFTable(minStep) \
      -contextHelp "Enter the minimum step for the scan.  Overrides individual gaps."
    
    APSLabeledEntry .stepInt -parent $w1 -width 10 \
      -label "Number of the same size steps:" -textVariable APSMpSRCollectGapFFTable(stepInterval) \
      -contextHelp "Enter the number of the same size steps."
    APSLabeledEntry .factor -parent $w2 -width 10 \
      -label "Factor for a step increase: " \
      -textVariable APSMpSRCollectGapFFTable(factor) \
      -contextHelp  "Enter a factor for a step increase expression."
    
    APSLabeledEntry .ptToAve -parent $w2 -width 10 \
      -label "Readings to average: " -textVariable APSMpSRCollectGapFFTable(numToAve) \
      -contextHelp "Number of readings to average at each gap value." 
    
    APSLabeledEntry .delta -parent $w1 -width 10 \
      -label "Delta to Minimum Gap (mm):" -textVariable APSMpSRCollectGapFFTable(deltaToMinGap) \
      -contextHelp "The different value between moving the gap to (close to minimum) and the device limit (minimum gap). This delta value is to prevent from moving the gap to the minimum value which may cause problems"
    bind $w1.delta.entry <Return> "APSSRUpdateMinGap -var APSMpSRCollectGapFFTable"
    APSLabeledEntry .pause -parent $w2 -width 10 \
      -label "Pause for orbit correction after gap change (s): " \
      -textVariable APSMpSRCollectGapFFTable(pause) -contextHelp \
      "Length of pause after gap change is completed to allow orbit correction to converge."
    APSLabeledEntry .interval -parent $w2  -textVariable APSMpSRCollectGapFFTable(closeInterval) \
      -label "Interval of closing gaps (seconds):" -width 10 \
      -contextHelp "Due to on-going restrictions on the SR rf systems, we need to tagger the closing of the gaps by a selectable time interval, i.e. issuing the next gap close command after T seconds of the previous one."
    
    APSRadioButtonFrame .rbf -parent $w1 -label "Reading type: " \
      -orientation horizontal -variable APSMpSRCollectGapFFTable(readingType) \
      -buttonList "ms msAve mswAve" \
      -valueList "ms msAve mswAve" -contextHelp \
      "Choose the type of BPM reading you want to use.  The names of the BPM data will be the same no matter what you choose!"
    APSRadioButtonFrame .transfer -parent $w1 \
      -label "Transfer orbit at each iteration:" \
      -variable APSMpSRCollectGapFFTable(transferOrbit) -buttonList {Yes No} -valueList {1 0} \
      -packOption "-side left" -orientation horizontal -contextHelp \
      "Transfer orbit at each iteration to remove systematic dispersion orbit."
    APSButton .reset -parent $w2 -text "Reset Mininum Gaps to Device Limits" \
      -command "APSSRGetDeviceLimits -gapVar APSMpSRCollectGapFFTable"
    APSButton .default -parent $w2 -text "Default Selection" -command "APSSRResetDefaultSelection"
    
}

#this pem is for scanning all applicable gaps
#Called by SR PEM
proc APSMpSRCollectGapFFTable {args} {
    global status APSMpSRCollectGapFFTable IDUseFlag AllIDList CUSectorList lockedIDList FixedIDList FixedGapList TogetherList
    
    set maxGap 34
    set minGap ""
    set maxStep 30
    set minStep 0.25
    set stepInterval 7
    set factor 2
    set numToAve 2
    set deltaToMinGap 0.01
    set pause 10
    set readingType msAve
    set transferOrbit 0
    set rootname IDscan
    set closeInterval 3
    APSMpStep init -promptDialog APSMpSRCollectGapFFTableInitDialog \
      -vars {maxGap minGap maxStep minStep stepInterval factor numToAve deltaToMinGap \
               pause readingType transferOrbit closeInterval}
    
    set IDList ""
    foreach ID $AllIDList {
        if $IDUseFlag($ID) {
            lappend IDList $ID
        }
    }
    
    if ![llength $IDList] {
        APSMpReturn error "APSMpSRCollectGapFFTable(1): no IDs selected for scan."
    }
    APSMpStep "$IDList selected for scan..."
    if [catch {APSSRCheckUndulatorScanType -IDList $IDList} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(2 - APSSRCheckUndulatorScanType): $result"
    }
    
    foreach par {maxGap minGap maxStep minStep stepInterval factor numToAve deltaToMinGap \
                   pause readingType transferOrbit rootname IDList FixedIDList FixedGapList TogetherList} {
        append paramString "$par=\"[join [set $par]]\" "
    }
    catch {APSLogScriptAction \
             -procedure  APSMpSRCollectGapFFTable \
             -action initialize \
             -state ok \
             -parameters $paramString \
         }
    
    global execMode 
    set oldMode $execMode
    
    exec medm -attach -x /usr/local/iocapps/adlsys/sr/id/ID_Controls.adl & 
    APSMpStep "Step 0b: start ID gap feedforward."
    #check if offset transfer is running
    #FIX THIS - I don't think this check is needed anymore for the APSU
    if {0} {
        if [catch {exec cavget -list=SR:CorrectorFFTransferRC.RUN -pend=30} result] {
            APSMpReturn error "APSMpSRCollectGapFFTable(3 - cavget  -list=SR:CorrectorFFTransferRC.RUN: $result"
        }
        if $result {
            if [catch {exec cavget -list=SR:CorrectorFFTransferRC.DESC -pend=30} description] {
                APSMpReturn error "APSMpSRCollectGapFFTable(4 - cavget -list=SR:CorrectorFFTransferRC.DESC): $description"
            }
            set desc "transferScalarstoWaveform"
            if [string compare $description $desc]!=0 {
                set result 0
            }
        }
        if !$result {
            APSAlertBox .alert -beep once \
              -errorMessage "DP offset transfer is not running, please run it first!"
            APSMpReturn ok
        }
    }

    if [catch {exec cavget -list=S:ID:GapFeedForwardRC.RUN -pend=30} running] {
        APSMpReturn error "APSMpSRCollectGapFFTable(5 - cavget -list=S:ID:GapFeedForwardRC.RUN ): $running"
    }
    if !$running {
        if [catch {APSMpIDOffsetFeedforward -action clear  } result ] {
            APSMpReturn error "APSMpSRCollectGapFFTable(6 - clean ID FF record): $result"
        }
        if [catch {APSMpIDOffsetFeedforward -action start  } result ] {
            APSMpReturn error "APSMpSRCollectGapFFTable(7 - start ID FF): $result"
        }
    }
    # set execMode Manual
    APSMpStep "Checking if orbit controllaw is running..."
    while {1} {
        #FIX THIS - I changed it from h.defaultXRDP to h.default for the APSU
        if [catch {APSCheckControllawRunning -config h.default} hRunning] {
            APSMpReturn error "APSMpSRCollectGapFFTable(8 - check h plane controllaw): $hRunning"
        }
        if [catch {APSCheckControllawRunning -config v.default} vRunning] {
            APSMpReturn error "APSMpSRCollectGapFFTable(9 - check v plane controllaw): $vRunning"
        }
        if {$hRunning && $vRunning} {
            break
        } else {
            if {!$hRunning && !$vRunning} {
                set desc "Both h and v plane controllaws not started yet"
            } elseif {!$hRunning} {
                set desc "h plane controllaw not started yet"
            } elseif {!$vRunning} {
                set desc "v plane controllaw not started yet"
            }
            set answer [APSMultipleChoice .info -modal 1 -name "orbit controllaw not running" \
                          -question "${desc}, press Check-Again to check again or abort to abort the pem." -labelList {Check-Again Abort} \
                          -returnList {Check Abort} ]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpSRCollectGapFFTable(10): Collecting SR FF table was aborted."
            }
            after 1000
        }
    }
    
    #FIX THIS - there is no realtime feedback for the APSU
    if {0} {
        APSMpStep "Step 0d:  check if realtime feedback is running..."
        if [catch {exec cavget -list=SRFB:GBL:Hor:CloseLoopBO,SRFB:GBL:Vert:CloseLoopBO -pend=30} rtfb] {
            APSMpReturn error "APSMpSRCollectGapFFTable(11- cavget -list=SRFB:GBL:Hor:CloseLoopBO,SRFB:GBL:Vert:CloseLoopBO): $rtfb"
        }
        set hRTFB [lindex $rtfb 0]
        set vRTFB [lindex $rtfb 1]
        if {$hRTFB=="?"} {
            APSMpReturn error "Unable to read SRFB:GBL:Hor:CloseLoopBO"
        }
        if {$vRTFB=="?"} {
            APSMpReturn error "Unable to read SRFB:GBL:Vert:CloseLoopBO"
        }
        if {[string compare $hRTFB "Close"]!=0 || [string compare $vRTFB "Close"]!=0} {
            APSMpStep "Step 0e: realtime feedback is not running, start it now."
            if [APSYesNoPopUp "Do you need to initialize the RTFB system before starting it?"] {
                APSSetVarAndUpdate status "Initialize RTFB system ..."
                if [catch {APSMpInitializeRTFBSystem -statusCallback "APSSetVarAndUpdate status"} result] {
                    APSMpReturn error "APSMpSRCollectGapFFTable(12 - Error in Initializing RTFB system): $result"
                }
            }
            global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz apshpFilterRampPoints apshpFilterRampInterval
            APSMpSetRTFBGlobalParameters -readonly 1
            if [catch {APSMpRTFBCloseLoops -hpFilterCutoffVert $apshpFilterCutoffVert \
                         -hpFilterCutoffHoriz $apshpFilterCutoffHoriz \
                         -hpFilterInitialVert $apshpFilterInitialVert \
                         -hpFilterInitialHoriz $apshpFilterInitialHoriz \
                         -hpFilterRampPoints $apshpFilterRampPoints \
                         -hpFilterRampInterval $apshpFilterRampInterval } result] {
                APSMpReturn error "APSMpSRCollectGapFFTable(13 - Error in close RTFB loops): $result"
            }
        }
    }

    if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30} current] {
        APSMpReturn error "APSMpSRCollectGapFFTable(14: cavget -list=S-DCCT:CurrentM): $current"
    }
    if {$current<99} {
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "Check SR current" \
                      -question "SR current now is $current mA, less than 99mA.\n\n Would you like to continue or abort the pem." -labelList {Continue Abort} \
                      -returnList {Continue Abort} ]
        if {$answer=="Abort"} {
            APSMpReturn error "APSMpSRCollectGapFFTable(15): Collecting SR FF table was aborted due to SR current ($current) was too low."
        }
    }
    
    APSMpStep "Step 2: tranfer rf- and BMx- bpm Setpoint += ErrorCC ..."
    if [catch {APSSRTransferBPMSetpoint -plane both} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(16 - transfer BPM setpoint failed): $result"
    }
    APSMpStep "Step 3: SR save after setpoint transfer."
    set scrDir /home/helios/oagData/SCR/snapshots/SR
    
    if [catch {APSSaveMachine -machine SR \
                 -description "After setpoint transfer, 15mm gap"} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(17 - SR save): $result"
    }
    set SRsnapshot [lindex $result 0]
    
    set execMode $oldMode
    APSMpStep "Step 4: Install $SRsnapshot as UBOP to prevent controllaw from reinstalling old setpoints when it starts up."
    
    if [catch {APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred" \
                 -filename $SRsnapshot} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(18 - install preferred file): $result"
    }
    
    #FIX THIS - I am changing this the regular orbitcontrollaw for the APSU
    if {0} {
        APSMpStep "Step 6a: abort XRDP controllaw."
        if [catch {exec cavput -list=DP:S:OrbitControlLaw -list=X,Y -list=SDDS.ABRT=1 -pend=30} result] {
            APSMpReturn error "APSMpSRCollectGapFFTable(19 - cavput -list=DP:S:OrbitControlLaw -list=X,Y -list=SDDS.ABRT=1): $result"
        }
    } else {
        APSMpStep "Step 6a: abort orbit controllaw."
        if [catch {exec cavput -list=S:OrbitControlLaw -list=X,Y -list=RC.ABRT=1 -pend=30} result] {
            APSMpReturn error "APSMpSRCollectGapFFTable(19 - cavput -list=S:OrbitControlLaw -list=X,Y -list=RC.ABRT=1): $result"
        }
    }
    APSMpStep "Step 6b: abort gap feedforward."
    
    if [catch {APSMpIDOffsetFeedforward -action stop } result ] {
        APSMpReturn error "APSMpSRCollectGapFFTable(20 - stop ID FF): $result"
    }
    APSMpStep "Step 6c: Load idxbpm position gains *ID*GainAO from SBPMs SCR \"ID xbpm position gain reference\" file"
    set tmpFile /tmp/[APSTmpString].gainAO
    # APSAddToTempFileList -ID gapFFpem -fileList $tmpFile
    #FIX THIS - I don't know what the PV names will be for the APSU
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/SBPMs/SBPMs-IDXrayGainReference.gz \
                 -match=col,ControlName=*ID*GainAO $tmpFile} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(21 - sddsprocess): $result"
    }
    if [catch {exec sddscasr -restore $tmpFile -pendIO=120} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(22 - sddscasr restore gainAO): $result"
    }
    # set execMode Manual
    #APSMpStep "Step 7: start default (both plane); press continue when both plan default OC started."
    APSInfoWindow .info -name "Start h.default and v.default controllaw" -modal 1 \
      -infoMessage "Start default (use h.default and v.default) controllaws\n from SR orbit correction in both plans.\n\n press ok when it is done"
    set execMode $oldMode
    APSMpStep "Checking if default controllaw started..."
    while {1} {
        if [catch {APSCheckControllawRunning -config h.default} hRunning] {
            APSMpReturn error "APSMpSRCollectGapFFTable(23 - check h plane controllaw): $hRunning"
        }
        if [catch {APSCheckControllawRunning -config v.default} vRunning] {
            APSMpReturn error "APSMpSRCollectGapFFTable(24 - check v plane controllaw): $vRunning"
        }
        if {$hRunning && $vRunning} {
            break
        } else {
            if {!$hRunning && !$vRunning} {
                set desc "Both h and v plane default controllaw not started yet"
            } elseif {!$hRunning} {
                set desc "h plane default controllaw not started yet"
            } elseif {!$vRunning} {
                set desc "v plane default controllaw not started yet"
            }
            set answer [APSMultipleChoice .info -modal 1 -name "orbit controllaw not running" \
                          -question "${desc}, pless Check-Again to check again or abort to abort the pem." -labelList {Check-Again Abort} \
                          -returnList {Check Abort} ]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpSRCollectGapFFTable(25): Collecting SR FF table was aborted."
            }
            after 1000
        }
    }
    if [lsearch -exact $$IDList S35ID:DSID]>=0 {
        APSMpStep "Step 8a -- close ID35 shutter."
        if [catch {APSCloseID35Shutter} result] {
            APSMpReturn error "APSMpSRCollectGapFFTable(25): Error in closing ID35 shutter: $result."
        }
    }
    APSMpStep "Step 8 - 13: Scan and fit brief gap data .."
    
    if [catch {APSMpSRGapBriefScan -openOtherGaps 1 -lockedIDList $lockedIDList \
                 -fixedIDList $FixedIDList -fixedGapList $FixedGapList -togetherList $TogetherList \
                 -IDList $IDList -rootname $rootname \
                 -numToAve $numToAve -pause $pause -closeInterval $closeInterval } result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(26 - APSMpSRGapBriefScan): $result"
    }
    
    
    set execMode $oldMode
    APSMpStep "Step 9: Save SRXrayBPM SCR and install as the new UBOP..."
    
    if [catch {APSSaveMachine -machine SRXrayBPM \
                 -description "New idxbpm blade offsets and rates."} snapshot1] {
        APSMpReturn error "APSMpSRCollectGapFFTable(27 - SR Save): $snapshot1"
    }
    set newSnapshot [lindex $snapshot1 0]
    APSMpStep "Install new UBOP." 
    if [catch {APSSCRInstallPreferredFile -system SRXrayBPM -choice "User beam operator preferred" \
                 -filename $newSnapshot} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(28 - install preferred file): $result"
    }
    APSMpStep "step 10: scan full gap data and prepare FF table..."
    set minGapList ""
    foreach ID $IDList {
        lappend minGapList $APSMpSRCollectGapFFTable($ID.minGap)
    }
    APSMpStep "Start full gap scan: $IDList  $minGapList"
    if [catch {APSMpSRGapFullScan -fullScan 0  \
                 -closeInterval $closeInterval \
                 -gapVar APSMpSRCollectGapFFTable -rootname $rootname \
                 -IDList $IDList -minGapList $minGapList \
                 -numToAve $numToAve \
                 -pause $pause \
                 -maxGap $maxGap \
                 -transferOrbit $transferOrbit \
                 -readingType $readingType \
                 -maxStep $maxStep \
                 -minStep $minStep \
                 -stepInterval $stepInterval \
                 -deltaToMinGap $deltaToMinGap \
                 -fixedIDList $FixedIDList \
                 -fixedGapList $FixedGapList \
                 -togetherList $TogetherList \
                 -factor $factor \
             } result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(29 - APSMpSRGapFullScan): $result."
    }
    APSMpStep "step 11: SR save after full gap scan."
    if [catch {APSSaveMachine -machine SR \
                 -description "After gap scan."} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(30 - SR save): $result"
    }
    set SRsnapshot [lindex $result 0]
    
    APSMpStep "Step 11: Install $SRsnapshot as UBOP to prevent controllaw from reinstalling old setpoints when it starts up."
    
    if [catch {APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred" \
                 -filename $SRsnapshot} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(31 - install preferred file): $result"
    }
    APSAlertBox .ok -type done -errorMessage "New UBOP was installed after Gap FF collecting done." -name done
    APSAlertBox .ok -type done -errorMessage "Gap FF collecting done." -name done
    APSMpReturn ok
}

#Called by APSMpSRCollectGapFFTable
proc APSSRTransferBPMSetpoint {args} {
    set plane both
    APSStrictParseArguments {plane}

    switch $plane {
        x -
        h {
            set planeList H
            set coordList x
        }
        y -
        v {
            set planeList V
            set coordList y
        }
        both {
            set planeList {H V}
            set coordList {x y}
        }
    }
    set statusFile /home/helios/oagData/sr/BPMStatus/config.sdds
    set putcomm ""
    foreach plane $planeList coord $coordList {
        if [catch {exec sddsprocess $statusFile -pipe=out \
                     -filter=col,Nonexistent$plane,0,0 \
                     "-match=col,DeviceName=*ID*,!" \
                     "-match=col,DeviceName=*BM*,!" \
                     | sdds2stream -pipe -col=DeviceName } pvList] {
            return -code error $pvList
        }
        if [catch {exec cavget -list=[join $pvList ,] -list=:${coord}:ErrorM -pend=120} valList] {
            return -code error $result
        }
        foreach pv $pvList val $valList {
            lappend putcomm ${pv}:${coord}:SetpointM=$val
        }
    } 
    if [catch {exec cavput -list=[join $putcomm ,] -deltaMode -pend=120} result] {
        return -code error $result
    }
}

#Called by APSMpSRCollectGapFFTable and various Tcl/Tk scripts
proc APSCheckControllawRunning {args} {
    set config ""
    APSStrictParseArguments {config}
    
    if [regexp {h.} $config] {
        set plane h
        set coord X
    } elseif [regexp {v.} $config] {
        set plane v
        set coord Y
    } else {
        return -code error "APSCheckControllawRunning: invalid config - $config provided."
    }
    set controlPV S:OrbitControlLaw${coord}RC
    if [catch {exec cavget -list=$controlPV.RUN -pend=30} running] {
        return -code error "APSCheckControllawRunning: $running"
    }
    if {$running=="?"} {
        return -code error "APSCheckControllawRunning: can not read value of $controlPV"
    }
    if {!$running} {
        return 0
    }
    return 1
}

proc APSMpSRSingleGapScanInitDialog {frame} {
    global APSMpSRSingleGapScan CUSectorList IDUseFlag 
    
    set APSMpSRSingleGapScan(closeInterval) 3
    set  CUdataDir /home/helios/oagData/feedForwardFiles/IDgap
    if [catch {exec sddsprocess $CUdataDir/cantingLogic.sdds -pipe=out \
                 -filter=col,TreatedAsCU,1,1 \
                 | sdds2stream -pipe -col=Sector} CUSectorList] {
        return -code error "APSSRGetIDGapInfo: $CUSectorList"
    }
    global checkButtonVariableList entryVariableList checkButtonCommandList IDDeviceLimit AllIDList lockedIDList
    if [catch {APSSRGetDeviceLimits -default 0 -initial 1 -gapVar APSMpSRSingleGapScan} result] {
        return -code error "APSMpSRSingleGapScapInitDialog: $result"
    }
    APSSRGapSetThresholds -IDList $AllIDList -thresholdVar APSMpSRSingleGapScan
    APSFrame .f1 -parent $frame -name "Select ID gaps for scanning"
    set buttonNameList [APSCheckButtonEntryFrame .idselect -parent $frame.f1.frame -orientation vertical \
                          -limitPerRow 7 -buttonList $AllIDList -variableList $checkButtonVariableList -allNone 1\
                          -entryVariableList $entryVariableList -label "Select ID gap for scanning." \
                          -commandList $checkButtonCommandList]
    set parent $frame.f1.frame
    APSFrameGrid .grid -parent $parent.idselect.frame.frame5 -yList {y1 y2}
    APSButton .default -parent $parent.idselect.frame.frame5.grid.y1 -text "default" -command "APSSRResetDefaultSelection -selectType default" -size small 
    APSButton .defaulta -parent $parent.idselect.frame.frame5.grid.y2 -text "default a" -command "APSSRResetDefaultSelection -selectType defaultA" -size small
    APSButton .defaultb -parent $parent.idselect.frame.frame5.grid.y2 -text "default b" -command "APSSRResetDefaultSelection -selectType defaultB"  -size small
    set lockedIDList  [APSSRGetLockedIDDevices]
    APSSRDisableLockedIDDeviceSelect -IDList $AllIDList -buttonNameList $buttonNameList -lockedIDList $lockedIDList
    
    APSFrame .par -parent $frame -label "Gap Scan Parameters"
    APSFrameGrid .grid -parent $frame.par.frame -xList {x1 x2} 
    set w1 $frame.par.frame.grid.x1
    set w2 $frame.par.frame.grid.x2
    APSLabeledEntry .max -parent $w1 -label "Maximum gap value (mm):" -width 10 \
      -textVariable APSMpSRSingleGapScan(maxGap) -contextHelp "Enter the maximum gap for the scan."
    set APSMpSRSingleGapScan(minGap) ""
    APSLabeledEntry .min -parent $w2 -label "Minimum gap value (mm):" -width 10 \
      -textVariable APSMpSRSingleGapScan(minGap) \
      -contextHelp "Enter the minimum gap for the scan. If not given, the device limit will be used."
    bind $w2.min.entry <Return> "APSSRSetAllMinGaps -var APSMpSRSingleGapScan"
    APSLabeledEntry .maxStep -parent $w1 -width 10  -label "Maximum step value (mm):" \
      -textVariable APSMpSRSingleGapScan(maxStep) \
      -contextHelp "Enter the maximum step for the scan."
    APSLabeledEntry .minStep -parent $w2 -width 10 -label "Minimum step value (mm):" \
      -textVariable APSMpSRSingleGapScan(minStep) \
      -contextHelp "Enter the minimum step for the scan.  Overrides individual gaps."
    
    APSLabeledEntry .stepInt -parent $w1 -width 10 \
      -label "Number of the same size steps:" -textVariable APSMpSRSingleGapScan(stepInterval) \
      -contextHelp "Enter the number of the same size steps."
    APSLabeledEntry .factor -parent $w2 -width 10 \
      -label "Factor for a step increase: " \
      -textVariable APSMpSRSingleGapScan(factor) \
      -contextHelp  "Enter a factor for a step increase expression."
    
    APSLabeledEntry .ptToAve -parent $w2 -width 10 \
      -label "Readings to average: " -textVariable APSMpSRSingleGapScan(numToAve) \
      -contextHelp "Number of readings to average at each gap value." 
    
    APSLabeledEntry .delta -parent $w1 -width 10 \
      -label "Delta to Minimum Gap (mm):" -textVariable APSMpSRSingleGapScan(deltaToMinGap) \
      -contextHelp "The different value between moving the gap to (close to minimum) and the device limit (minimum gap). This delta value is to prevent from moving the gap to the minimum value which may cause problems"
    bind $w1.delta.entry <Return> "APSSRUpdateMinGap -var APSMpSRSingleGapScan"
    APSLabeledEntry .pause -parent $w2 -width 10 \
      -label "Pause for orbit correction after gap change (s): " \
      -textVariable APSMpSRSingleGapScan(pause) -contextHelp \
      "Length of pause after gap change is completed to allow orbit correction to converge."
    APSLabeledEntry .interval -parent $w2 -textVariable APSMpSRSingleGapScan(closeInterval) \
      -label "Interval of closing gaps (seconds):" -width 20 \
      -contextHelp "Due to on-going restrictions on the SR rf systems, we need to tagger the closing of the gaps by a selectable time interval, i.e. issuing the next gap close command after T seconds of the previous one."
    
    APSRadioButtonFrame .rbf -parent $w1 -label "Reading type: " \
      -orientation horizontal -variable APSMpSRSingleGapScan(readingType) \
      -buttonList "ms msAve mswAve" \
      -valueList "ms msAve mswAve" -contextHelp \
      "Choose the type of BPM reading you want to use.  The names of the BPM data will be the same no matter what you choose!"
    APSRadioButtonFrame .transfer -parent $w1 \
      -label "Transfer orbit at each iteration:" \
      -variable APSMpSRSingleGapScan(transferOrbit) -buttonList {Yes No} -valueList {1 0} \
      -packOption "-side left" -orientation horizontal -contextHelp \
      "Transfer orbit at each iteration to remove systematic dispersion orbit."
    APSButton .reset -parent $w2 -text "Reset Mininum Gaps to Device Limits" \
      -command "APSSRGetDeviceLimits -gapVar APSMpSRSingleGapScan"
    
}

proc APSMpSRSingleGapScanInfo {} {
    return "This pem collects the gap FF table for one or several selected gap without affecting other gaps."
}

#this pem is for scanning one gap without affecting other gaps
#Called by SR PEM
proc APSMpSRSingleGapScan {} {
    global status APSMpSRSingleGapScan IDUseFlag AllIDList CUSectorList lockedIDList FixedIDList FixedGapList TogetherList

    set maxGap 34
    set minGap ""
    set maxStep 30
    set minStep 0.25
    set stepInterval 7
    set factor 2
    set numToAve 2
    set deltaToMinGap 0.01
    set pause 10
    #FIX THIS - Not sure if this is correct for the APSU
    set readingType msAve
    set transferOrbit 0
    set rootname IDsingle
    set closeInterval 3
    APSMpStep Init -promptDialog APSMpSRSingleGapScanInitDialog \
      -vars {maxGap minGap maxStep minStep stepInterval factor numToAve deltaToMinGap \
               pause readingType transferOrbit closeInterval}
    global execMode  
    set oldMode $execMode
    set IDList ""
    foreach ID $AllIDList {
        if $IDUseFlag($ID) {
            lappend IDList $ID
        }
    }
    if ![llength $IDList] {
        APSMpReturn error "APSMpSRSingleGapScan(1): no IDs selected for scan."
    }
    if [catch {APSSRCheckUndulatorScanType -IDList $IDList} result] {
        APSMpReturn error "APSMpSRSingleGapScan(2 - APSSRCheckUndulatorScanType): $result"
    }
    foreach par {maxGap minGap maxStep minStep stepInterval factor numToAve deltaToMinGap \
                   pause readingType transferOrbit rootname IDList FixedIDList FixedGapList TogetherList} {
        append paramString "$par=\"[join [set $par]]\" "
    }
    
    catch {APSLogScriptAction \
             -procedure  APSMpSRSingleGapScan \
             -action initialize \
             -state ok \
             -parameters $paramString \
         }
    #set status "$IDList will be scanned."
    #remove this ID from gap feedforward table with feedforward running
    #remove the corresponding x-bpms from [hv].default
    
    set deviceList ""
    set option ""
    foreach ID $IDList {
        set sector [scan $ID S%ldID]
        set ssector [format %02d $sector]
        lappend deviceList S${ssector}ID:P?
        if ![string length $option] {
            set option "-match=col,Name=S${ssector}ID*"
        } else {
            append option ",Name=S${ssector}ID*,|"
        }
    }
    APSMpStep "Save SR ..."
    if [catch {APSSaveMachine -machine SR \
                 -description "before single gap scan."} result] {
        APSMpReturn error "APSMpSRSingleGapScan(00 - SR save): $result"
    }
    set SRsnapshot0 [lindex $result 0]
    
    set oldH [file readlink /home/helios/oagData/sr/orbitControllaw/lattices/default/h.default]
    set oldV [file readlink /home/helios/oagData/sr/orbitControllaw/lattices/default/v.default]
    set planeList ""
    if [catch {exec sddsprocess /home/helios/oagData/sr/orbitControllaw/lattices/default/h.default/config \
                 -match=par,NameType=MonitorNames $option -pipe=out -nowarnings \
                 | sdds2stream -pipe -rows=bar } hremoved] {
        APSMpReturn error "APSMpSRSingleGapScan(1a:) Error checking removing device:  $hremoved"
    }
    if [catch {exec sddsprocess /home/helios/oagData/sr/orbitControllaw/lattices/default/v.default/config \
                 -match=par,NameType=MonitorNames $option -pipe=out -nowarnings \
                 | sdds2stream -pipe -rows=bar } vremoved] {
        APSMpReturn error "APSMpSRSingleGapScan(1b:) Error checking removing device:  $result"
    }
    if {$hremoved} {
        lappend planeList h
    }
    if $vremoved {
        lappend planeList v
    }
    set removedh 0
    set removedv 0
    if [llength $planeList] {
        APSMpStep "Removed $deviceList from h.default and v.default .."
        foreach plane $planeList {
            set config ${plane}.default
            set removed$plane 1
            set old${plane}Config [file readlink /home/helios/oagData/sr/orbitControllaw/lattices/default/${plane}.default]
            if [catch {APSRemoveDeviceFromDefaultConfig -config $config \
                         -deviceList $deviceList \
                         -initials "pem" \
                         -confirm 0 \
                         -controllawType dcOrbitCorrection \
                         -comment "Removed ID Xray bpms ($deviceList) from sector(s) from $config." \
                     } result] {
                APSMpReturn error "APSMpSRSingleGapScan(2a:) Error removing $deviceList from $config $result"
            }
        }
    }
    APSMpStep "Remove $IDList from ID feedback forward table."
    set oldFF [file readlink /home/helios/oagData/feedForwardFiles/IDgap/FF]
    set option ""
    set opt ""
    foreach ID $IDList {
        #for sector, to remove one gap FF, have to remove all ID01 gap FF tables,
        if ![string length $option] {
            if [regexp S01ID $ID] {
                set option "-match=par,ReadbackName=S01ID*,!"
                set opt "-match=par,ReadbackName=S01ID*"
            } else {
                set option "-match=par,ReadbackName=${ID}*,!"
                set opt "-match=par,ReadbackName=${ID}*"
            }
        } else {
            if [regexp S01ID $ID] {
                append option ",ReadbackName=S01ID*,!,&"
                append opt ",ReadbackName=S01ID*,|"
            } else {
                append option ",ReadbackName=${ID}*,!,&"
                append opt ",ReadbackName=${ID}*,|"
            }
        }
    }
    APSMpStep "$opt"
    if [catch {exec sddsprocess /home/helios/oagData/feedForwardFiles/IDgap/FF $opt -pipe=out \
                 | sdds2stream -npages=bar -pipe} removedFF] {
        APSMpReturn error "APSMpSRSingleGapScan(1c): Error checking FF table: $removedFF"
    }
    APSMpStep "Move selected gaps to 20mm..."
    if [catch {APSSRMoveIDGaps -moveTo 20 -IDList $IDList -open 0 -closeInterval 1 \
                 -fixedIDList $FixedIDList -fixedGapList $FixedGapList } moveList] {
        APSMpReturn error "APSMpSRSingleGapScan(1a): error in moving ID gaps to 20mm: $moveList"
    }
    #should wait for gaps move to the desired value
    if [catch {APSMpCheckAndWaitForIDs -deviceList $moveList -tolerance 0.1} results] {
        if {[APSPEMTKDialog .warningDialog -text "APSMpSRGapFullScan: Problem occurred while waiting ID gaps\n$results"] == 1} {
            APSMpReturn error "APSMpSRgapSingleGapScan(1c): $results"
        }
    }
    if $removedFF {
        set newFF [APSNextGenerationedName -directory  /home/helios/oagData/feedForwardFiles/IDgap -name $oldFF -newFile 1 -separator .]
        cd /home/helios/oagData/feedForwardFiles/IDgap/
        if [regexp "S01ID" $IDList] {
            #S01ID gap, the new FF should not contain any of S01ID gap table when scan either ds or us 
            if [catch {exec sddsprocess FF "-match=par,ReadbackName=S01ID*" ID01.FF -nowarnings} resykt] {
                APSMpReturn error "APSMpSRSingleGapScan(1d): Error obtaining ID01.FF: $result"
            }
        }
        if [catch {exec sddsprocess FF $newFF $option -nowarnings} result] {
            APSMpReturn error "APSMpSRSingleGapScan(1e): Error removing $IDList from FF table: $result"
        }
        exec rm FF
        exec ln -s $newFF FF
        APSMpStep "FF changed, abort and restart ID feedforward ..."
        if [catch {exec cavget -list=S:ID:GapFeedForwardRC.RUN -pend=30} running] {
            APSMpReturn error "APSMpSRSingleGapScan(2a - cavget -list=S:ID:GapFeedForwardRC.RUN ): $running"
        }
        if $running {
            if [catch {APSMpIDOffsetFeedforward -action stop} result ] {
                APSMpReturn error "APSMpSRSingleGapScan(2b - abort ID FF): $result"
            }
            if [catch {APSMpIDOffsetFeedforward -action clear} result ] {
                APSMpReturn error "APSMpSRSingleGapScan(2b - abort ID FF): $result"
            }
        }
        after 1000
        if [catch {APSMpIDOffsetFeedforward -action start} result ] {
            APSMpReturn error "APSMpSRSingleGapScan(2c - start ID FF): $result"
        }
    }
    if [catch {exec cavget -list=S:ID:GapFeedForwardRC.RUN -pend=30} running] {
        APSMpReturn error "APSMpSRSingleGapScan(2d - cavget -list=S:ID:GapFeedForwardRC.RUN ): $running"
    }
    if !$running {
        APSMpStep "Start ID feedforward..."
        if [catch {APSMpIDOffsetFeedforward -action start} result ] {
            APSMpReturn error "APSMpSRSingleGapScan(2e - start ID FF): $result"
        }
    }
    APSMpStep "Start h.default and v.default"
    
    APSInfoWindow .info -name "Start h.default and v.default controllaw" -modal 1 \
      -infoMessage "Start default (use h.default and v.default) controllaws\n from SR orbit correction in both plans.\n\n press ok when it is done"
    
    APSMpStep "Step 1: Checking if default controllaw started..."
    while {1} {
        if [catch {APSCheckControllawRunning -config h.default} hRunning] {
            APSMpReturn error "APSMpSRSingleGapScan(3 - APSCheckControllawRunning h plane): $hRunning"
        }
        if [catch {APSCheckControllawRunning -config v.default} vRunning] {
            APSMpReturn error "APSMpSRSingleGapScan(4 - APSCheckControllawRunning v plane): $vRunning"
        }
        if {$hRunning && $vRunning} {
            break
        } else {
            if {!$hRunning && !$vRunning} {
                set desc "Both h and v plane controllaw not started yet"
            } elseif {!$hRunning} {
                set desc "h plane controllaw not started yet"
            } elseif {!$vRunning} {
                set desc "v plane controllaw not started yet"
            }
            set answer [APSMultipleChoice .info -modal 1 -name "controllaw not running" \
                          -question "${desc}, pless Check-Again to check again or abort to abort the pem." -labelList {Check-Again Abort} \
                          -returnList {Check Abort} ]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpSRSingleGapScan(5): Collecting SR single FF table was aborted."
            }
            APSWaitWithUpdate -waitSeconds 1
        }
    }
    
    

    if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30} current] {
        APSMpReturn error "APSMpSRSingleGapScan(6 - cavget -list=S-DCCT:CurrentM): $current"
    }
    if {$current<99} {
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "Check SR current" \
                      -question "SR current now is $current mA, less than 99mA.\n\n Would you like to continue or abort the pem." -labelList {Continue Abort} \
                      -returnList {Continue Abort} ]
        if {$answer=="Abort"} {
            APSMpReturn error "APSMpSRSingleGapScan(7): Collecting SR FF table was aborted due to SR current ($current) was too low."
        }
    }
    if [catch {APSSaveMachine -machine SR \
                 -description "Save before single gap scan of $IDList"} result] {
        APSMpReturn error "APSMpSRSingleGapScan(9 - SCR save SR): $result"
    }
    set execMode $oldMode
    APSDisplayIDControlMedm -IDList $IDList

    if [lsearch -exact $$IDList "S35ID:DSID"]>=0 {
        APSMpStep "Step 2a -- close ID35 shutter."
        if [catch {APSCloseID35Shutter} result] {
            APSMpReturn error "APSMpSRSingleGapScan(10a): Error in closing ID35 shutter: $result."
        }
    }
    APSMpStep "Step 3: start $IDList gap brief scan." 
    
    if [catch {APSMpSRGapBriefScan -IDList $IDList -rootname $rootname -lockedIDList $lockedIDList \
                 -fixedIDList $FixedIDList -fixedGapList $FixedGapList -togetherList $TogetherList \
                 -numToAve $numToAve -pause $pause -openOtherGaps 0 -closeInterval $closeInterval \
                 -keepFFrunning 1} result] {
        APSMpReturn error "APSMpSRSingleGapScan(11 - APSMpSRGapBriefScan): $result"
    }
    
    APSMpStep "Step 4: Save SRXrayBPM SCR and install as the new UBOP..."
    
    if [catch {APSSaveMachine -machine SRXrayBPM \
                 -description "New idxbpm blade offsets and rates for $IDList."} snapshot1] {
        APSMpReturn error "APSMpSRSingleGapScan(12 - SR save): $snapshot1"
    }
    set newSnapshot [lindex $snapshot1 0]
    APSMpStep "Step 5, Install new SRXrayBPM UBOP."
    if [catch {APSSCRInstallPreferredFile -system SRXrayBPM -choice "User beam operator preferred" \
                 -filename $newSnapshot} result] {
        APSMpReturn error "APSMpSRSingleGapScan(13 - install preferred file): $result"
    }
    
    APSMpStep "Step 6: scan full gap data and prepare FF table for $IDList ..."
    
    set minGapList ""
    foreach ID $IDList {
        lappend minGapList $APSMpSRSingleGapScan($ID.minGap)
    } 
    if [catch {APSMpSRGapFullScan -fullScan 0 \
                 -keepFFrunning 1 \
                 -closeInterval $closeInterval \
                 -gapVar APSMpSRSingleGapScan -rootname $rootname \
                 -IDList $IDList -minGapList $minGapList \
                 -numToAve $numToAve \
                 -pause $pause \
                 -maxGap $maxGap \
                 -transferOrbit $transferOrbit \
                 -readingType $readingType \
                 -maxStep $maxStep \
                 -minStep $minStep \
                 -stepInterval $stepInterval \
                 -deltaToMinGap $deltaToMinGap \
                 -fixedIDList $FixedIDList \
                 -fixedGapList $FixedGapList \
                 -togetherList $TogetherList \
                 -factor $factor} result] {
        APSMpReturn error "APSMpSRSingleGapScan(14 - APSMpSRGapFullScan): $result."
    }
    if [regexp S01ID $IDList] {
        #ID01 gap scan, since all ID01 gap FF are removed, should put the non-scanned ID01 gap  back after scan
        cd  /home/helios/oagData/feedForwardFiles/IDgap
        if [regexp S01ID:DSID $IDList] {
            if [catch {exec sddsprocess ID01.FF "-match=par,ReadbackName=S01ID:DSID*,!" ID01.other } result] {
                APSMpReturn error "APSMpSRSingleGapScan(14a -- error createing ID01.other): $result"
            }
        } else {
            if [catch {exec sddsprocess ID01.FF "-match=par,ReadbackName=S01ID:USID*,!" ID01.other } result] {
                APSMpReturn error "APSMpSRSingleGapScan(14a -- error createing ID01.other): $result"
            }
        }
        set newFF [APSNextGenerationedName -directory  /home/helios/oagData/feedForwardFiles/IDgap -name $oldFF -newFile 1 -separator .]
        if [catch {exec sddscombine FF ID01.other -pipe=out \
                     | sddssort -pipe=in $newFF -par=ReadbackName } result] {
            APSMpReturn error "APSMpSRSingleGapScan(14b -- error generating newFF): $result"
        }
        exec rm FF
        exec ln -s $newFF FF
    }
    APSMpStep "Stop ID gap feedforward after single gap scan."
    if [catch {APSMpIDOffsetFeedforward -action stop  } result ] {
        APSMpReturn error "APSMpSRSignleGapSan(15 - clear ID FF record): $result"
    }
    after 1000
    if [catch {APSMpIDOffsetFeedforward -action clear  } result ] {
        APSMpReturn error "APSMpSRSignleGapSan(15 - clear ID FF record): $result"
    }
    
    APSMpStep "Step 7: re-start ID gap feedforward..."
    if [catch {APSMpIDOffsetFeedforward -action start } result ] {
        APSMpReturn error "APSMpSRSignleGapSan(16 - start ID FF): $result"
    }
    
    APSMpStep "Step 8: restoring the gaps of $IDList ..."
    set matchOpt ""
    foreach ID $IDList {
        if [string length $matchOpt] {
            append matchOpt ,ControlName=${ID}*GapSet*,|
        } else {
            set matchOpt -match=col,ControlName=${ID}*GapSet*
        }
    }
    
    set tmpFile /tmp/[APSTmpString]
    set scrDir /home/helios/oagData/SCR/snapshots/SR
    if [catch {exec sddsprocess $scrDir/$SRsnapshot0 "$matchOpt" $tmpFile.set
        exec sddsprocess $tmpFile.set $tmpFile.start -match=col,ControlName=*:GapSet* \
                 -reedit=col,ControlName,%/:GapSet/:Start/ \
                 -reprint=col,ValueString,1 } result] {
        APSMpReturn error "APSMpSRSingleGapScan(17 - sddsprocess): $result"
    }
    
    if [catch {exec sddsprocess $tmpFile.set -match=col,ControlName=S01ID:DSID:Gap* -pipe=out -nowarnings \
                 | sddsstream -pipe -col=ValueString } ID01dsGap] {
        set ID01dsGap ""
    }
    if [catch {exec sddsprocess $tmpFile.set -match=col,ControlName=S01ID:USDS:Gap* -pipe=out -nowarnings \
                 | sddsstream -pipe -col=ValueString } ID01usGap] {
        set ID01usGap ""
    }
    
    APSMpStep "Preparing for ID01 gap moving (turn off SCU1 for moving S01ID:USID, open S01ID:USID for closing S01ID:DSID..."
    if [catch {APSSRPrepareMovingID01Gaps -dsGap $ID01dsGap -usGap $ID01usGap -orbitSwitch 0} result] {
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                      -question "Error in preparing for moving ID01 gaps, $result; do you want to abort or continue still?" \
                      -returnList {Abort Continue} \
                      -labelList {Abort Continue}]
        if {$answer=="Abort"} {
            APSMpReturn error "APSMpSRSingleGapScan(18a): Error in preparing for moving ID01 gaps, $result"
        }
    }
    if [catch {exec sddsprocess $tmpFile.set -match=col,ControlName=S06ID:DSID:Gap* -pipe=out -nowarnings \
                 | sddsstream -pipe -col=ValueString } ID06dsGap] {
        set ID06dsGap ""
    }
    if [string length $ID06dsGap] {
        APSMpStep "Preparing for S06ID:DSID gap..."
        if [catch {APSSRPrepareMovingSCU0Gaps -gapList $ID06dsGap -IDList S06ID:DSID} result] {
            set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                          -question "Error in preparing for moving S06ID:DSID gaps, $result; do you want to abort or continue still?" \
                          -returnList {Abort Continue} \
                          -labelList {Abort Continue}]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpSRSingleGapScan(18b): Error in preparing for moving S06ID:DSID gaps, $result"
            }
        }
    }
    APSMpStep "Restore ID gaps..."
    if [catch {exec sddscasr -restore $tmpFile.set } result] {
        APSMpReturn error "APSMpSRSingleGapScan(18 - sddscasr -restore $tmpFile.set): $result"
    }
    after 2000
    if [catch {exec sddscasr -restore $tmpFile.start } result] {
        APSMpReturn error "APSMpSRSingleGapScan(19 - sddscasr -restore $tmPFile.start): $result"
    }
    
    APSAddToTmpFileList -ID singlescan -fileList "$tmpFile.set $tmpFile.start"
    APSAlertBox .warning -type warning -errorMessage "Please wait while moving $IDList gaps to its original values; press ok when gaps stop moving." -name warning

    APSMpStep "Step 9: do SR SCR save after single gap scan."
    if [catch {APSSaveMachine -machine SR \
                 -description "After single gap scan."} result] {
        APSMpReturn error "APSMpSRSingleGapScan(20 - SR save): $result"
    }
    set SRsnapshot [lindex $result 0]
    
    APSMpStep "Step 10: Install $SRsnapshot as UBOP to prevent controllaw from reinstalling old setpoints when it starts up."
    
    if [catch {APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred" \
                 -filename $SRsnapshot} result] {
        APSMpReturn error "APSMpSRCollectGapFFTable(31 - install preferred file): $result"
    }
    APSAlertBox .ok -type done -errorMessage "New UBOP was installed after single gap scan." -name done

    APSInfoWindow .confirm -name "Add Device" -infoMessage \
      "Start the APSAddDeviceToDefaultConfigs pem and add devices; press OK when you are done." -modal 1
    
    APSMpStep "Step 11: abort orbit controllaw and restore orbit controllaw config."
    if [catch {exec cavput -list=S:OrbitControlLaw -list=X,Y -list=SDDS.ABRT=1 -pend=20} result] {
        APSMpReturn error "APSMpSRSingleGapScan(19): Error aborting orbit correction: $result"
    }
    
    APSMpStep "Step 12: start h.default and v.default controllaw"
    APSInfoWindow .info -name "Start h.default and v.default controllaw" -modal 1 \
      -infoMessage "Start (use h.default and v.default) controllaws\n from SR orbit correction in both plans.\n\n press ok when it is done"
    
    APSAlertBox .ok -type done -errorMessage "Gap FF collecting for $IDList done." -name done
    APSMpReturn ok
}

#Called by APSMpSRSingleGapScan
proc APSDisplayIDControlMedm {args} {
    set IDList ""
    APSStrictParseArguments {IDList}

    #FIX THIS - ID used to have values like 06ds. I think we should pass the full ID name to medm
    foreach ID $IDList {
        #regsub {ID} $ID "" ID
        exec medm -attach -macro ID=$ID -x /usr/local/iocapps/adlsys/sr/id/IDControl.adl &
    }
}



proc APSMpSRCollectXrayBPMDataInfo {args} {
    return "This procedure is for measuring Xray BPM data which can be used for xbpm alignment."
}

#Not used
proc APSSelectCantedUndulator {args} {
    APSStrictParseArguments {type}
    global IDUseFlag CUSectorList AllIDList

    foreach ID $AllIDList {
        set IDUseFlag($ID) 0
    }
    foreach sector $CUSectorList {
        set IDUseFlag(ID[format %02d $sector]$type) 1
    }
}

proc APSMpSRCollectXrayBPMDataInitDialog {frame} {
    global APSMpSRCollectXrayBPMData CUSectorList IDUseFlag
    set APSMpSRCollectXrayBPMData(closeInterval) 3
    
    set  CUdataDir /home/helios/oagData/feedForwardFiles/IDgap
    if [catch {exec sddsprocess $CUdataDir/cantingLogic.sdds -pipe=out \
                 -filter=col,TreatedAsCU,1,1 \
                 | sdds2stream -pipe -col=Sector} CUSectorList] {
        return -code error "APSMpSRCollectXrayBPMDataInitDialog1: $CUSectorList"
    }
    global checkButtonVariableList entryVariableList checkButtonCommandList IDDeviceLimit AllIDList lockedIDList
    if [catch {APSSRGetDeviceLimits -default 1 -initial 1 -gapVar APSMpSRCollectXrayBPMData} result] {
        return -code error "APSMpSRCollectGapFFTableInitDialog: $result"
    }
    APSSRGapSetThresholds -IDList $AllIDList -thresholdVar APSMpSRCollectXrayBPMData
    APSFrame .f1 -parent $frame -name "Select ID gaps for brief scanning"
    set buttonNameList [APSCheckButtonEntryFrame .idselect -parent $frame.f1.frame -orientation vertical \
                          -limitPerRow 7 -buttonList $AllIDList \
                          -variableList $checkButtonVariableList -allNone 1\
                          -entryVariableList $entryVariableList -label "Select ID gap for brief scanning." \
                          -commandList $checkButtonCommandList]
    set parent $frame.f1.frame
    set parent $frame.f1.frame
    APSFrameGrid .grid -parent $parent.idselect.frame.frame5 -yList {y1 y2}
    APSButton .default -parent $parent.idselect.frame.frame5.grid.y1 -text "default" -command "APSSRResetDefaultSelection -selectType default" -size small 
    APSButton .defaulta -parent $parent.idselect.frame.frame5.grid.y1 -text "default a" -command "APSSRResetDefaultSelection -selectType defaultA" -size small
    APSButton .defaultb -parent $parent.idselect.frame.frame5.grid.y1 -text "default b" -command "APSSRResetDefaultSelection -selectType defaultB"  -size small
    APSButton .ds -parent $parent.idselect.frame.frame5.grid.y2 -text "canted ds" -size small -command "APSSelectCantedUndulator -type ds"
    APSButton .us -parent $parent.idselect.frame.frame5.grid.y2 -text "canted us" -size small -command "APSSelectCantedUndulator -type us"
    set lockedIDList  [APSSRGetLockedIDDevices]
    APSSRDisableLockedIDDeviceSelect -IDList $AllIDList -buttonNameList $buttonNameList -lockedIDList $lockedIDList
    APSFrame .par -parent $frame -label "Gap Scan Parameters"
    APSFrameGrid .grid -parent $frame.par.frame -xList {x1 x2} 
    set w1 $frame.par.frame.grid.x1
    set w2 $frame.par.frame.grid.x2
    APSLabeledEntry .max -parent $w1 -label "Maximum gap value (mm):" -width 10 \
      -textVariable APSMpSRCollectXrayBPMData(maxGap) -contextHelp "Enter the maximum gap for the scan."
    set APSMpSRCollectXrayBPMData(minGap) ""
    APSLabeledEntry .min -parent $w2 -label "Minimum gap value (mm):" -width 10 \
      -textVariable APSMpSRCollectXrayBPMData(minGap) \
      -contextHelp "Enter the minimum gap for the scan. If not given, the device limit will be used."
    bind $w2.min.entry <Return> "APSSRSetAllMinGaps -var APSMpSRCollectXrayBPMData"
    APSLabeledEntry .maxStep -parent $w1 -width 10  -label "Maximum step value (mm):" \
      -textVariable APSMpSRCollectXrayBPMData(maxStep) \
      -contextHelp "Enter the maximum step for the scan."
    APSLabeledEntry .minStep -parent $w2 -width 10 -label "Minimum step value (mm):" \
      -textVariable APSMpSRCollectXrayBPMData(minStep) \
      -contextHelp "Enter the minimum step for the scan.  Overrides individual gaps."
    
    APSLabeledEntry .stepInt -parent $w1 -width 10 \
      -label "Number of the same size steps:" -textVariable APSMpSRCollectXrayBPMData(stepInterval) \
      -contextHelp "Enter the number of the same size steps."
    APSLabeledEntry .factor -parent $w2 -width 10 \
      -label "Factor for a step increase: " \
      -textVariable APSMpSRCollectXrayBPMData(factor) \
      -contextHelp  "Enter a factor for a step increase expression."
    
    APSLabeledEntry .ptToAve -parent $w2 -width 10 \
      -label "Readings to average: " -textVariable APSMpSRCollectXrayBPMData(numToAve) \
      -contextHelp "Number of readings to average at each gap value." 
    
    APSLabeledEntry .delta -parent $w1 -width 10 \
      -label "Delta to Minimum Gap (mm):" -textVariable APSMpSRCollectXrayBPMData(deltaToMinGap) \
      -contextHelp "The different value between moving the gap to (close to minimum) and the device limit (minimum gap). This delta value is to prevent from moving the gap to the minimum value which may cause problems"
    bind $w1.delta.entry <Return> "APSSRUpdateMinGap -var APSMpSRCollectXrayBPMData"
    APSLabeledEntry .pause -parent $w2 -width 10 \
      -label "Pause for orbit correction after gap change (s): " \
      -textVariable APSMpSRCollectXrayBPMData(pause) -contextHelp \
      "Length of pause after gap change is completed to allow orbit correction to converge."
    APSLabeledEntry .interval -parent $w2  -textVariable APSMpSRCollectXrayBPMData(closeInterval) \
      -label "Interval of closing gaps (seconds):" -width 10 \
      -contextHelp "Due to on-going restrictions on the SR rf systems, we need to tagger the closing of the gaps by a selectable time interval, i.e. issuing the next gap close command after T seconds of the previous one."
    
    APSRadioButtonFrame .rbf -parent $w1 -label "Reading type: " \
      -orientation horizontal -variable APSMpSRCollectXrayBPMData(readingType) \
      -buttonList "ms msAve mswAve" \
      -valueList "ms msAve mswAve" -contextHelp \
      "Choose the type of BPM reading you want to use.  The names of the BPM data will be the same no matter what you choose!"
    APSRadioButtonFrame .transfer -parent $w1 \
      -label "Transfer orbit at each iteration:" \
      -variable APSMpSRCollectXrayBPMData(transferOrbit) -buttonList {Yes No} -valueList {1 0} \
      -packOption "-side left" -orientation horizontal -contextHelp \
      "Transfer orbit at each iteration to remove systematic dispersion orbit."
    APSButton .reset -parent $w2 -text "Reset Mininum Gaps to Device Limits" \
      -command "APSSRGetDeviceLimits -gapVar APSMpSRCollectXrayBPMData"
    #APSButton .default -parent $w2 -text "Default Selection" -command "APSSRResetDefaultSelection"
    # APSLabeledEntry .outdir -parent $frame.par.frame -width 80 -textVariable APSMpSRCollectXrayBPMData(outputDir) -label "Data output directory:"
    APSRadioButtonFrame .plane -parent $frame -label "Select plane for data collection:" -variable APSMpSRCollectXrayBPMData(plane) \
      -buttonList {x y both} -valueList {x y both} -orientation horizontal
}

#Called by SR PEM
proc APSMpSRCollectXrayBPMData {args} {
    set maxGap 34
    set minGap ""
    set maxStep 30
    set minStep 0.25
    set stepInterval 3
    set factor 2.5
    set numToAve 2
    set deltaToMinGap 0.01
    set pause 10
    set readingType msAve
    set transferOrbit 0
    set rootname XrayBPM
    set closeInterval 3
    set plane x
    set outputDir /home/helios/oagData/sr/gapScans/data/
    APSMpStep Init -promptDialog APSMpSRCollectXrayBPMDataInitDialog \
      -vars {maxGap minGap maxStep minStep stepInterval factor numToAve deltaToMinGap \
               pause readingType transferOrbit closeInterval plane}
    
    global status APSMpSRCollectXrayBPMData IDUseFlag AllIDList CUSectorList lockedIDList FixedIDList FixedGapList TogetherList
    set APSMpSRCollectXrayBPMData(XFileListFull) ""
    set APSMpSRCollectXrayBPMData(YFileListFull) ""
    set IDList ""
    foreach ID $AllIDList {
        if $IDUseFlag($ID) {
            lappend IDList $ID
        }
    }
    set APSMpSRCollectXrayBPMData(IDList) $IDList
    if ![llength $IDList] {
        APSMpReturn error "APSMpSRCollectXrayBPMData: no IDs selected for scan."
    }
    if [catch {APSSRCheckUndulatorScanType -IDList $IDList} result] {
        APSMpReturn error "APSMpSRCollectXrayBPMData15 - APSSRCheckUndulatorScanType): $result"
    }
    foreach par {maxGap minGap maxStep minStep stepInterval factor numToAve deltaToMinGap \
                   pause readingType transferOrbit rootname IDList FixedIDList FixedGapList TogetherList} {
        append paramString "$par=\"[join [set $par]]\" "
    }
    
    
    if {0} {
        catch {APSLogScriptAction \
                 -procedure  APSMpSRCollectXrayBPMData \
                 -action initialize \
                 -state ok \
                 -parameters $paramString \
             }
    }
    #initial conditions
    #24-bunch top-up, ubop conditions, i.e. user orbit, realtime feedback
    #running, 24-bunch cogging, gap feedforward running, P5 controllaw running.
    
    #24-bunch
    APSMpStep "Initial condition -- step 1: check bunch pattern -- skip, no longer needed:"
    set topupneeded 1
    if {0} {
        set tmpfile /tmp/[APSTmpString].bunchpattern
        if [catch {exec sddswget -pv=Mt:S:FillPatternWF.VAL $tmpfile} result] {
            APSMpReturn error "APSMpSRCollectXrayBPMData1: Unable to read Mt:S:FillPatternWF.VAL waveform: $result"
        }
        set referenceFile1 /home/helios/oagData/sr/bunchPatterns/bunchPatternFillRef.24singlets
        set referenceFile2 /home/helios/oagData/sr/bunchPatterns/bunchPatternFillRef.324singlets
        set topupneeded 1
        if [catch {exec sddsdiff -col=Index,Waveform $referenceFile1 $tmpfile} result] {
            set topupneeded 0
            if [catch {exec sddsdiff -col=Index,Waveform $referenceFile2 $tmpfile} result] {
                APSMpReturn error "APSMpSRCollectXrayBPMData2: current bunch pattern is not 24 or 324 singlets."
            }
        }
        APSInfoWindow .warn -name "Check 24-bunch or 324-bunch cogging" -modal 1 \
          -infoMessage "Please check if it is 24-bunch or 324 cogging."
    }
    #topup
    if $topupneeded {
        APSMpStep "Initial condition -- step 2: check topup:"
        #FIX THIS. Not sure if this PV is still valid
        if [catch {exec cavget -list=Mt:TopUpAutoEnableC -pend=10 -printErrors -num} topup] {
            APSMpReturn error "APSMpSRCollectXrayBPMData3: error reading TopUpAutoEnableC.VAL: $topup"
        }
        if !$topup {
            APSMpReturn error "APSMpSRCollectXrayBPMData4: topup is not running!"
        }
    }
    #FIX THIS - I don't think we have a realtime feedback system anymore
    if {0} {
        #realtime feadback running
        APSMpStep "Initial condition -- step 3: check if realtime feadback running"
        #FIX THIS. Not sure if this PV is still valid
        if [catch {exec cavget -list=SRFB:GBL:Hor:CloseLoopBO,SRFB:GBL:Vert:CloseLoopBO -printErrors -pend=30} rtfb] {
            APSMpReturn error "APSMpSRCollectXrayBPMData5- cavget -list=SRFB:GBL:Hor:CloseLoopBO,SRFB:GBL:Vert:CloseLoopBO): $rtfb"
        }
        set hRTFB [lindex $rtfb 0]
        set vRTFB [lindex $rtfb 1]
        if {[string compare $hRTFB "Close"]!=0 || [string compare $vRTFB "Close"]!=0} {
            APSMpStep "Initial condition -- step 3a: realtime feedback is not running, start it now."
            if [APSYesNoPopUp "Do you need to initialize the RTFB system before starting it?"] {
                APSSetVarAndUpdate status "Initialize RTFB system ..."
                if [catch {APSMpInitializeRTFBSystem -statusCallback "APSSetVarAndUpdate status"} result] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData6 - Error in Initializing RTFB system): $result"
                }
            }
            global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz apshpFilterRampPoints apshpFilterRampInterval
            APSMpSetRTFBGlobalParameters -readonly 1
            if [catch {APSMpRTFBCloseLoops -hpFilterCutoffVert $apshpFilterCutoffVert \
                         -hpFilterCutoffHoriz $apshpFilterCutoffHoriz \
                         -hpFilterInitialVert $apshpFilterInitialVert \
                         -hpFilterInitialHoriz $apshpFilterInitialHoriz \
                         -hpFilterRampPoints $apshpFilterRampPoints \
                         -hpFilterRampInterval $apshpFilterRampInterval } result] {
                APSMpReturn error "APSMpSRCollectXrayBPMData7 - Error in close RTFB loops): $result"
            }
        }
    }
    #  24-bunch cogging ?  --- how to check cogging?
    
    APSMpStep "Initial condition -- step 4: check if gap feedforward is running"
    if [catch {exec cavget -list=S:ID:GapFeedForwardRC.RUN -pend=30} running] {
        APSMpReturn error "APSMpSRCollectXrayBPMData8 - cavget -list=S:ID:GapFeedForwardRC.RUN ): $running"
    }
    if !$running {
        APSMpStep "Initial condition --step 4a: start ID gap feedforward..."
        if [catch {APSMpIDOffsetFeedforward -action clear  } result ] {
            APSMpReturn error "APSMpSRCollectXrayBPMData9 - clear ID FF record): $result"
        }
        if [catch {APSMpIDOffsetFeedforward -action start } result ] {
            APSMpReturn error "APSMpSRCollectXrayBPMData10 - start ID FF): $result"
        }
    }
    
    APSMpStep "Initial condition -- step 5: check if P5 controllaw is running"
    while {1} {
        if [catch {exec cavget -list=S:rfFreqControlLawRC.RUN -pend=10 -printErrors} p5running] {
            APSMpReturn error "APSMpSRCollectXrayBPMData11: error reading S:rfFreqControlLawRC.RUN: $p5running"
        }
        if {!$p5running} {
            set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "P5 controllaw not running" \
                          -question "P5 controllaw is not running, please start it and press continue." -labelList {Continue Abort} \
                          -returnList {Continue Abort} ]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpSRCollectXrayBPMData11: aborted due to P5 controllaw not running."
            }
        } else {
            break
        }
    }
    
    
    APSMpStep "Initial condition -- step 6, start h.default and v.default controllaw."
    APSInfoWindow .info -name "Start h.default and v.default controllaw" -modal 1 \
      -infoMessage "Start default controllaws\n from SR orbit correction in both plans.\n\n press ok when it is done"
    
    APSMpStep "Checking if default controllaw started..."
    
    while {1} {
        if [catch {APSCheckControllawRunning -config h.default} hRunning] {
            APSMpReturn error "APSMpSRCollectXrayBPMData12 - check h plane controllaw): $hRunning"
        }
        if [catch {APSCheckControllawRunning -config v.default} vRunning] {
            APSMpReturn error " APSMpSRCollectXrayBPMData13- check v plane controllaw): $vRunning"
        }
        if {$hRunning && $vRunning} {
            break
        } else {
            if {!$hRunning && !$vRunning} {
                set desc "Both h and v plane default controllaw not started yet"
            } elseif {!$hRunning} {
                set desc "h plane default controllaw not started yet"
            } elseif {!$vRunning} {
                set desc "v plane default controllaw not started yet"
            }
            set answer [APSMultipleChoice .info -modal 1 -name "orbit controllaw not running" \
                          -question "${desc}, pless Check-Again to check again or abort to abort the pem." -labelList {Check-Again Abort} \
                          -returnList {Check Abort} ]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpSRCollectXrayBPMData14: Collecting xray bpm data was aborted."
            }
            after 1000
        }
    }
    #APSMpStep "Open Gaps."
    #if [catch {APSIDOpenAllGaps} result] {
    #	APSMpReturn error "APSMpSRCollectXrayBPMData14a - OpenAllGaps): $result"
    # }
    #APSInfoWindow .info -name "Waiting for Gaps" -infoMessage "Opening gaps, click OK when all gaps stop moving." -modal 1
    
    if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30 -printErrors} current] {
        APSMpReturn error "APSMpSRCollectXrayBPMData15 - cavget -list=S-DCCT:CurrentM): $current"
    }
    if {$current<99} {
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "Check SR current" \
                      -question "SR current now is $current mA, less than 99mA.\n\n Would you like to continue or abort the pem." -labelList {Continue Abort} \
                      -returnList {Continue Abort} ]
        if {$answer=="Abort"} {
            APSMpReturn error "APSMpSRCollectXrayBPMData16: aborted due to SR current ($current) was too low."
        }
    }
    #? should open other gaps here?
    APSMpStep "Move selected gaps to 20mm..."
    set open [APSYesNoPopUp "Would you like to open other gaps while closing selected gaps to 20mm?"]
    
    if [catch {APSSRMoveIDGaps -moveTo 20 -IDList $IDList -open $open -closeInterval $closeInterval \
                 -fixedIDList $FixedIDList -fixedGapList $FixedGapList } moveList] {
        APSMpReturn error "APSMpSRCollectXrayBPMData17: error in moving ID gaps to 20mm: $moveList"
    }
    #should wait for gaps move to the desired value
    if [catch {APSMpCheckAndWaitForIDs -deviceList $moveList -tolerance 0.1} results] {
        if {[APSPEMTKDialog .warningDialog -text "APSMpSRGapFullScan: Problem occurred while waiting ID gaps\n$results"] == 1} {
            APSMpReturn error "APSMpSRGapBriefScan: $results"
        }
    }
    if {0} {
        #remove transfer orbit and install UBOP per Diag's request
        APSMpStep "Tranfer rf- and BMx- bpm Setpoint += ErrorCC ..."
        if [catch {APSSRTransferBPMSetpoint -plane both} result] {
            APSMpReturn error "APSMpSRCollectXrayBPMData18 - transfer bpm setpoint): $result"
        }
        APSMpStep "SR save after setpoint transfer."
    }
    APSMpStep "SR Save ..."
    set scrDir /home/helios/oagData/SCR/snapshots/SR
    
    if [catch {APSSaveMachine -machine SR \
                 -description "After setpoint transfer, 20mm gap"} result] {
        APSMpReturn error "APSMpSRCollectXrayBPMData19 - SCR save SR): $result"
    }
    set SRsnapshot0 [lindex $result 0]
    APSMpStep "$SRsnapshot0 was collected."
    
    if {0} {
        if [catch {APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred" \
                     -filename $SRsnapshot0 } result] {
            if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData20 - install preferred file): $result" \
                     } results] {
                APSMpReturn error "APSMpSRCollectXrayBPMData20a - install preferred file): $results"
            }
            APSMpReturn error "APSMpSRCollectXrayBPMData20 - install preferred file): $result"
        }
    }
    #bring up adts
    #FIX THIS - I suspect the suffix is wrong
    exec LaunchSROrbitADT -config glennsSquareMatrix -suffix :ErrorM -xray 0  &
    APSMpStep "Start h.glennsSquareMatrix and v.glennsSquareMatrix controllaw"
    APSInfoWindow .info -name "Start  h.glennsSquareMatrix and v.glennsSquareMatrix controllaw" -modal 1 \
      -infoMessage "Start  h.glennsSquareMatrix and v.glennsSquareMatrix controllaw"
    while {1} {
        if [catch {APSCheckControllawRunning -config h.glennsSquareMatrix} hRunning] {
            if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData21- check h plane controllaw): $hRunning" \
                     } results] {
                APSMpReturn error "APSMpSRCollectXrayBPMData21a - check h plane controllaw): $results"
            }
            APSMpReturn error "APSMpSRCollectXrayBPMData21- check h plane controllaw): $hRunning"
        }
        if [catch {APSCheckControllawRunning -config v.glennsSquareMatrix} vRunning] {
            if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData22- check v plane controllaw): $vRunning" \
                     } results] {
                APSMpReturn error "APSMpSRCollectXrayBPMData22a - check v plane controllaw): $results"
            }
            APSMpReturn error " APSMpSRCollectXrayBPMData22 - check v plane controllaw): $vRunning"
        }
        if {$hRunning && $vRunning} {
            break
        } else {
            if {!$hRunning && !$vRunning} {
                set desc "Both h and v plane gleenSquareMatrix controllaw not started yet"
            } elseif {!$hRunning} {
                set desc "h plane glennSquareMatrix controllaw not started yet"
            } elseif {!$vRunning} {
                set desc "v plane glennSquareMatrix controllaw not started yet"
            }
            set answer [APSMultipleChoice .info -modal 1 -name "glennSquarematrix controllaw not running" \
                          -question "${desc}, pless check or abort to abort the pem." -labelList {Check-Again Abort} \
                          -returnList {Check Abort} ]
            if {$answer=="Abort"} {
                if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData23- aborted"} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData23a: $results"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData23: Collecting xray bpm data was aborted."
            }
            after 1000
        }
    }
    APSMpStep "Set all idxbpm blade rates to zero"
    if [catch {APSSRSetXrayBlades -value 0} result] {
        if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData24: $result"} results] {
            APSMpReturn error "APSMpSRCollectXrayBPMData24a: $results"
        }
        APSMpReturn error "APSMpSRCollectXrayBPMData24: $result"
    }
    
    set minGapList ""
    foreach ID $IDList {
        lappend minGapList $APSMpSRCollectXrayBPMData($ID.minGap)
    }
    if {$plane=="both"} {
        set planeList {X Y} 
        set typeList {horizontal vertical}
    } else {
        set planeList [string toupper $plane]
        switch $plane {
            x {
                set typeList horizontal
            }
            y {
                set typeList vertical
            }
        }
    }
    foreach plane $planeList type $typeList {
        set APSMpSRCollectXrayBPMData(${plane}FileListFull) ""
        set fileList ""
        if {$plane=="X"} {
            set steerList {200 100 0 -100 -200}
            set valList {0.03 -0.015 -0.015 -0.015 -0.015}
            set steps [llength $valList]
        } else {
            if {[llength $planeList]==1} {
                set steerList {200 100 0 -100 -200}
                set valList {0.03 -0.015 -0.015 -0.015 -0.015}
            } else {
                set steerList {200 100 -100 -200}
                set valList {0.03 -0.015 -0.03 -0.015}
            }
            set steps [llength $valList]
        }
        for {set i 0} {$i<$steps} {incr i} {
            set steerAmp [lindex $steerList $i]
            set value [lindex $valList $i]
            while {1} {
                if [catch {APSCheckControllawRunning -config h.glennsSquareMatrix} hRunning] {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error  "APSMpSRCollectXrayBPMData12 - check h plane controllaw): $hRunning"} results] {
                        APSMpReturn error "APSMpSRCollectXrayBPMData12a - check h plane controllaw): $results"
                    }
                    APSMpReturn error "APSMpSRCollectXrayBPMData12 - check h plane controllaw): $hRunning"
                }
                if [catch {APSCheckControllawRunning -config v.glennsSquareMatrix} vRunning] {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error  "APSMpSRCollectXrayBPMData12 - check v plane controllaw): $vRunning"} results] {
                        APSMpReturn error "APSMpSRCollectXrayBPMData13a - check h plane controllaw): $results"
                    }
                    APSMpReturn error " APSMpSRCollectXrayBPMData13- check v plane controllaw): $vRunning"
                }
                if {$hRunning && $vRunning} {
                    break
                } else {
                    if {!$hRunning && !$vRunning} {
                        set desc "Both h and v plane  glennsSquareMatrix controllaw not started yet"
                    } elseif {!$hRunning} {
                        set desc "h plane glennsSquareMatrix controllaw not started yet"
                    } elseif {!$vRunning} {
                        set desc "v plane glennsSquareMatrix controllaw not started yet"
                    }
                    set answer [APSMultipleChoice .info -modal 1 -name "glennsSquareMatrix controllaw not running" \
                                  -question "$desc, pless Check-Again to check again or abort to abort the pem." -labelList {Check-Again Abort} \
                                  -returnList {Check Abort} ]
                    if {$answer=="Abort"} {
                        if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData14- aborted"} results] {
                            APSMpReturn error "APSMpSRCollectXrayBPMData14a - check v plane controllaw): $results"
                        }
                        APSMpReturn error "APSMpSRCollectXrayBPMData14: Collecting xray bpm data was aborted."
                    }
                    after 1000
                }
            }
            #check current
            while {1} {
                if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30 -printErrors} current] {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData25 - cavget -list=S-DCCT:CurrentM): $current" } results] {
                        APSMpReturn error "APSMpSRCollectXrayBPMData25a - cavget -list=S-DCCT:CurrentM): $results"
                    }
                    APSMpReturn error "APSMpSRCollectXrayBPMData25 - cavget -list=S-DCCT:CurrentM): $current"
                }
                if {$current<99} {
                    set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "Check SR current" \
                                  -question "SR current now is $current mA, less than 99mA.\n\n Would you like to continue check or abort pem." -labelList {Continue Abort} \
                                  -returnList {Continue Abort} ]
                    if {$answer=="Abort"} {
                        if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData26: aborted because current <99Amps"} results] {
                            APSMpReturn error "APSMpSRCollectXrayBPMData26a: $results"
                        }
                        APSMpReturn error "APSMpSRCollectXrayBPMData26: aborted due to SR current ($current) was too low."
                    }
                    after 1000
                } else {
                    break
                }
            }
            APSMpStep "Steering $type orbt by $steerAmp microns."
            if [catch {APSSRSteerXrayOrbit -value $value -plane $plane} result] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error  "APSMpSRCollectXrayBPMData27 (steer xray orbit): $result"} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData27a: $results"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData27: $result"
            }
            APSMpStep " Scan and fit brief gap data .."
            if {$steerAmp==0} {
                set rootname Steer0
            } else {
                set rootname Steer${plane}$steerAmp
            }
            if [catch {APSMpSRGapBriefScan -openOtherGaps 1 -lockedIDList $lockedIDList -loadRate 0 -loadOffset 1 \
                         -fixedIDList $FixedIDList -fixedGapList $FixedGapList -togetherList $TogetherList \
                         -IDList $IDList -rootname $rootname \
                         -numToAve $numToAve -pause $pause -closeInterval $closeInterval } result] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error  "APSMpSRCollectGapFFTable(26 - APSMpSRGapBriefScan): $result"} results] {
                    APSMpReturn error  "APSMpSRCollectGapFFTable(26 - APSMpSRGapBriefScan): $results"
                }
                APSMpReturn error "APSMpSRCollectGapFFTable(26 - APSMpSRGapBriefScan): $result"
            }
            set newFile [lindex [lsort [glob -nocomplain $outputDir/briefScan/${rootname}*.sdds]] end]
            while {1} {
                if [catch {APSCheckControllawRunning -config h.glennsSquareMatrix} hRunning] {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error  "APSMpSRCollectXrayBPMData12 - check h plane controllaw): $hRunning"} results] {
                        APSMpReturn error  "APSMpSRCollectGapFFTable(12 - check h plane controllaw): $results"
                    }
                    APSMpReturn error "APSMpSRCollectXrayBPMData12 - check h plane controllaw): $hRunning"
                }
                if [catch {APSCheckControllawRunning -config v.glennsSquareMatrix} vRunning] {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error  "APSMpSRCollectXrayBPMData12 - check h plane controllaw): $vRunning"} results] {
                        APSMpReturn error  "APSMpSRCollectGapFFTable(12 - check v plane controllaw): $results"
                    }
                    APSMpReturn error " APSMpSRCollectXrayBPMData13- check v plane controllaw): $vRunning"
                }
                if {$hRunning && $vRunning} {
                    break
                } else {
                    if {!$hRunning && !$vRunning} {
                        set desc "Both h and v plane  glennsSquareMatrix controllaw not started yet"
                    } elseif {!$hRunning} {
                        set desc "h plane glennsSquareMatrix controllaw not started yet"
                    } elseif {!$vRunning} {
                        set desc "v plane glennsSquareMatrix controllaw not started yet"
                    }
                    set answer [APSMultipleChoice .info -modal 1 -name "glennsSquareMatrix controllaw not running" \
                                  -question "${desc}, pless Check-Again to check again or abort to abort the pem." -labelList {Check-Again Abort} \
                                  -returnList {Check Abort} ]
                    if {$answer=="Abort"} {
                        if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData14- aborted"} results] {
                            APSMpReturn error "APSMpSRCollectXrayBPMData14a - check v plane controllaw): $results"
                        }
                        APSMpReturn error "APSMpSRCollectXrayBPMData14: Collecting xray bpm data was aborted."
                    }
                    after 1000
                }
            }
            if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30 -printErrors} current] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData28 - cavget -list=S-DCCT:CurrentM): $current"} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData28a: $result"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData28 - cavget -list=S-DCCT:CurrentM): $current"
            }
            
            if {$current<99} {
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "Check SR current" \
                              -question "SR current now is $current mA, less than 99mA.\n\n Would you like to scan again or abort pem?" -labelList {Continue Abort} \
                              -returnList {Scan-again Abort} ]
                if {$answer=="Abort"} {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData29- aborted"} results] {
                        APSMpReturn error "APSMpSRCollectXrayBPMData29a - check v plane controllaw): $results"
                    }
                    APSMpReturn error "APSMpSRCollectXrayBPMData29: aborted due to SR current ($current) was too low."
                }
                set i [expr $i-1]
                #delete just created file
                exec rm $newFile
                continue
            }
            if [catch {exec sddsprocess $newFile $newFile.1 "-reprint=par,SteerString,Steer $steerAmp microns" } result] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData29: $result"} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData29a: $results"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData29: $result"
            }
            exec mv $newFile.1 $newFile
            if [catch {APSMpSRGapFullScan -fullScan 0 \
                         -scanOnly 1 \
                         -closeInterval $closeInterval \
                         -gapVar APSMpSRCollectXrayBPMData -rootname $rootname \
                         -IDList $IDList -minGapList $minGapList \
                         -numToAve $numToAve \
                         -pause $pause \
                         -maxGap $maxGap \
                         -transferOrbit $transferOrbit \
                         -readingType $readingType \
                         -maxStep $maxStep \
                         -minStep $minStep \
                         -stepInterval $stepInterval \
                         -deltaToMinGap $deltaToMinGap \
                         -fixedIDList $FixedIDList \
                         -fixedGapList $FixedGapList \
                         -togetherList $TogetherList \
                         -factor $factor} result] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData(27 - APSMpSRGapFullScan): $result."} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData27a: $results"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData(27 - APSMpSRGapFullScan): $result."
            }
            if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30 -printErrors} current] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData28 - cavget -list=S-DCCT:CurrentM): $current"} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData28a: $results"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData28 - cavget -list=S-DCCT:CurrentM): $current"
            }
            set newFile [lindex [lsort [glob -nocomplain $outputDir/fullScan/${rootname}*.sdds]] end]
            if [catch {exec sddsprocess $newFile $newFile.1 "-reprint=par,SteerString,Steer $steerAmp microns" } result] {
                if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData29: $result"} results] {
                    APSMpReturn error "APSMpSRCollectXrayBPMData29a: $results"
                }
                APSMpReturn error "APSMpSRCollectXrayBPMData29: $result"
            }
            exec mv $newFile.1 $newFile
            if {$current<99} {
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name "Check SR current" \
                              -question "SR current now is $current mA, less than 99mA.\n\n Would you like to scan again or abort pem?" -labelList {Continue Abort} \
                              -returnList {Scan-again Abort} ]
                if {$answer=="Abort"} {
                    if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData29- aborted"} results] {
                        APSMpReturn error "APSMpSRCollectXrayBPMData29a: $results"
                    }
                    APSMpReturn error "APSMpSRCollectXrayBPMData29: aborted due to SR current ($current) was too low."
                }
                set i [expr $i-1]
                exec rm $newFile
            } else {
                lappend APSMpSRCollectXrayBPMData(${plane}FileListFull) $newFile
                lappend fileList $newFile
                catch {APSPlotXrayBPMData -fileList $fileList -plane $plane}
            }
        }
        #the orbit was steered to -0.03 mm, undo-steer
        if [catch {APSSRSteerXrayOrbit -value 0.03 -plane $plane} result] {
            if [catch {APSMpSRMoboScanErrorSafeReturn error "APSMpSRCollectXrayBPMData30 (steer xray orbit)- $result"} results] {
                APSMpReturn error "APSMpSRCollectXrayBPMData30a: $results"
            }
            APSMpReturn error "APSMpSRCollectXrayBPMData30: $result"
        }
    }
    #set oldUBOP SR2011-304-1031-083237.gz
    APSMpStep "Restore setpoints, blades rates and offsets...."
    
    if [catch { APSMpSRMoboScanErrorSafeReturn ok "finishing"} result] {
        APSMpReturn error "APSMpSRCollectXrayBPMData34: Error restore system: $result"
    }
    APSMpStep "Start gap FF."
    if [catch {APSMpIDOffsetFeedforward -action start} result] {
        APSMpReturn error "APSMpSRCollectXrayBPMData35: error restart gap FF: $result"
    }
    APSMpStep "Start h.default and v.default"
    APSInfoWindow .info -name "Start  h.default and v.default  controllaw" -modal 1 \
      -infoMessage "Retart  h.default and v.default controllaw"
    
    if [APSYesNoPopUp "Data collection is done, would you like to open all the gaps?"] {
        APSMpStep "Open gaps"
        if [catch {APSIDOpenAllGaps} result] {
            APSMpReturn error "APSMpSRCollectXrayBPMData37 - OpenAllGaps): $result"
        }
    }
    APSInfoWindow .done -name "done" -infoMessage "SR xray bpm data collection done." -modal 1
    
    APSMpReturn ok
}

#Called by SR PEM
proc APSPlotXrayBPMData {args} {
    set fileList ""
    set plane ""
    APSStrictParseArguments {fileList plane}
    global APSPlotXrayBPMData status
    if ![string length $fileList] {
        set APSPlotXrayBPMData(plane) X
        set APSPlotXrayBPMData(ok) 1
        if [winfo exist .xraydata] {
            destroy .xraydata
        }
        APSDialogBox .xraydata -name "Select Plane" \
          -okCommand "set APSPlotXrayBPMData(ok) 1" \
          -cancelCommand "set APSPlotXrayBPMData(ok) 0"
        APSRadioButtonFrame .plane -parent .xraydata.userFrame -label "Selet plane for plot:" \
          -orientation horizontal -buttonList {X Y} -valueList {X Y} \
          -variable APSPlotXrayBPMData(plane)
        tkwait window .xraydata
        if !$APSPlotXrayBPMData(ok) {
            APSMpReturn ok "Plot xray bpm data was cancelled."
        }
        set dataDir /home/helios/oagData/sr/gapScans/data/gapScanFull
        set oldDir [pwd]
        cd $dataDir
        set plane $APSPlotXrayBPMData(plane)
        set files [glob -nocomplain Steer${plane}*.sdds]
        set files0 [glob -nocomplain Steer0*.sdds]
        set files [concat $files $files0]
        if ![llength $files] {
            APSMpReturn error "No files found."
        }
        set tmpFile /tmp/[APSTmpString]
        set files1 ""
        foreach file $files {
            set len [string length $file]
            lappend files1 [string range $file [expr $len - 25] end]
            #25 is the date-string plus ".sdds" length
        }
        if [catch {exec sddsmakedataset -pipe=out -col=filename,type=string -data=[join $files ,] \
                     -col=filename1,type=string -data=[join $files1 ,] \
                     | sddssort -pipe -col=filename1,decreasing \
                     | sdds2stream -pipe -col=filename} fileList] {
            APSMpReturn error "Error in sorting filenames by date: $fileList"
        }
        set fileList [join $fileList]
        if [info exist .plotxraydata] {
            destroy .plotxraydata
        }
        set APSPlotXrayBPMData(files) ""
        APSScrolledListWindow .plotxraydata -name "Xray BPM Data" -label "" -itemList $fileList \
          -selectionVar APSPlotXrayBPMData(files)
        tkwait variable APSPlotXrayBPMData(files)
        set fileList $APSPlotXrayBPMData(files)
    }
    #FIX THIS - this may be wrong for the APSU but the files don't exist yet
    set IDList [split [string trim [lindex [split [regsub -all {\"} [exec sdds2stream -par=Description [lindex $fileList 0]] ""] :] 1]] ,]
    set option ""
    foreach ID $IDList {
        set sector [scan $ID %ld]
        #FIX THIS - this looks wrong for the APSU
        lappend option -col=ID[string toupper $ID]AverageGap,S${sector}ID:P1:msAve:[string tolower $plane]
        lappend option -col=ID[string toupper $ID]AverageGap,S${sector}ID:P2:msAve:[string tolower $plane]
    }
    set sep [llength $fileList]
    eval exec sddsplot $APSPlotXrayBPMData(files) -layout=2,1 -sep=$sep -graphic=line,vary -legend=parameter=SteerString -title=@TimeStamp -topTitle $option &
    eval exec sddsplot $APSPlotXrayBPMData(files) -sep=$sep -graphic=line,vary -legend=file -title=@TimeStamp -topTitle $option &
    
    #plot blades rate and offsets
    #puts $fileList
    set dir /home/helios/oagData/sr/gapScans/data/gapScanBrief
    cd $dir
    set breifScanFiles ""
    foreach file $fileList {
        set rootname [string range $file 0 end-11]
        set date [string range $file end-24 end-5]
        set time0 [clock scan $date -format %Y-%j-%m%d-%H%M%S]
        set files [glob ${rootname}*.sdds]
        set delta [expr 24*60*60]
        set briefFile ""
        foreach file1 $files {
            set date1 [string range $file1 end-24 end-5]
            set time1 [clock scan $date1 -format %Y-%j-%m%d-%H%M%S]
            if {[expr abs($time0-$time1)]<$delta} {
                set briefFile $file1
            }
        }
        if [string length $briefFile] {
            lappend briefFileList $briefFile
        }
    }
    if [llength $briefFileList] {
        set file0 [lindex $briefFileList 0]
        set len [llength $briefFileList]
        set gaps [exec sddsquery -col $file0 | grep GapSP]
        set option ""
        set bladeList [exec sddsquery $file0 -col | grep Corrected]
        foreach gap $gaps {
            set id [string range $gap 0 3]
            set blist ""
            foreach blade $bladeList {
                if [string match ${id}* $blade] {
                    lappend blist $blade
                }
            }
            foreach blade $blist {
                lappend option -col=$gap,$blade
            }
        }
        
        eval exec sddsplot $briefFileList -layout=2,2 -sep=$len -grap=line,vary -leg=file,edit=e26b26D -split=page -groupby=page \
          $option &
        
    }
    APSMpReturn ok
}

#Called by APSMpSRCollectXrayBPMData
proc APSSRSetXrayBlades {args} {
    set value 0
    APSStrictParseArguments {value}
    set configFile /home/helios/oagData/sr/BPMStatus/config.sdds
    set tmpFile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $configFile $tmpFile \
                 -match=col,DeviceName=S*ID* \
                 -match=col,DeviceName=S01ID:P*,! \
                 -match=col,DeviceName=S06ID:P2,! \
                 -match=col,DeviceName=S27ID:P*,! \
                 -match=col,DeviceName=S35ID:P*,! \
                 -match=col,DeviceName=S25ID:P*,! \
                 -filter=col,NonexistentH,0,0 -filter=col,NonexistentV,0,0 } result] {
        return -code error "APSSRSetXrayBlades1: $result"
    }
    set deviceList [exec sdds2stream -col=DeviceName $tmpFile]
    #FIX THIS - there is no DeviceType column in the config file
    set typeList [exec sdds2stream -col=DeviceType $tmpFile]
    set pvList ""
    foreach device $deviceList type $typeList {
        set type [lindex [split $type  " "] 1]
        for {set i 0} {$i<[string length $type]} {incr i} {
            lappend pvList ${device}:[string index $type $i]
        }
    }
    #FIX THIS - I don't know what the RateP PV is for the APSU
    if [catch {exec cavput -list=[join $pvList ,] -list=:RateP=$value -pend=30} result] {
        return -code error "APSSRSetXrayBlades2: error in setting RateP: $result"
    }
    #for 1ID, it is special, should set to either us or ds blades depending on the gap status
    #FIX THIS - I don't if this is correct for the APSU
    if [catch {exec cavget -list=ID01:USorDSselect -pend=10} ID01gap] {
        return -code error "APSSRSetXrayBlades3: error getting ID01 gap select state: $ID01gap"
    }
    #FIX THIS - I don't know what the PVs should be here for the APSU
    switch $ID01gap {
        0 {
            #us gap closed
            if [catch {exec cavput -list=S1IDus: -list=P1:,P2: -list=A,B,C,D -list=:RateP=$value -pend=30} result] {
                return -code error "APSSRSetXrayBlades4: error in setting ID01 us blades rate: $result"
            }
        }
        1 {
            if [catch {exec cavput -list=S1IDds: -list=P1:,P2: -list=A,B,C,D -list=:RateP=$value -pend=30} result] {
                return -code error "APSSRSetXrayBlades5: error in setting ID01 ds blades rate: $result"
            }
            #ds gap closed
        }
        default {
            #both gap open or closed, does not matter which one to use
            return
        }
    }
}

proc APSPlotXrayBPMDataInfo {} {
    return "plot xray bpm data collected by APSMpSRCollectXrayBPMData pem."
}

#Called by APSMpSRCollectXrayBPMData
proc APSSRSteerXrayOrbit {args} {
    set plane x
    set value 0
    APSStrictParseArguments {plane value}
    set plane [string tolower $plane]
    switch $plane {
        x {
            set config /home/helios/oagData/sr/orbitControllaw/lattices/default/h.glennsSquareMatrix/config
        }
        y {
            set config /home/helios/oagData/sr/orbitControllaw/lattices/default/v.glennsSquareMatrix/config
        }
        default {
            return -code error "invalid plane given-- $plane"
        }
    }
    set tmpFile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $config -match=par,NameType=MonitorNames -pipe=out \
                 | sddsselect -pipe=in /home/helios/oagData/sr/orbitControllaw/waveforms/nonIDbpms.sdds -match=Name -invert $tmpFile} result] {
        return -code error "APSSRSteerXrayOrbit1: $result"
    }

    if [catch {exec sddsprocess $tmpFile -match=par,NameType=MonitorNames -match=col,Name=S*A:P* -pipe=out \
                 | sdds2stream -pipe -col=Name} minusBPMs] {
        return -code error "APSSRSteerXrayOrbit2: Error in obtaining minusBPMs: $minusBPMs"
    }
    if [catch {exec sddsprocess $tmpFile -match=par,NameType=MonitorNames -match=col,Name=S*B:P* -pipe=out \
                 | sdds2stream -pipe -col=Name} plusBPMs] {
        return -code error "APSSRSteerXrayOrbit3: Error in obtaining plusBPMs: $plusBPMs"
    }
    set value1 [expr $value * -1.0]
    if [catch {exec cavput -deltaMode -list=[join $minusBPMs ,] -list=:${plane}:SetpointC=$value1 -pend=10 } result] {
        return -code error "APSSRSteerXrayOrbit4: $result"
    }
    if [catch {exec cavput -deltaMode -list=[join $plusBPMs ,] -list=:${plane}:SetpointC=$value -pend=10 } result] {
        return -code error "APSSRSteerXrayOrbit5: $result"
    }
}

#Called by APSMpSRCollectXrayBPMData
proc APSMpSRMoboScanErrorSafeReturn {code results args} {
    set scrDir /home/helios/oagData/SCR/snapshots/SR
    #APSMpStep "Reinstall original SR ubop file as SR ubop."
    #if [catch {APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred" \
      #      -filename $oldUBOP } result] {
    #    APSMpStep "Error $result"
    #    APSMpReturn error "APSMpSRMoboScanErrorSafeReturn1 - re-install old UBOP): $result"
    #}
    APSMpStep "Stop datapool"
    if [catch {exec cavput -list=S:OrbitControlLaw -list=X,Y -list=SDDS.ABRT=1 -pend=30} result] {
        APSMpReturn error "APSMpSRMoboScanErrorSafeReturn2 - cavput -list=DP:S:OrbitControlLaw -list=X,Y -list=SDDS.ABRT=1): $result"
    }
    
    APSMpStep "Load all bpm setpoints from SR UBOP, blade offsets and rates from the SRXrayBPM ubop."
    set tmpFile /tmp/[APSTmpString]
    set UBOP [file readlink /home/helios/oagData/SCR/snapshots/SRXrayBPM/SRXrayBPM-UserBeamPreferred.gz]
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/SRXrayBPM/SRXrayBPM-UserBeamPreferred.gz \
                 $tmpFile "-match=col,ControlName=*RateP,ControlName=*OffsetP,|"
        exec sddsprocess /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz \
                 "-match=col,ControlName=*SetpointAO,ControlName=*CurrentAO,|" $tmpFile.1
        exec sddscasr -restore $tmpFile -pend=60
        exec sddscasr -restore $tmpFile.1  -pend=60 \
                 -waveform=directory=$scrDir,onefile,rootname=[file root $UBOP],extension=.waveform.gz } result] {
        APSMpReturn error "APSMpSRMoboScanErrorSafeReturn5: Error in loading bpm setpoints, blade offsets and rates-- $result"
    }
    APSMpReturn $code $results
}
