
# suspend, resume, and query state of rf power controllaws for
# the linac.

proc APSLSuspendResumeRFPowerControllaws {args} {
    set klystronList [list 1 2 3 4 5 6]
    set valueList ""
    set mode read
    APSStrictParseArguments {klystronList mode valueList}
    if ![llength $klystronList] {
        return -code error "APSLSuspendResumeRFPowerControllaws: no klystrons listed"
    }
    switch [string tolower $mode] {
        suspend {
            set mode Suspend
            set valueList ""
        } 
        resume {
            set mode Resume
            set valueList ""
        }
        read {
            set mode Read
        }
        set {
            set mode Set
            if [llength $valueList]!=[llength $klystronList] {
                return -code error "APSLSuspendResumeRFPowerControllaws: value/klystron list mismatch"
            }
        }
        default {
            return -code error "APSLSuspendResumeRFPowerControllaws: invalid mode: $mode"
        }
    }
    if ![llength $klystronList] {
        return -code error "APSLSuspendResumeRFPowerControllaws: no klystrons listed"
    }
    if [catch {APSLinkToLINACPVs} result] {
        return -code error "APSLSuspendResumeRFPowerControllaws: $result"
    }
    # read the present state
    if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList -operation ReadPowerControlMode} \
          controlModeList] {
        return -code error "APSLSuspendResumeRFPowerControllaws: $controlModeList"
    }
    # return the state if read mode
    if [string compare $mode Read]==0 {
        return $controlModeList
    }
    if [string compare $mode Set]!=0 {
        # suspend or resume all
        if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                     -operation ${mode}PowerControl} \
              result] {
            return -code error "APSLSuspendResumeRFPowerControllaws: $result"
        }
    } else {
        # set values from user's list
        if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                       -valueList $valueList -operation SetPowerControlMode} \
                result] {
            return -code error "APSLSuspendResumeRFPowerControllaws: $result"
        }
        #Try again after 5 seconds because in low rate it may take that long for
        #a previous suspend command to execute before it will accept a resume command.
        after 5000
        if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                       -valueList $valueList -operation SetPowerControlMode} \
                result] {
            return -code error "APSLSuspendResumeRFPowerControllaws: $result"
        }
    }
    # return previous mode list
    return $controlModeList
}

# Reduce linac klystron output power below a specified level

proc APSLReduceKlystronOutputPower {args} {
    set klystronList [list 1 2 3 4 5 6]
    set powerLevel 1e6
    set stepSize 1
    set pause 2
    set iterationLimit 50
    APSStrictParseArguments {klystronList powerLevel stepSize iterationLimit pause}
    if ![llength $klystronList] {
        return -code error "APSLReduceKlystronOutputPower: no klystrons listed"
    }
    if $powerLevel<0 {
        return -code error "APSLReduceKlystronOutputPower: requested power level < 0"
    }

    # suspend controllaws
    if [catch {APSLinkToLINACPVs} result] {
        return -code error "APSLReduceKlystronOutputPower: $result"
    }
    if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                 -operation SuspendPowerControl} result] {
        return -code error "APSLReduceKlystronOutputPower: $result"
    }

    set deviceList $klystronList
    while {[llength $deviceList] && $iterationLimit>0} {
        # read the forward powers
        if [catch {APSDevSend -group LinacKlystron -operation ReadForwardPower \
                     -deviceList $deviceList} FPData] {
            return -code error "APSLReduceKlystronOutputPower: $FPData"
        }
        # make list of devices over the limit
        set newDeviceList ""
        foreach power $FPData device $deviceList {
            if $power<$powerLevel continue
            lappend newDeviceList $device
        }
        set deviceList $newDeviceList
        # send commands to move attenuators
        if [catch {APSDevSend -group LinacKlystron -operation MoveRFAttenuator \
                     -deviceList $deviceList -value [expr -1*abs($stepSize)]} result] {
            return -code error "APSLReduceKlystronOutputPower: $result"
        }
        incr iterationLimit -1
        APSWaitWithUpdate -waitSeconds $pause -updateInterval 1
    }
    # check for devices still over the limit
    if [catch {APSDevSend -group LinacKlystron -operation ReadForwardPower \
                 -deviceList $deviceList} FPData] {
        return -code error "APSLReduceKlystronOutputPower: $FPData"
    }
    set newDeviceList ""
    foreach power $FPData device $deviceList {
        if $power<$powerLevel continue
        lappend newDeviceList $device
    }
    return [llength $newDeviceList]
}

# ramp linac modulator PFN voltages to specified values

proc APSLRampPFNVoltage {args} {
    set klystronList [list 1 3 4 5 6]
    set rampTo 0
    set rampToList ""
    set steps 10
    set pause 30
    set checkVacuum 0
    APSStrictParseArguments {klystronList rampTo steps pause rampToList checkVacuum}

    if ![llength $klystronList] {
        return -code error "APSLRampPFNVoltage:  no klystrons listed"
    }
    if {[llength $rampToList]!=0 && [llength $rampToList]!=[llength $klystronList]} {
        return -code error "APSLRampPFNVoltage: rampToList and klystronList don't match in length"
    }
    if ![llength $rampToList] {
        set rampToList [APSReplicateItem -item $rampTo -number [llength $klystronList]]
    }
    if $steps<1 {
        return -code error "APSLRampPFNVoltage:  can't ramp in less than 1 step"
    }
    if {$checkVacuum} {
        set files ""
        foreach k $klystronList {
            set RF L$k
            lappend files /home/helios/oagData/linac/Linac_RF_Recovery/${RF}vacuum.mon
        }
        if {[catch {eval exec sdds2stream $files -col=ControlName} vacPVs]} {
            return -code error "APSLRampPFNVoltage: $vacPVs"
        }
        if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors 1} vacValuesInit]} {
            return -code error "APSLRampPFNVoltage: $vacValuesInit"
        }
    }
    if [catch {APSLinkToLINACPVs} result] {
        return -code error "APSLRampPFNVoltage: $result"
    }
    if {0} {
        # check controllaws
        if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                     -operation QueryPowerControlRunning} controllawMode] {
            return -code error "APSLRampPFNVoltage: $result"
        }
        if [lsearch -exact $controllawMode 1]!=-1 {
            #commented out temporarily
            #        return -code error "APSLRampPFNVoltage: power controllaws are running."
        }
    }
    # read the PFN levels 
    if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                 -operation SetPFNVoltage -forceRead 1} PFNVoltageList] {
        return -code error "APSLRampPFNVoltage: $PFNVoltageList"
    }
    # compute the step sizes
    foreach klystron $klystronList V $PFNVoltageList rampTo $rampToList {
        if {$rampTo < 0} {
            return -code error "APSLRampPFNVoltage: can't ramp to <0"
        }
        if {$steps > 1} {
            lappend dVList [expr ($V-$rampTo)/($steps-1.0)]
        } else {
            lappend dVList [expr ($V-$rampTo)]
        }
    }
    set useSteps 0
    foreach rampTo $rampToList V $PFNVoltageList {
        if {[expr abs($V - $rampTo)] > 2.0} {
            set useSteps 1
        }
    }
    # ramp the PFNs
    while {($steps) && ($useSteps)} {
        incr steps -1
        APSMpStep "Ramping PFN for sector $klystronList ($steps remaining)"
        set newPFNVoltageList ""
        foreach V $PFNVoltageList dV $dVList rampTo $rampToList {
            if {[set newV [expr $V-$dV]] < 0} {
                set newV 0
            }
            if {$newV > $rampTo} {
                set newV $rampTo
            }
            lappend newPFNVoltageList $newV
        }
        if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                     -operation SetPFNVoltage -valueList $newPFNVoltageList} result] {
            return -code error "APSLRampPFNVoltage: $result"
        }
        set PFNVoltageList $newPFNVoltageList
        if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                     -operation ReadPFNVoltageSetpoint} ActualPFNVoltageList1] {
            return -code error "APSLRampPFNVoltage: $ActualPFNVoltageList1"
        }
        APSWaitWithUpdate -waitSeconds $pause -updateInterval 1
        set stillChanging 1
        while {$stillChanging} {
            APSMpStep "Waiting for PFN to ramp in sector $klystronList"
            after 1000
            if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                         -operation ReadPFNVoltageSetpoint} ActualPFNVoltageList2] {
                return -code error "APSLRampPFNVoltage: $ActualPFNVoltageList"
            }
            set stillChanging 0
            foreach oldPFN $ActualPFNVoltageList1 newPFN $ActualPFNVoltageList2 \
              targetPFN $PFNVoltageList {
                  if [expr abs($newPFN-$targetPFN)<1.0] continue
                  if [expr abs($newPFN-$oldPFN)>0.1] {
                      incr stillChanging
                  }
              }
            update
            set ActualPFNVoltageList1 $ActualPFNVoltageList2
        }
        if {$checkVacuum} {
            #Check Vacuum
            set VacuumLimit 1.0e-8
             foreach k $klystronList {
                if {$k == 5} {
                    set RF L$k
                    if {[catch {APScavget -list=${RF}:KY:DC2ARF -pend=5 -printErrors 1} KlystronForwardPower]} {
                       return -code error "APSLRampPFNVoltage: $KlystronForwardPower"
                    }
                    if {($KlystronForwardPower >= 14e6) && ($KlystronForwardPower <= 18e6)} {
                        set VacuumLimit 1.0e-7
                    }
                }
            }

            set count 0
            while {1} {
                if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors 1} vacValues]} {
                    return -code error "APSLRampPFNVoltage: $vacValues"
                }
                set tooHigh 0
                set highPVs ""
                foreach pv $vacPVs val $vacValues initVal $vacValuesInit {
                    if {$val > $VacuumLimit} {
                        set delta [scan 5.0e[scan [string range [format %\#.2g $initVal] 4 end] %ld] %g]
                        if {$val >= [expr $delta + $initVal]} {
                            incr tooHigh
                            lappend highPVs $pv
                        }
                    }
                }
                if {$tooHigh} {
                    incr count
                    if {$count == 6} {
                        set answer [APSPEMTKDialog .warningDialog -text "[join $highPVs ,] vacuum is too high" -strings {Continue Recheck "Abort Procedure"}]
                        if {$answer == 0} {
                            break
                        } elseif {$answer == 1} {
                            set count 0
                            continue
                        } else {
                            return -code error "APSLRampPFNVoltage: RF recovery was aborted"
                        }
                    }
                    APSStep "Waiting for vacuum to decrease for [join $highPVs ,]"
                    APSWaitWithUpdate -waitSeconds 10
                } else {
                    break
                }
            }
        }
    }
    if [catch {APSDevSend -group LinacKlystron -deviceList $klystronList \
                 -operation SetPFNVoltage -valueList $rampToList} result] {
        return -code error "APSLRampPFNVoltage: $result"
    }
    
}


proc APSMpGenericPSArrayQuery {args} {
    set arrayName ""
    set operation ""
    set invert 0
    APSStrictParseArguments {arrayName operation invert}
    global $arrayName

    set chosenList ""
    # <operation>,DeviceList is the list of devices in a group
    # supporting an operation
    # <operation>,DeviceVariableList is the list of Tcl variables
    # associated with checkbuttons for users to select the operation for
    # a device

    foreach device [set ${arrayName}($operation,DeviceList)] \
      choiceVar [set ${arrayName}($operation,DeviceVariableList)] {
          if [set $choiceVar]!=$invert {
              lappend chosenList $device
          }
      }
    return $chosenList
}

proc APSLGenericPSArrayQuery {args} {
    set arrayName ""
    set operation ""
    set invert 0
    APSStrictParseArguments {arrayName operation invert}
    return [APSMpGenericPSArrayQuery -arrayName $arrayName -operation $operation -invert $invert]
}

proc APSMpGenericPSArraySetup {args} {
    set arrayName ""
    set turnOnList ""
    set turnOffList ""
    set conditionList ""
    set turnOnListDetailed ""
    set turnOffListDetailed ""
    set conditionListDetailed ""
    set SCRFile ""
    set cycles 4
    set system linac
    
    APSStrictParseArguments {turnOnList turnOffList conditionList arrayName \
                               SCRFile cycles turnOnListDetailed turnOffListDetailed \
                               conditionListDetailed system}
    global debugSwitch
    if $debugSwitch {
        puts "APSLGenericPSArraySetup arguments:"
        foreach item {turnOnList turnOffList conditionList arrayName SCRFile} {
            puts "$item [set $item]"
        }
        flush stdout
    }

    if [catch {APSLinkToDeviceConfigPVs -device $system} result] {
        APSMpReturn error "APSGenericPSArraySetup: $result"
    }
    if $debugSwitch {
        puts "Linked to PVs"
        flush stdout
    }

    global $arrayName

    set ${arrayName}(Filename) $SCRFile
    set ${arrayName}(ShortFilename) [file tail $SCRFile]
    set ${arrayName}(Description) ""

    # list of device groups in this array
    
    # array elements set in these loops:
    # <operation>,DeviceList
    #       list of devices that support an operation.  Also labels for checkbuttons
    # <operation>,DeviceVariableList
    #       list of variables used for checkbuttons for selecting an operation on
    #       a device
    # <operation>,<device>
    #       variable used for checkbutton for selecting an operation on a device

    foreach operation {TurnOn TurnOff StartConditioning} \
      listName {turnOnList turnOffList conditionList} \
      detailedListName {turnOnListDetailed turnOffListDetailed conditionListDetailed} {
          set defaultList [set $listName]
          if {$system == "booster"} {
              set deviceList "BTS:AH BTS:AV BTS:AQ BTS:BH BTS:BV BTS:BQ BTS:BSQ BTS:CQ BTS:DQ BTS:AB BTS:BX BTS:BB1 BTS:CB1"
          } elseif {$system == "lts"} {
              #set deviceList "L1:PC1 LTS:H LTS:V LTS:Q LTS:BM1"
              set deviceList "LTS:H LTS:V LTS:Q LTS:BM1 LTS:Alpha"
          } elseif {$system == "lea"} {
              set deviceList "LEA:H LEA:V LEA:Q LEA:BD"
          } else {
              set deviceList "L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:H L1:V L1:Q L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM L5:AM"
          }
          set ${arrayName}($operation,DeviceList) $deviceList
          set ${arrayName}($operation,DeviceChoiceList) ""
          set ${arrayName}($operation,DeviceVariableList) ""
          set ${arrayName}($operation,DetailedDeviceVariableList) ""
          foreach device $deviceList {
              set ${arrayName}($operation,$device) 0
              ## change here
              set detailedDeviceList [APSMpConvertDeviceNames -operation $operation -deviceList $device -system $system]
              foreach detailedDevice $detailedDeviceList {
                  set ${arrayName}(${operation}Detailed,$detailedDevice) 0
                  lappend ${arrayName}($operation,DetailedDeviceVariableList) ${arrayName}(${operation}Detailed,$detailedDevice)
              }
              if {[llength $defaultList] && \
                    [lsearch -exact $defaultList $device]!=-1} {
                  set ${arrayName}($operation,$device) 1
                  foreach detailedDevice $detailedDeviceList {
                      if {([llength [set $detailedListName]]==0) || ([lsearch -exact [set $detailedListName] $detailedDevice] != -1)} {
                          set ${arrayName}(${operation}Detailed,$detailedDevice) 1
                      }
                  }
              }
              # these lists used to make check button frame
              lappend ${arrayName}($operation,DeviceVariableList) ${arrayName}($operation,$device)
          }
          if {$operation == "StartConditioning"} {
              if {![info exists ${arrayName}(${operation}Info,cycles)]} {
                  set ${arrayName}(${operation}Info,cycles) $cycles
              }
          }
      }
}

proc APSLGenericPSArraySetup {args} {
    set arrayName ""
    set turnOnList ""
    set turnOffList ""
    set conditionList ""
    set turnOnListDetailed ""
    set turnOffListDetailed ""
    set conditionListDetailed ""
    set SCRFile ""
    set cycles 4
    
    APSStrictParseArguments {turnOnList turnOffList conditionList arrayName \
                               SCRFile cycles turnOnListDetailed turnOffListDetailed conditionListDetailed}
    APSMpGenericPSArraySetup -turnOnList $turnOnList \
      -turnOffList $turnOffList \
      -conditionList $conditionList \
      -arrayName $arrayName \
      -SCRFile $SCRFile \
      -cycles $cycles \
      -turnOnListDetailed $turnOnListDetailed \
      -turnOffListDetailed $turnOffListDetailed \
      -conditionListDetailed $conditionListDetailed \
      -system linac
}

proc APSMpGenericPSDialog {args} {
    set frame ""
    set turnOn 0
    set turnOff 0
    set condition 0
    set chooseSCR 0
    set arrayName ""
    set packProc ""
    set packProcBottom ""
    set system LPL
    APSStrictParseArguments {turnOn turnOff condition chooseSCR arrayName frame packProc packProcBottom system}
    
    global $arrayName
    
    if {[llength $packProc] == 1} {
        eval $packProc $frame
    }

    if {$system == "Booster"} {
        set sys "booster"
        set label "BTS PS"
    } elseif {$system == "LTS"} {
        set sys "lts"
        set label "LTS PS"
    } elseif {$system == "LEA"} {
        set sys "lea"
        set label "LEA PS"
    } else {
        set sys "linac"
        set label "Linac PS"
    }

    foreach operation {TurnOn TurnOff StartConditioning} \
      varName {turnOn turnOff condition} \
      label {"Turn on" "Turn off" "Condition"} {
          if {[set $varName]} {
              APSFrame .f$operation -parent $frame -label $label
              set w $frame.f$operation.frame
              set index 1
              set commandList ""
              set i 1
              foreach device [set ${arrayName}($operation,DeviceList)] \
                deviceVar [set ${arrayName}($operation,DeviceVariableList)] {
                    set detailedDeviceList [APSMpConvertDeviceNames -operation $operation -deviceList $device -system $sys]
                    set command ""
                    lappend command "$w.cb$index.frame.button$i configure -selectcolor \#ffffff"
                    foreach detailedDevice $detailedDeviceList {
                        lappend command "set ${arrayName}(${operation}Detailed,$detailedDevice) \[expr \[set $deviceVar\] ? 1 : 0\]"
                    }
                    lappend commandList [join $command " ; "]
                    incr i
                }
              APSCheckButtonFrame .cb$index -parent $w -orientation horizontal \
                -label $label \
                -buttonList [set ${arrayName}($operation,DeviceList)] \
                -variableList [set ${arrayName}($operation,DeviceVariableList)] \
                -commandList $commandList \
                -limitPerRow 8 \
                -contextHelp "Select power supply groups to [string tolower $label]." -allNone 1
              APSButton .simple -parent ${w}.cb${index}.frame -text Detailed -size small  -command "APSMpDetailedPSDialog -operation $operation -arrayName \"$arrayName\" -frame $w.cb$index -system $sys"
              if {$operation == "StartConditioning"} {
                  pack [frame $w.cycles$operation]
                  APSLabeledEntry .entry -parent $w.cycles$operation \
                    -label "Standardize Cycles" \
                    -textVariable ${arrayName}(${operation}Info,cycles) \
                    -type integer
                  bindtags $w.cycles$operation.entry.entry "Entry .promptDialog all $w.cycles$operation.entry.entry"
                  bind $w.cycles$operation.entry.entry <KeyPress> "
                      if \"(\[llength \[set ${arrayName}(${operation}Info,cycles)\]\]) && (\[string is integer \[set ${arrayName}(${operation}Info,cycles)\]\])\" \{
                          if \"(\[llength \[set ${arrayName}(${operation}Info,cycles)\]\]) && (\[set ${arrayName}(${operation}Info,cycles)\] <= 4) && (\[set ${arrayName}(${operation}Info,cycles)\] >= 1)\" \{ $w.cycles$operation.entry.entry configure -bg white \} else \{ $w.cycles$operation.entry.entry configure -bg yellow \}
                      \} else \{ $w.cycles$operation.entry.entry configure -bg yellow \}
                  "
                  bind $w.cycles$operation.entry.entry <ButtonRelease-2> "
                      if \"(\[llength \[set ${arrayName}(${operation}Info,cycles)\]\]) && (\[string is integer \[set ${arrayName}(${operation}Info,cycles)\]\])\" \{
                          if \"(\[llength \[set ${arrayName}(${operation}Info,cycles)\]\]) && (\[set ${arrayName}(${operation}Info,cycles)\] <= 4) && (\[set ${arrayName}(${operation}Info,cycles)\] >= 1)\" \{ $w.cycles$operation.entry.entry configure -bg white \} else \{ $w.cycles$operation.entry.entry configure -bg yellow \}
                      \} else \{ $w.cycles$operation.entry.entry configure -bg yellow \}
                  "
              }
              incr index
          }
      }
    if {$chooseSCR} {
        if {[info exists ${arrayName}(ShortFilename)]} {
            APSAddSCRDialog .scr -parent $frame -arrayName $arrayName -daysPast 7 -system $system -defaultFile [set ${arrayName}(ShortFilename)]
        } else {
            APSAddSCRDialog .scr -parent $frame -arrayName $arrayName -daysPast 7 -system $system
        }
    }
    if {[llength $packProcBottom] == 1} {
        eval $packProcBottom $frame
    }

}

proc APSLGenericPSDialog {args} {
    set frame ""
    set turnOn 0
    set turnOff 0
    set condition 0
    set chooseSCR 0
    set arrayName ""
    set packProc ""
    set packProcBottom ""
    set system LPL
    APSStrictParseArguments {turnOn turnOff condition chooseSCR arrayName frame packProc packProcBottom system}
    APSMpGenericPSDialog -turnOn $turnOn \
      -turnOff $turnOff \
      -condition $condition \
      -chooseSCR $chooseSCR \
      -arrayName $arrayName \
      -frame $frame \
      -packProc $packProc \
      -packProcBottom $packProcBottom \
      -system $system
}

proc APSMpDetailedPSDialog {args} {
    set operation ""
    set arrayName ""
    set frame ""
    set system linac
    APSStrictParseArguments {operation arrayName frame system}
    global $arrayName
    set w [APSUniqueName .diag]
    APSDialogBox $w -name "Detailed $operation Listing"
    destroy $w.buttonRow.cancel.button
    set w $w.userFrame
    set i 1
    set DetailedList ""
    foreach device [set ${arrayName}($operation,DeviceList)] \
      deviceVar [set ${arrayName}($operation,DeviceVariableList)] {
          set detailedDeviceList [APSMpConvertDeviceNames -operation $operation -deviceList $device -system $system]
          set DetailedList ""
          set CommandList ""
          set exprCommand ""
          set exprCommand2 ""
          foreach detailedDevice $detailedDeviceList {
              lappend DetailedList ${arrayName}(${operation}Detailed,$detailedDevice)
              lappend exprCommand "\[set ${arrayName}(${operation}Detailed,$detailedDevice)\]"
          }
          set exprCommand [join $exprCommand " + "]
          foreach detailedDevice $detailedDeviceList {
              lappend CommandList "set $deviceVar \[expr $exprCommand ? 1 : 0\] ; if \[expr $exprCommand\]==[llength $detailedDeviceList] {$frame.frame.button$i configure -selectcolor \#ffffff} else {$frame.frame.button$i configure -selectcolor yellow}"
          }
          APSCheckButtonFrame .cb$i -parent $w \
            -label "PS Group $device :" \
            -buttonList $detailedDeviceList \
            -variableList $DetailedList \
            -commandList $CommandList \
            -limitPerRow 10 \
            -orientation horizontal
          incr i
      }
}

proc APSLDetailedPSDialog {args} {
    set operation ""
    set arrayName ""
    set frame ""
    APSStrictParseArguments {operation arrayName frame}
    APSMpDetailedPSDialog -operation $operation -arrayName $arrayName -frame $frame -system linac
}

proc APSMpLTurnOffPSInfo {} {
    return "This procedure allows tuning off linac power supplies in groups.  You may choose from among L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:QM L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:QM L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM and L5:AM."
}

proc APSMpLTurnOffPS {args} {
    set arrayName APSMpLControlPS
    set configured 0
    set turnOffList ""
    set turnOffListDetailed ""
    APSStrictParseArguments {arrayName configured turnOffList turnOffListDetailed}
    global execMode

    if {0} {
    if {$execMode != "Automatic"} {
        if {[catch {exec cavget -list=ACIS:LBL_GUN_INH,ACIS:LA_BP_MODE,ACIS:LB_BP_MD -num -pend=20 -printErrors} acisState]} {
            APSMpReturn error "APSMpLTurnOffPS: $acisState"
        }
        if {[lindex $acisState 0] == 1} {
            if {[APSPEMTKDialog .warningDialog \
                   -text "Linac/PAR is in an acis inhibit state."] == 1} {
                APSMpReturn error "APSMpLTurnOffPS: Linac/PAR is in an acis inhibit state."
            }
        } elseif {([lindex $acisState 1] == 0) || ([lindex $acisState 2] == 0)} {
            if {[APSPEMTKDialog .warningDialog \
                   -text "Linac/PAR is in an acis trip state."] == 1} {
                APSMpReturn error "APSMpLTurnOffPS: Linac/PAR is in an acis trip state."
            }
        }
    }
    }

    global status mpInterface execMode $arrayName
    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName -turnOffList $turnOffList -turnOffListDetailed $turnOffListDetailed
    }
    if {[llength $turnOffList] == 0} {
        APSMpStep init -promptDialog \
          "APSLGenericPSDialog -turnOff 1 -arrayName $arrayName -frame "
        set turnOffList [APSLGenericPSArrayQuery -arrayName $arrayName -operation TurnOff]
    }

    set paramString ""
    foreach param {turnOffList} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction -procedure APSMpLTurnOffPS -action initialize -state ok -parameters $paramString}

    foreach mag1 "L3:AM1T" mag2 "L3:AM1" {
        if {[lsearch $turnOffList $mag1] != -1} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList $mag2} result] {
                APSMpReturn error "APSMpLTurnOffPS: $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 \
                             -group LinacPS \
                             -operation ReadCurrent \
                             -deviceList $mag2} result2] {
                    return -code error "APSMpLTurnOffPS: $result2"
                }
                APSMpStep "Setting $mag2 current to zero"
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent -deviceList $mag2 -value 0} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while setting $mag2 current to zero \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOffPS: $result"
                    }
                }
                if {[expr abs($result2)] > 1} {
                    APSWaitWithUpdate -waitSeconds 10
                }
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOff -deviceList $mag2} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning off $mag2 \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOffPS: $result"
                    }
                }
            }
        }
    }
    set turnOffList [APSMpLConvertDeviceNames -operation TurnOff -deviceList $turnOffList]
    set turnOffList [APSMpLConvertDetailedDeviceNames -operation TurnOff -deviceList $turnOffList -arrayName $arrayName]

    if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent \
                 -deviceList $turnOffList -value 0} results2] {
        APSMpReturn error "APSMpLTurnOffPS: $results2"
    }
    APSWaitWithUpdate -waitSeconds 2
    set count [APSLArrayDrivenOperationPS -arrayName $arrayName -operation TurnOff]

    set foundall 1
    foreach sector "L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM" {
        if {[lsearch $turnOffList $sector] == -1} {
            set foundall 0
            break
        }
        set detailedDeviceList [APSMpLConvertDeviceNames -operation TurnOff -deviceList $sector]
        foreach detailedDevice $detailedDeviceList {
            if {[set ${arrayName}(TurnOffDetailed,$detailedDevice)] == 0} {
                set foundall 0
                break
            }
        }
    }

    if {$foundall} {
        set foundall2 1
        foreach sector "L1:H L1:V L1:Q" {
            if {[lsearch $turnOffList $sector] == -1} {
                set foundall2 0
                break
            }
            set detailedDeviceList [APSMpLConvertDeviceNames -operation TurnOff -deviceList $sector]
            foreach detailedDevice $detailedDeviceList {
                if {[set ${arrayName}(TurnOffDetailed,$detailedDevice)] == 0} {
                    set foundall2 0
                    break
                }
            }
        }
        if {$foundall2} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList L1:RG1:RAW1} result] {
                APSMpReturn error "APSMpLTurnOffPS: $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOff -deviceList L1:RG1:RAW1} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning off L1:RG1:RAW1 \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOffPS: $result"
                    }
#                    APSMpReturn error "APSMpLTurnOffPS: $result"
                }
            }
        }
        if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList L1:RG1:RAW2} result] {
            APSMpReturn error "APSMpLTurnOffPS: $result"
        }
        if {$result} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOff -deviceList L1:RG1:RAW2} result] {
                if {[APSPEMTKDialog .warningDialog -text "Error while turning off L1:RG1:RAW2 \n$result"] == 1} {
                    APSMpReturn error "APSMpLTurnOffPS: $result"
                }
#                APSMpReturn error "APSMpLTurnOffPS: $result"
            }
        }
    }

    set foundall 1
    foreach sector "L1:Q L2:QM L4:QM L5:QM" {
        if {[lsearch $turnOffList $sector] == -1} {
            set foundall 0
            break
        }
    }
    if {$foundall} {
        if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList L1:QM:RAW} result] {
            APSMpReturn error "APSMpLTurnOffPS: $result"
        }
        if {$result} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOff -deviceList L1:QM:RAW} result] {
                if {[APSPEMTKDialog .warningDialog -text "Error while turning off L1:QM:RAW \n$result"] == 1} {
                    APSMpReturn error "APSMpLTurnOffPS: $result"
                }
#                APSMpReturn error "APSMpLTurnOffPS: $result"
            }
        }
    }
    set foundall 1
    foreach sector "L3:CHICANE" {
        if {[lsearch $turnOffList $sector] == -1} {
            set foundall 0
            break
        }
    }
    if {$foundall} {
        if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList L3:Raw} result] {
            APSMpReturn error "APSMpLTurnOffPS: $result"
        }
        if {$result} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOff -deviceList L3:Raw} result] {
                if {[APSPEMTKDialog .warningDialog -text "Error while turning off L3:Raw \n$result"] == 1} {
                    APSMpReturn error "APSMpLTurnOffPS: $result"
                }
#                APSMpReturn error "APSMpLTurnOffPS: $result"
            }
        }
    }
    APSMpReturn ok

}


proc APSMpLTurnOnPSInfo {} {
    return "This procedure allows turning on linac power supplies in groups.  You may choose from among L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:QM L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:QM L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T LS4:SC L4:QM L5:SC L5:QM and L5:AM."
}

proc APSMpLTurnOnPS {args} {
    set arrayName APSMpLControlPS
    set configured 0
    set turnOnList ""
    set turnOnListDetailed ""
    APSStrictParseArguments {arrayName configured turnOnList turnOnListDetailed}
    global execMode
    if {$execMode != "Automatic"} {
        if {[catch {exec cavget -list=LP-ACIS:Status:InhibitM,LP-ACIS:Status:AaTripM,LP-ACIS:Status:CaTripM -num -pend=5 -printErrors} acisState]} {
            APSMpReturn error "APSMpLTurnOnPS: $acisState"
        }
        if {[lindex $acisState 0] == 1} {
            if {[APSPEMTKDialog .warningDialog \
                   -text "Linac is in an acis inhibit state."] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: Linac is in an acis inhibit state."
            }
        } elseif {([lindex $acisState 1] == 1) || ([lindex $acisState 2] == 1)} {
            if {[APSPEMTKDialog .warningDialog \
                   -text "Linac is in an acis trip state."] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: Linac is in an acis trip state."
            }
        }
    }

    global status mpInterface execMode $arrayName
    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName -turnOnList $turnOnList -turnOnListDetailed $turnOnListDetailed
    }
    APSMpStep init -promptDialog \
      "APSLGenericPSDialog -turnOn 1 -arrayName $arrayName -frame "
    set turnOnList [APSLGenericPSArrayQuery -arrayName $arrayName -operation TurnOn]

    set paramString ""
    foreach param {turnOnList} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction -procedure APSMpLTurnOnPS -action initialize -state ok -parameters $paramString}

    foreach mag1 "L3:AM1T" mag2 "L3:AM1" {
        if {[lsearch $turnOnList $mag1] != -1} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOff -deviceList $mag2} result] {
                APSMpReturn error "APSMpLTurnOnPS $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOn -deviceList $mag2} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning on $mag2 \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOnPS: $result"
                    }
                }
            }
        }
    }

    foreach mag1 "L5:AM1" {
        if {[lsearch $turnOnList $mag1] != -1} {
            if {[catch {APScavput -list=L5:AM1:PS2:resetBO=1} result]} {
                APSMpReturn error "APSMpLTurnOnPS $result"
            }
            after 500
        }
    }

    foreach sector "L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:H L1:V L1:Q" {
        if {[lsearch $turnOnList $sector] != -1} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOff -deviceList L1:RG1:RAW1} result] {
                APSMpReturn error "APSMpLTurnOnPS $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOn -deviceList L1:RG1:RAW1} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning on L1:RG1:RAW1 \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOnPS: $result"
                    }
#                    APSMpReturn error "APSMpLTurnOnPS $result"
                }
            }
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOff -deviceList L1:RG1:RAW2} result] {
                APSMpReturn error "APSMpLTurnOnPS $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOn -deviceList L1:RG1:RAW2} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning on L1:RG1:RAW2 \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOnPS: $result"
                    }
#                    APSMpReturn error "APSMpLTurnOnPS $result"
                }
            }
            break
        }
    }
    foreach sector "L1:Q L2:QM L4:QM L5:QM" {
        if {[lsearch $turnOnList $sector] != -1} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOff -deviceList L1:QM:RAW} result] {
                APSMpReturn error "APSMpLTurnOnPS $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOn -deviceList L1:QM:RAW} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning on L1:QM:RAW \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOnPS: $result"
                    }
#                    APSMpReturn error "APSMpLTurnOnPS $result"
                }
                APSWaitWithUpdate -waitSeconds 5
                if {[catch {exec cavput -list=L1:QM:RAW:CurrentAO=-8.0} result]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpLTurnOnPS: Error setting L1:QM:RAW:CurrentAO=-8.0 \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOnPS: Error setting L1:QM:RAW:CurrentAO=-8.0 \n$result"
                    }
                }

            }
            break
        }
    }
    foreach sector "L3:CHICANE" {
        if {[lsearch $turnOnList $sector] != -1} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOff -deviceList L3:Raw} result] {
                APSMpReturn error "APSMpLTurnOnPS $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOn -deviceList L3:Raw} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while turning on L3:Raw \n$result"] == 1} {
                        APSMpReturn error "APSMpLTurnOnPS: $result"
                    }
#                    APSMpReturn error "APSMpLTurnOnPS $result"
                }
                APSWaitWithUpdate -waitSeconds 5
            }
            break
        }
    }
    set turnOnList [APSMpLConvertDeviceNames -operation TurnOn -deviceList $turnOnList]
    set turnOnList [APSMpLConvertDetailedDeviceNames -operation TurnOn -deviceList $turnOnList -arrayName $arrayName]
    if {[llength $turnOnList]} {
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOff \
                       -deviceList $turnOnList} result] {
            APSMpReturn error "APSMpLTurnOnPS $result"
        }
    } else {
        set result ""
    }
    set tol ""
    set tol1 ""
    set tol2 ""
    set tol3 ""
    set tol4 ""
    set tol5 ""
    set tol6 ""
    foreach item $result device $turnOnList {
        if {$item} {
            if {($device == "L3:QM1") || ($device == "L3:QM2") || ($device == "L3:QM3") || ($device == "L3:QM4") || ($device == "L3:QM5") || ($device == "L3:QM6")} {
                lappend tol1 $device
            } elseif {($device == "L3:SC2:HZ") || ($device == "L3:SC2:VL") || ($device == "L3:SC1:HZ") || ($device == "L3:SC1:VL")} {
                lappend tol2 $device
            } elseif {($device == "L3:BM1") || ($device == "L3:BM2") || ($device == "L3:BM3") || ($device == "L3:BM4")} {
                lappend tol3 $device
            } elseif {($device == "L1:H1") || ($device == "L1:V1") || ($device == "L1:H2") || ($device == "L1:V2") || ($device == "L1:H3") || ($device == "L1:V3") || ($device == "L1:H4") || ($device == "L1:V4") || ($device == "L1:Q1") || ($device == "L1:Q2") || ($device == "L1:Q3") || ($device == "L1:Q4") || ($device == "L1:Q5") || ($device == "L1:RG1:H1") || ($device == "L1:RG1:V1") || ($device == "L1:RG1:H2") || ($device == "L1:RG1:V2") || ($device == "L1:RG1:H3") || ($device == "L1:RG1:V3") || ($device == "L1:RG1:Q1") || ($device == "L1:RG1:Q2") || ($device == "L1:RG1:Q3") || ($device == "L1:RG1:Q4") || ($device == "L1:RG2:V1") || ($device == "L1:RG2:H2") || ($device == "L1:RG2:V2") || ($device == "L1:RG2:H3") || ($device == "L1:RG2:V3") || ($device == "L1:RG2:Q1") || ($device == "L1:RG2:Q2") || ($device == "L1:RG2:Q3") || ($device == "L1:RG2:Q4")} {
                lappend tol4 $device
                lappend tol $device
            } else {
                lappend tol $device
            }
        }
    }
    if {[llength $tol4]} {
        if {[catch {exec cavput -list=[join $tol4 ,] -list=:ResetSupplyC.PROC=1 -blunderAhead=silently} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol4 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        APSWaitWithUpdate -waitSeconds 5
        if {[catch {exec cavget -list=[join $tol4 ,] -list=:FaultsStatusM} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol4 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        foreach ps $tol4 v $result {
            if {$v != 255} {
                lappend tol5 $ps
            }
        }
    }
    if {[llength $tol5]} {
        if {[catch {exec cavput -list=[join $tol5 ,] -list=:ResetSupplyC.PROC=1 -blunderAhead=silently} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol5 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        APSWaitWithUpdate -waitSeconds 5
        if {[catch {exec cavget -list=[join $tol5 ,] -list=:FaultsStatusM} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol5 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        foreach ps $tol5 v $result {
            if {$v != 255} {
                lappend tol6 $ps
            }
        }
        if {[llength $tol6]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol6"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: Error while turning on $tol6"
            }
        }
    }
    if {[llength $tol]} {
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation TurnOn \
                     -deviceList $tol} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
    }
    if {[llength $tol1]} {
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation TurnOn \
                     -deviceList $tol1} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol1 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        APSWaitWithUpdate -waitSeconds 5
    }
    if {[llength $tol2]} {
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation TurnOn \
                     -deviceList $tol2} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol2 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        APSWaitWithUpdate -waitSeconds 5
    }
    if {[llength $tol3]} {
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation TurnOn \
                     -deviceList $tol3} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning on $tol3 \n$result"] == 1} {
                APSMpReturn error "APSMpLTurnOnPS: $result"
            }
        }
        APSWaitWithUpdate -waitSeconds 5
    }
    APSMpReturn ok
}

proc APSMpArrayDrivenOperationPS {args} {
    set arrayName APSMpLControlPS
    set operation TurnOn
    set system linac
    set value ""
    APSStrictParseArguments {arrayName operation system value}

    if {$system == "linac"} {
        set group "LinacPS"
    } else {
        set group "PSOps"
    }

    global debugSwitch
    set deviceList [APSMpGenericPSArrayQuery -arrayName $arrayName -operation $operation]
    APSSetVarAndUpdate status "Devices for $operation operation: $deviceList"
    set deviceList [APSMpConvertDeviceNames -operation $operation -deviceList $deviceList -system $system]
    APSSetVarAndUpdate status "Devices for $operation operation: $deviceList"
    set deviceList [APSMpConvertDetailedDeviceNames -operation $operation -deviceList $deviceList -arrayName $arrayName]
    APSSetVarAndUpdate status "Devices for $operation operation: $deviceList"
    set operationsDone 0

    if {[llength $deviceList]} {
        if {$value != ""} {
            if {[catch {APSDevSend -releaseLinks 1 -group $group -operation $operation \
                          -deviceList $deviceList -timeout 0 -value $value} result]} {
                return -code error "APSMpArrayDrivenOperationPS: $result"
            }
        } else {
            if {[catch {APSDevSend -releaseLinks 1 -group $group -operation $operation \
                          -deviceList $deviceList -timeout 0} result]} {
                return -code error "APSMpArrayDrivenOperationPS: $result"
            }
        }
        if {$debugSwitch} {
            puts "APSMpArrayDrivenOperationPS : $operation: $deviceList"
            flush stdout
        }
        incr operationsDone [llength $deviceList]
    }

    APSWaitWithUpdate -waitSeconds 15
    return -code ok $operationsDone
}

proc APSLArrayDrivenOperationPS {args} {
    set arrayName APSMpLControlPS
    set operation TurnOn
    set value ""
    APSStrictParseArguments {arrayName operation value}
    if {[catch {APSMpArrayDrivenOperationPS -arrayName $arrayName -operation $operation -system linac -value $value} results]} {
        return -code error "$results"
    }
    return -code ok $results
}

proc APSMpLStartUpPSInfo {} {
    return "This procedure allows starting up linac power supplies in groups.  You may choose from among L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:QM L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:QM L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM and L5:AM.  Start up implies turning on the supplies and conditioning.  In addition, you may choose an SCR file from which to restore power supply setpoints.  The conditioning parameters are also configured."
}

set debugSwitch 0

proc APSMpLStartUpPSPackProc {frame} {
    if 0 {
        pack [frame $frame.top]
        APSCheckButtonFrame .unused \
          -parent $frame.top -label "" \
          -variableList {APSMpLStartUpPS(turnOffUnused)} \
          -buttonList {"Turn off unused supplies"} \
          -allNone 0 \
          -packOption {-side top} \
          -orientation horizontal
    }
}

proc APSMpLStartUpPS {args} {
    set SCRFile ""
    set configured 0
    set turnOnList ""
    set conditionList ""
    set turnOnListDetailed ""
    set conditionListDetailed ""
    set autoAdd 0
    set waitForConditioning 1
    set waitForConditioningOnly 0
    set cycles 4
    set turnOffUnused 0
    global debugSwitch
    if [catch {APSLinkToLINACPVs} result] {
        APSMpReturn error "APSMpLStartUpPS: $result"
    }
    if [catch {APSRFGUN_DetectSelectedGun} RGSelected] {
        APSMpReturn error "APSMpLStartUpPS: $RGSelected"
    }
    if [catch {APSPCGUN_ReadRFSwitch1} switch] {
        APSMpReturn error "APSMpLStartUpPS: $switch"
    }

    APSStrictParseArguments {turnOnList conditionList turnOnListDetailed conditionListDetailed SCRFile configured waitForConditioning waitForConditioningOnly cycles turnOffUnused}
    if {([llength $turnOnList] == 0) && ([llength $conditionList] == 0)} {
        set turnOnList [list L1:H L1:V L1:Q L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM L5:AM]
        set conditionList [list L1:H L1:V L1:Q L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM L5:AM]
        set autoAdd 1
    }

    if $debugSwitch {
        puts "Parsed arguments:"
        foreach item {turnOnList conditionList SCRFile configured} {
            puts "$item [set $item]"
        }
        flush stdout
    }
    if {$autoAdd} {
        if {$switch != "GUN"} {
            lappend turnOnList L1:PC1 L1:RG1:LFA:TRM L1:RG2:LFA:TRM
            lappend conditionList L1:PC1 L1:RG1:LFA:TRM L1:RG2:LFA:TRM
        } else {
            if {$RGSelected == "RG1"} {
                lappend turnOnList L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG2:LFA:TRM
                lappend conditionList L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG2:LFA:TRM
            } elseif {$RGSelected == "RG2"} {
                lappend turnOnList L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA
                lappend conditionList L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA
            } else {
                APSMpReturn error "APSMpLStartUpPS: unable to determine which gun is in use."
            }
        }
    }
    if $debugSwitch {
        puts "* Before dialog"
        puts "turnOnList : $turnOnList"
        puts "conditionList : $conditionList"
        flush stdout
    }
    global status mpInterface execMode APSMpLControlPS
    
    set arrayName APSMpLControlPS
    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName \
          -turnOnList $turnOnList -conditionList $conditionList \
          -turnOnListDetailed $turnOnListDetailed -conditionListDetailed $conditionListDetailed \
          -SCRFile $SCRFile -cycles $cycles
    }

    APSMpStep init -promptDialog \
      "APSLGenericPSDialog -packProc APSMpLStartUpPSPackProc -turnOn 1 -condition 1 -chooseSCR 1 -arrayName $arrayName -frame " -vars {turnOffUnused}
    set SCRFile $APSMpLControlPS(Filename)
    if {![file exists $SCRFile]} {
	APSMpReturn error "APSMpLStartUpPS: No SCR file selected"
    }
    if {[catch {exec sdds2stream $SCRFile -parameter=SnapshotDescription -page=1 -noquotes} results]} {
	APSMpReturn error "APSMpLStartUpPS: Invalid SCR file"
    }    
    if {[string first "Limited save:" $results] != -1} {
        if {[catch {exec sddssort $SCRFile -pipe=out -column=Beamline -unique | sdds2stream -pipe=in -col=Beamline} results]} {
            APSMpReturn error "APSMpLStartUpPS: Problem reading beamlines categories from the SCR file"
        } else {
            if {([lsearch -exact $results L1] == -1) || \
                  ([lsearch -exact $results L2] == -1) || \
                  ([lsearch -exact $results L3] == -1) || \
                  ([lsearch -exact $results L4] == -1) || \
                  ([lsearch -exact $results L5] == -1) || \
                  ([lsearch -exact $results rfGun] == -1) || \
                  ([lsearch -exact $results rfGun1] == -1) || \
                  ([lsearch -exact $results rfGun2] == -1)} {
                APSMpReturn error "APSMpLStartUpPS: LIMITED SAVE SCR file does not include all the Linac and rfGun beamline categories"
            }
        }
    }

    set turnOnList [APSLGenericPSArrayQuery -arrayName $arrayName -operation TurnOn]
    set turnOnList [APSMpLConvertDeviceNames -operation TurnOn -deviceList $turnOnList]
    set turnOnList [APSMpLConvertDetailedDeviceNames -operation TurnOn -deviceList $turnOnList -arrayName $arrayName]
    set conditionList [APSLGenericPSArrayQuery -arrayName $arrayName -operation StartConditioning]
    set conditionList [APSMpLConvertDeviceNames -operation StartConditioning -deviceList $conditionList]
    set conditionList [APSMpLConvertDetailedDeviceNames -operation StartConditioning -deviceList $conditionList -arrayName $arrayName]
    if $debugSwitch {
        puts "* After dialog"
        puts "turnOnList : $turnOnList"
        puts "conditionList : $conditionList"
        puts "SCRFile : $SCRFile"
        flush stdout
    }

    set paramString ""
    foreach param {SCRFile turnOnList conditionList cycles turnOffUnused} {
        if {[string length "${paramString}${param}=\"[set $param]\" "] < 1020} {
            append paramString "$param=\"[set $param]\" "
        }
    }
    catch {APSLogScriptAction -procedure APSMpLStartUpPS -action initialize -state ok -parameters $paramString}

#####################
###
    set rateDivOptions ""
    set firstRateDiv 1
    foreach c $conditionList {
        if {$firstRateDiv} {
            append rateDivOptions "-match=column,ControlName=${c}*"
            set firstRateDiv 0
        } else {
            append rateDivOptions ",ControlName=${c}*,|"
        }
    }
    set useRateDiv 0
    if {[string length $rateDivOptions]} {
        if {[catch {exec sddsprocess $SCRFile -pipe=out -match=column,ControlName=*:RateDiv* $rateDivOptions -nowarn | sdds2stream -pipe=in -col=ControlName,ValueString} rateDivData]} {
        } else {
            set rateDivName ""
            set rateDivRestoreOptions ""
            set rateDivNameAndValue ""
            foreach "name value" $rateDivData {
                if {$value == "_NoConnection_"} {
                    continue
                }
                append rateDivName "$name "
                append rateDivRestoreOptions "$name=[format %g $value] "
                append rateDivNameAndValue "${name}=75 "
            }
            if {[string length $rateDivName]} {
                set useRateDiv 1
            }
        }
    }
###
#####################


    if {!$waitForConditioningOnly} {

        for {set i 1} {$i < 3} {incr i} {
            if {([lsearch -exact $conditionList "L1:RG${i}:LFA"] != -1) &&
                ([lsearch -exact $conditionList "L1:RG${i}:LFA:TRM"] != -1)} {
                set answer [tk_dialog2 .warningDialog "Warning Message" "You can only condition the Alpha or the Alpha trim magnet.\nNot both" warning -1 "RG${i} Alpha" "RG${i} Alpha Trim"]
                if {$answer == 0} {
                    set index [lsearch -exact $conditionList "L1:RG${i}:LFA:TRM"]
                } else {
                    set index [lsearch -exact $conditionList "L1:RG${i}:LFA"]
                }
                set conditionList [lreplace $conditionList $index $index]
            }
        }

        APSMpStep "Stop Conditioning"
        if [catch {APSDevSend -cavput 1 -releaseLinks 1 -timeout 0 -group LinacPS -operation StopConditioning -deviceList $conditionList} result] {
            if {[APSPEMTKDialog .warningDialog -text "Unable to stop conditioning\nAPSMpLStartUpPS: \"$result\""] == 1} {
                APSMpReturn error "APSMpLStartUpPS: $result"
            }
#            APSMpReturn error "APSMpLStartUpPS: $result"
        }
        
        if {([lsearch -exact $conditionList "L1:RG1:LFA:TRM"] != -1)} {
            if [catch {APSDevSend -releaseLinks 1 \
                         -group LinacPS \
                         -operation TurnOff \
                         -deviceList "L1:RG1:LFA"} result] {
                if {[APSPEMTKDialog .warningDialog -text "Unable to turn off L1:RG1:LFA\nAPSMpLStartUpPS: $result"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
        }
        if {([lsearch -exact $conditionList "L1:RG2:LFA:TRM"] != -1)} {
            if [catch {APSDevSend -releaseLinks 1 \
                         -group LinacPS \
                         -operation TurnOff \
                         -deviceList "L1:RG2:LFA"} result] {
                if {[APSPEMTKDialog .warningDialog -text "Unable to turn off L1:RG2:LFA\nAPSMpLStartUpPS: $result"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
        }

        if {$turnOffUnused} {
            APSMpStep "Turn off unused supplies" -proc APSMpLTurnOffPS
            set LinacPSGroupUnusedList [APSLGenericPSArrayQuery -arrayName $arrayName -operation TurnOn -invert 1]
            set LinacPSUnusedList [APSMpLConvertDeviceNames -operation TurnOn -deviceList $LinacPSGroupUnusedList]
            set LinacPSUnusedList [APSMpLConvertDetailedDeviceNames -operation TurnOn -deviceList $LinacPSUnusedList -arrayName $arrayName -invert 1]

            foreach device $LinacPSGroupUnusedList {
                set ${arrayName}(TurnOff,$device) 1
            }
            foreach device $LinacPSUnusedList {
                set ${arrayName}(TurnOffDetailed,$device) 1
            }
            APSSetVarAndUpdate status "Unused Supplies -- $LinacPSUnusedList"
            if {[catch {APSMpLTurnOffPS -turnOffList $LinacPSGroupUnusedList -configured 1} result]} {
                if {[APSPEMTKDialog .warningDialog -text "Unable to turn off unused power supplies\nAPSMpLStartUpPS: $result"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
#                APSMpReturn error "APSMpLStartUpPS: $result"
            }	
            
            APSMpStep "Turn off command issued."
            
            
            APSMpStep "Queried supplies on/off state."
            if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                         -deviceList $LinacPSUnusedList} results] {
                APSMpReturn error "APSMpLStartUpPS: $results"
            }
            foreach item $results {
                if {$item != 0} {
                    APSWaitWithUpdate -waitSeconds 15
                    if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                                   -deviceList $LinacPSUnusedList} results2] {
                        APSMpReturn error "APSMpLStartUpPS: $results2"
                    }
                    foreach item2 $results2 {
                        if {$item2 != 0} {
                            APSWaitWithUpdate -waitSeconds 15   
                            if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                                           -deviceList $LinacPSUnusedList} results3] {
                                APSMpReturn error "APSMpLStartUpPS: $results3"
                            }
                            set deviceErrorList ""
                            foreach item3 $results3 device3 $LinacPSUnusedList {
                                if {$item3 != 0} {
                                    append deviceErrorList "$device3 "
                                }
                            }
                            if {[string length $deviceErrorList]} {
                                if {[APSPEMTKDialog .warningDialog -text "$deviceErrorList magnets failed to turn off"] == 1} {
                                    APSMpReturn error "APSMpLStartUpPS: User aborted"
                                }
                            }
                            break
                        }
                    }
                    break
                }
            }
        }
        APSMpStep "Turn on needed supplies" -proc APSMpLTurnOnPS

        if {[catch {APSMpLTurnOnPS -turnOnList $turnOnList -configured 1} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Unable to turn on power supplies\nAPSMpLStartUpPS: $result"] == 1} {
                APSMpReturn error "APSMpLStartUpPS: $result"
            }
#            APSMpReturn error "APSMpLStartUpPS: $result"	    
        }
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                     -deviceList $turnOnList} results] {
            APSMpReturn error "APSMpLStartUpPS: $results"
        }
        foreach item $results {
            if {($item == 0) || ($item == "?")} {

                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent \
                               -deviceList $turnOnList -value 0} results2] {
                    APSMpReturn error "APSMpLStartUpPS: $results2"
                }

                APSWaitWithUpdate -waitSeconds 15
                if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                               -deviceList $turnOnList} results2] {
                    APSMpReturn error "APSMpLStartUpPS: $results2"
                }
                foreach item2 $results2 {
                    if {($item2 == 0) || ($item2 == "?")} {
                        APSWaitWithUpdate -waitSeconds 15
                        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                                       -deviceList $turnOnList} results3] {
                            APSMpReturn error "APSMpLStartUpPS: $results3"
                        }
                        set deviceErrorList ""
                        foreach item3 $results3 device3 $turnOnList {
                            if {($item3 == 0) || ($item3 == "?")} {
                                append deviceErrorList "$device3 "
                            }
                        }
                        if {[string length $deviceErrorList]} {
                            if {[APSPEMTKDialog .warningDialog -text "$deviceErrorList magnets failed to turn on"] == 1} {
                                APSMpReturn error "APSMpLStartUpPS: User aborted"
                            }
                        }
                        break
                    }
                }
                break
            }
        }
        
#####################
###
        if {$useRateDiv} {
            APSMpStep "Reduce PS Rate Div PVs for more accurate conditioning"
            if {[catch {exec cavput -list=[join $rateDivNameAndValue ,]} result]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpLStartUpPS: Error while reducing the PS Rate Div PVs\nThis may cause some of the PS to not track the conditioning setpoints closely"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
        }
####
#####################
        APSMpStep "Condition needed supplies" -proc APSMpLConditionPS
        if [catch {APSMpLConditionPS -arrayName $arrayName -configured 1 \
                       -SCRFile $APSMpLControlPS(Filename)} conditioning] {
            if {[APSPEMTKDialog .warningDialog -text "Error while conditioning needed power supplies \n$conditioning"] == 1} {
                APSMpReturn error "APSMpLStartUpPS: $conditioning"
            }
            set conditioning 1
        }
    }

    if {$waitForConditioning} {
####################
###
        if {!$waitForConditioningOnly} {
            if {$useRateDiv} {
                APSMpStep "Starting PS Conditioning Logger"
                set fileName /tmp/[APSTmpString]
                APSAddToTempFileList $fileName
                if {[catch {APSMpLStartPSConditionLogging -fileName $fileName -deviceList $conditionList} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpLStartUpPS: Unable to log PVs as they condition: $results"] == 1} {
                        APSMpReturn error "APSMpLStartUpPS: Unable to log PVs as the condition: $results"
                    }
                }
            }
        }
###
###################
        if {$waitForConditioningOnly} {
            set conditioning 1
        }
        if $conditioning {
            if {[catch {APSMpLWaitForConditioningPS -deviceList $conditionList} result]} {
                if {[APSPEMTKDialog .warningDialog -text "Error while waiting for power supplies to condition \n$result"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
        }
####################
###
        if {$useRateDiv} {
            if {[catch {exec cavput -list=[join $rateDivRestoreOptions ,]} result]} {
                if {[APSPEMTKDialog .warningDialog -text "Error while restoring the PS Rate Div PVs\nThis may cause some of the PS ramp to the SCR setpoint faster than normal"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
            if {!$waitForConditioningOnly} {
                APSMpStep "Examining PS Conditioning Logger"
                if {[catch {APSMpLExaminePSConditionLogging -fileName $fileName -deviceList $conditionList} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpLStartUpPS: Unable to examine log of PVs as they conditioned: $results"] == 1} {
                        APSMpReturn error "APSMpLStartUpPS: Unable to examine log of PVs as they conditioned: $results"
                    }
                }
            }
        }
####
####################
        set option ""
        set i 0
        set detailedList "$conditionList $turnOnList"
        foreach supply $detailedList {
            if {$i == 0} {
                append option "-match=column,ControlName=${supply}*"
                incr i
            } else {
                append option ",ControlName=${supply}*,|"
            }
        }

        if [string length $APSMpLControlPS(Filename)] {
            APSMpStep RestoringSCRValues 
            set tmpFile /tmp/[APSTmpString]
            if [catch {exec sddsprocess $APSMpLControlPS(Filename) $tmpFile \
                         -match=column,IsReadOnly=+n \
                         -match=column,Category=MainPS,Category=SteeringPS,| \
                         -match=col,ControlType=,! -match=col,ControlName=,! $option
                exec sddscasr -restore $tmpFile} result] {
                APSPEMTKDialog .warningDialog -strings Continue -default 0 -text "Problem restoring SCR file: APSMpLStartUpPS: $result"
                catch {APSSendEMail -address soliday \
                         -subject "Problem restoring SCR file."  \
                         -message "Problem restore SCR file\nAPSMpLStartUpPS\n$SCRFile\n$result"} 

            }
        }

        if {0} {
            if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList "L3:AM1"} result] {
                APSMpReturn error "APSMpLStartUpPS: $result"
            }
            if {$result} {
                if [catch {APSDevSend -releaseLinks 1 \
                             -group LinacPS \
                             -operation ReadCurrent \
                             -deviceList "L3:AM1"} result2] {
                    return -code error "APSMpLStartUpPS: $result2"
                }
                APSMpStep "Setting L3:AM1 current to zero"
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent -deviceList "L3:AM1" -value 0} result] {
                    if {[APSPEMTKDialog .warningDialog -text "Error while setting L3:AM1 current to zero \n$result"] == 1} {
                        APSMpReturn error "APSMpLStartUpPS: $result"
                    }
                }
                if {[expr abs($result2)] > 1} {
                    APSWaitWithUpdate -waitSeconds 10
                }
            }

            APSMpStep "Turning off L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1 L3:AM1T L5:AM1"
            if [catch {APSDevSend -releaseLinks 1 \
                         -group LinacPS \
                         -operation TurnOff \
                         -deviceList "L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1 L3:AM1T L5:AM1"} result] {
                if {[APSPEMTKDialog .warningDialog -text "Unable to turn off L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1 L3:AM1T L5:AM1\nAPSMpLStartUpPS: $result"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
        } else {
            APSMpStep "Turning off L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1T L5:AM1"
            if [catch {APSDevSend -releaseLinks 1 \
                         -group LinacPS \
                         -operation TurnOff \
                         -deviceList "L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1T L5:AM1"} result] {
                if {[APSPEMTKDialog .warningDialog -text "Unable to turn off L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1 L3:AM1T L5:AM1\nAPSMpLStartUpPS: $result"] == 1} {
                    APSMpReturn error "APSMpLStartUpPS: $result"
                }
            }
        }
    }
    APSMpReturn ok
}


proc APSMpLConditionPowerSuppliesInfo {} {
    return "This procedure allows conditioning up linac power supplies in groups.  You may choose from among L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:QM L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:QM L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM and L5:AM.  In addition, you may choose an SCR file from which to restore power supply setpoints.  The conditioning parameters are also configured."
}

set debugSwitch 0

proc APSMpLConditionPowerSupplies {args} {
    set autoAdd 0
    set SCRFile ""
    set configured 0
    set conditionList ""
    set conditionListDetailed ""
    set turnOnList ""
    set turnOnListDetailed ""
    set conditionList ""
    set cycles 4
    global debugSwitch
    if [catch {APSLinkToLINACPVs} result] {
        APSMpReturn error "APSMpLConditionPowerSupplies: $result"
    }
    if [catch {APSRFGUN_DetectSelectedGun} RGSelected] {
        APSMpReturn error "APSMpLConditionPowerSupplies: $RGSelected"
    }
    if [catch {APSPCGUN_ReadRFSwitch1} switch] {
        APSMpReturn error "APSMpLConditionPowerSupplies: $switch"
    }

    APSStrictParseArguments {autoAdd conditionList conditionListDetailed SCRFile configured cycles}
    
    if {[llength $conditionList] == 0} {
        set conditionList [list L1:H L1:V L1:Q L2:SC L2:QM L3:CHICANE L3:MATCHING L4:SC L4:QM L5:SC L5:QM]
        set autoAdd 1
    }


    if {$autoAdd} {
        if {$switch != "GUN"} {
            lappend conditionList L1:PC1 L1:RG1:LFA:TRM L1:RG2:LFA:TRM
        } else {
            if {$RGSelected == "RG1"} {
                lappend conditionList L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG2:LFA:TRM
            } elseif {$RGSelected == "RG2"} {
                lappend conditionList L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA
            } else {
                APSMpReturn error "APSMpLConditionPowerSupplies: unable to determine which gun is in use."
            }
        }
    }

    if $debugSwitch {
        puts "Parsed arguments:"
        foreach item {conditionList SCRFile configured} {
            puts "$item [set $item]"
        }
        flush stdout
    }
    global status mpInterface execMode APSMpLControlPS
    set turnOnList $conditionList
    set turnOnListDetailed $conditionListDetailed
    set arrayName APSMpLControlPS
    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName \
          -turnOnList $turnOnList -turnOnListDetailed $turnOnListDetailed \
          -conditionList $conditionList \
          -conditionListDetailed $conditionListDetailed \
          -SCRFile $SCRFile -cycles $cycles
    }

    APSMpStep init -promptDialog \
      "APSLGenericPSDialog -turnOn 0 -condition 1 -chooseSCR 1 -arrayName $arrayName -frame "
    set SCRFile $APSMpLControlPS(Filename)

    set conditionList [APSLGenericPSArrayQuery -arrayName $arrayName -operation StartConditioning]
    set cld [APSMpLConvertDeviceNames -operation StartConditioning -deviceList $conditionList]
    set cld [APSMpLConvertDetailedDeviceNames -operation StartConditioning -deviceList $cld -arrayName $arrayName]

    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName \
          -turnOnList $conditionList -turnOnListDetailed $cld \
          -conditionList $conditionList -conditionListDetailed $cld \
          -SCRFile $SCRFile -cycles $cycles
    }
    if {![file exists $SCRFile]} {
	APSMpReturn error "APSMpLConditionPowerSupplies: No SCR file selected"
    }
    if {[catch {exec sdds2stream $SCRFile -parameter=SnapshotDescription -page=1 -noquotes} results]} {
	APSMpReturn error "APSMpLConditionPowerSupplies: Invalid SCR file"
    }    
    if {[string first "Limited save:" $results] != -1} {
        if {[catch {exec sddssort $SCRFile -pipe=out -column=Beamline -unique | sdds2stream -pipe=in -col=Beamline} results]} {
            APSMpReturn error "APSMpLConditionPowerSupplies: Problem reading beamlines categories from the SCR file"
        } else {
            if {([lsearch -exact $results L1] == -1) || \
                  ([lsearch -exact $results L2] == -1) || \
                  ([lsearch -exact $results L3] == -1) || \
                  ([lsearch -exact $results L4] == -1) || \
                  ([lsearch -exact $results L5] == -1) || \
                  ([lsearch -exact $results rfGun] == -1) || \
                  ([lsearch -exact $results rfGun1] == -1) || \
                  ([lsearch -exact $results rfGun2] == -1)} {
                APSMpReturn error "APSMpLConditionPowerSupplies: LIMITED SAVE SCR file does not include all the Linac and rfGun beamline categories"
            }
        }
    }

    set conditionList [APSLGenericPSArrayQuery -arrayName $arrayName -operation StartConditioning]
    set conditionList [APSMpLConvertDeviceNames -operation StartConditioning -deviceList $conditionList]
    set conditionList [APSMpLConvertDetailedDeviceNames -operation StartConditioning -deviceList $conditionList -arrayName $arrayName]
    #    set conditionList $conditionListDetailed

    if $debugSwitch {
        puts "* After dialog"
        puts "conditionList : $conditionList"
        puts "SCRFile : $SCRFile"
        flush stdout
    }
    set paramString ""
    foreach param {SCRFile conditionList turnOnList cycles} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction -procedure APSMpLConditionPowerSupplies -action initialize -state ok -parameters $paramString}

    for {set i 1} {$i < 3} {incr i} {
        if {([lsearch -exact $conditionList "L1:RG${i}:LFA"] != -1) &&
            ([lsearch -exact $conditionList "L1:RG${i}:LFA:TRM"] != -1)} {
            set answer [tk_dialog2 .warningDialog "Warning Message" "You can only condition the Alpha or the Alpha trim magnet.\nNot both" warning -1 "RG${i} Alpha" "RG${i} Alpha Trim"]
            if {$answer == 0} {
                set index [lsearch -exact $conditionList "L1:RG${i}:LFA:TRM"]
            } else {
                set index [lsearch -exact $conditionList "L1:RG${i}:LFA"]
            }
            set conditionList [lreplace $conditionList $index $index]
        }
    }

    if {([lsearch -exact $conditionList "L1:RG1:LFA:TRM"] != -1)} {
        if [catch {APSDevSend -releaseLinks 1 \
                     -group LinacPS \
                     -operation TurnOff \
                     -deviceList "L1:RG1:LFA"} result] {
            if {[APSPEMTKDialog .warningDialog -text "Unable to turn off L1:RG1:LFA\nAPSMpLStartUpPS: $result"] == 1} {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result"
            }
        }
    }
    if {([lsearch -exact $conditionList "L1:RG2:LFA:TRM"] != -1)} {
        if [catch {APSDevSend -releaseLinks 1 \
                     -group LinacPS \
                     -operation TurnOff \
                     -deviceList "L1:RG2:LFA"} result] {
            if {[APSPEMTKDialog .warningDialog -text "Unable to turn off L1:RG2:LFA\nAPSMpLStartUpPS: $result"] == 1} {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result"
            }
        }
    }

    set turnOnList $conditionList

    APSMpStep "Stop Conditioning"
    if [catch {APSDevSend -cavput 1 -releaseLinks 1 -timeout 0 -group LinacPS -operation StopConditioning -deviceList $conditionList} result] {
        if {[APSPEMTKDialog .warningDialog -text "Error while stoping conditioning for $conditionList \n$result"] == 1} {
            APSMpReturn error "APSMpLConditionPowerSupplies: $result"
        }
#        APSMpReturn error "APSMpLConditionPowerSupplies: $result"
    }	

    APSMpStep "Turn on needed supplies" -proc APSMpLTurnOnPS
    if {[catch {APSMpLTurnOnPS -turnOnList $turnOnList -configured 1} result]} {
        if {[APSPEMTKDialog .warningDialog -text "Error while turning on $turnOnList \n$result"] == 1} {
            APSMpReturn error "APSMpLConditionPowerSupplies: $result"
        }
#        APSMpReturn error "APSMpLConditionPowerSupplies: $result"	    
    }
    
    
    if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                   -deviceList $conditionList} result] {
        APSMpReturn error "APSMpLConditionPowerSupplies: $result"
    }
    foreach item $result {
        if {!$item} {
            APSWaitWithUpdate -waitSeconds 15
            if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                           -deviceList $conditionList} result2] {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result2"
            }
            foreach item2 $result2 {
                if {!$item2} {
                    APSWaitWithUpdate -waitSeconds 15
                    if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                                   -deviceList $conditionList} result3] {
                        APSMpReturn error "APSMpLConditionPowerSupplies: $result3"
                    }
                    set deviceErrorList ""
                    foreach item3 $result3 device3 $conditionList {
                        if {!$item3} {
                            append deviceErrorList "$device3 "
                        }
                    }
                    if {[string length $deviceErrorList]} {
                        if {[APSPEMTKDialog .warningDialog -text "$deviceErrorList magnets are not on"] == 1} {
                            APSMpReturn error "APSMpLConditionPowerSupplies: User aborted"
                        }
                    }
                    break
                }
            }
            break
        }
    }
    
    if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList "L3:AM1"} result] {
        APSMpReturn error "APSMpLConditionPowerSupplies: $result"
    }
    if {$result} {
        if [catch {APSDevSend -releaseLinks 1 \
                     -group LinacPS \
                     -operation ReadCurrent \
                     -deviceList "L3:AM1"} result2] {
            return -code error "APSMpLConditionPowerSupplies: $result2"
        }
        APSMpStep "Setting L3:AM1 current to zero"
        if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent -deviceList "L3:AM1" -value 0} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while setting L3:AM1 current to zero \n$result"] == 1} {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result"
            }
        }
        if {[expr abs($result2)] > 1} {
            APSWaitWithUpdate -waitSeconds 10
        }
        if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation TurnOff -deviceList "L3:AM1"} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while turning off L3:AM1 \n$result"] == 1} {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result"
            }
        }
    }


#####################
#####
    APSMpStep "Reduce PS Rate Div PVs for more accurate conditioning"
    set rateDivOptions ""
    set firstRateDiv 1
    foreach c $conditionList {
        if {$firstRateDiv} {
            append rateDivOptions "-match=column,ControlName=${c}*"
            set firstRateDiv 0
        } else {
            append rateDivOptions ",ControlName=${c}*,|"
        }
    }
    if {[string length $rateDivOptions]} {
        set useRateDiv 0
        if {[catch {exec sddsprocess $SCRFile -pipe=out -match=column,ControlName=*:RateDiv* $rateDivOptions -nowarn | sdds2stream -pipe=in -col=ControlName,ValueString} rateDivData]} {
        } else {
            set rateDivName ""
            set rateDivRestoreOptions ""
            set rateDivNameAndValue ""
            foreach "name value" $rateDivData {
                if {$value == "_NoConnection_"} {
                    continue
                }
                append rateDivName "$name "
                append rateDivRestoreOptions "$name=[format %g $value] "
                append rateDivNameAndValue "${name}=75 "
            }
            if {[string length $rateDivName]} {
                set useRateDiv 1
                if {[catch {exec cavput -list=[join $rateDivNameAndValue ,]} result]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpLConditionPowerSupplies: Error while reducing the PS Rate Div PVs\nThis may cause some of the PS to not track the conditioning setpoints closely"] == 1} {
                        APSMpReturn error "APSMpLConditionPowerSupplies: $result"
                    }
                }
            }
        }
    }
#####
#####################
    APSMpStep "Condition needed supplies" -proc APSMpLConditionPS
    if [catch {APSMpLConditionPS -arrayName $arrayName -configured 1 \
                 -SCRFile $APSMpLControlPS(Filename) } conditioning] {
        if {[APSPEMTKDialog .warningDialog -text "Error while conditioning power supplies \n$conditioning"] == 1} {
            APSMpReturn error "APSMpLConditionPowerSupplies: $conditioning"
        }
        set conditioning 1
#        APSMpReturn error "APSMpLConditionPowerSupplies: $conditioning"
    }
    
    if $conditioning {
###################
####
        if {$useRateDiv} {
            APSMpStep "Starting PS Conditioning Logger"
            set fileName /tmp/[APSTmpString]
            APSAddToTempFileList $fileName
            if {[catch {APSMpLStartPSConditionLogging -fileName $fileName -deviceList $conditionList} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpLConditionPowerSupplies: Unable to log PVs as they condition: $results"] == 1} {
                    APSMpReturn error "APSMpLConditionPowerSupplies: Unable to log PVs as the condition: $results"
                }
            }
        }
#####
###################
        if {[catch {APSMpLWaitForConditioningPS -deviceList $conditionList} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while waiting for power supplies to condition \n$result"] == 1} {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result"
            }
        }
###################
#####
        if {$useRateDiv} {
            if {[catch {exec cavput -list=[join $rateDivRestoreOptions ,]} result]} {
                if {[APSPEMTKDialog .warningDialog -text "Error while restoring the PS Rate Div PVs\nThis may cause some of the PS ramp to the SCR setpoint faster than normal"] == 1} {
                    APSMpReturn error "APSMpLConditionPowerSupplies: $result"
                }
            }
            APSMpStep "Examining PS Conditioning Logger"
            if {[catch {APSMpLExaminePSConditionLogging -fileName $fileName -deviceList $conditionList} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpLConditionPowerSupplies: Unable to examine log of PVs as they conditioned: $results"] == 1} {
                    APSMpReturn error "APSMpLConditionPowerSupplies: Unable to examine log of PVs as they conditioned: $results"
                }
            }
        }
#####
###################
    }
    
    set option ""
    set i 0
    foreach supply $conditionList {
        if {$i == 0} {
            append option "-match=column,ControlName=${supply}*"
            incr i
        } else {
            append option ",ControlName=${supply}*,|"
        }
    }

    if [string length $APSMpLControlPS(Filename)] {
        APSMpStep RestoringSCRValues 
        set tmpFile /tmp/[APSTmpString]
        if [catch {exec sddsprocess $APSMpLControlPS(Filename) $tmpFile \
                     -match=column,IsReadOnly=+n \
                     -match=column,Category=MainPS,Category=SteeringPS,| \
                     -match=col,ControlType=,! -match=col,ControlName=,! $option
            exec sddscasr -restore $tmpFile} result] {
            catch {APSSendEMail -address soliday \
                     -subject "Problem restoring SCR file."  \
                     -message "Problem restore SCR file\nAPSMpLConditionPowerSupplies\n$SCRFile\n$result"} 
            if {[APSPEMTKDialog .warningDialog -text "Problem restoring SCR file: APSMpLConditionPowerSupplies: $SCRFile: \n$result"] == 1} {
                APSMpReturn error "Problem restoring SCR file: APSMpLConditionPowerSupplies: $SCRFile: $result"
            }
        }
    }
    
    if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation QueryOn -deviceList "L3:AM1"} result] {
        APSMpReturn error "APSMpLConditionPowerSupplies: $result"
    }
    if {$result} {
        if [catch {APSDevSend -releaseLinks 1 \
                     -group LinacPS \
                     -operation ReadCurrent \
                     -deviceList "L3:AM1"} result] {
            return -code error "APSMpLConditionPowerSupplies: $result2"
        }
        APSMpStep "Setting L3:AM1 current to zero"
        if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent -deviceList "L3:AM1" -value 0} result] {
            if {[APSPEMTKDialog .warningDialog -text "Error while setting L3:AM1 current to zero \n$result"] == 1} {
                APSMpReturn error "APSMpLConditionPowerSupplies: $result"
            }
        }
        if {[expr abs($result2)] > 1} {
            APSWaitWithUpdate -waitSeconds 10
        } 
    }
    if [catch {APSDevSend -releaseLinks 1 \
                 -group LinacPS \
                 -operation TurnOff \
                 -deviceList "L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1 L3:AM1T L5:AM1"} result] {
        if {[APSPEMTKDialog .warningDialog -text "Error while turning off L1:RG1:LFA:TRM L1:RG2:LFA:TRM L3:AM1 L3:AM1T L5:AM power supplies \n$result"] == 1} {
            APSMpReturn error "APSMpLConditionPowerSupplies: $result"
        }
    }

    APSMpReturn ok
}


proc APSMpLWaitTurnOnPS {args} {
    set deviceList ""
    APSStrictParseArguments {deviceList}

    set steps 10
    set someOff 1
    while {$steps && $someOff} {
        incr steps -1
        set someOff 0
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation QueryOn \
                     -deviceList $deviceList} result] {
            APSMpReturn error "APSMpLWaitTurnOnPS: $result"
        }
        set deviceOffList ""
        foreach item $result device $deviceList {
            if !$item {
                lappend deviceOffList $device
                incr someOff 1
            }
        }
        if $someOff {
            APSMpStep "Waiting for turn on of $someOff ganged devices: [join $deviceOffList ,]"
            APSWaitWithUpdate -waitSeconds 5 -updateInterval 1
        }
    }
    if $someOff {
        if ![APSQueryToProceed -message "Some supplies not on.  What do you want to do?"] {
            APSMpReturn error "Some supplies did not turn on."
        }
    }
    APSMpReturn ok
}

proc APSMpLConditionPS {args} {
    set arrayName APSMpLControlPS
    set configured 0
    set conditionList ""
    set conditionListDetailed ""
    set SCRFile ""
    APSStrictParseArguments {arrayName configured conditionList conditionListDetailed SCRFile}

    global $arrayName
    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName \
          -conditionList $conditionList -conditionListDetailed $conditionListDetailed
    }

    APSMpStep init -promptDialog \
      "APSLGenericPSDialog -condition 1 -arrayName $arrayName -frame "
    set conditionList [APSLGenericPSArrayQuery -arrayName $arrayName -operation StartConditioning]
    set conditionList [APSMpLConvertDeviceNames -operation StartConditioning -deviceList $conditionList]
    set conditionList [APSMpLConvertDetailedDeviceNames -operation StartConditioning -deviceList $conditionList -arrayName $arrayName]

    if ![llength $conditionList] {
        APSMpReturn ok 0
    }

    APSMpStep "Configure conditioning"
    if [catch {exec sddscasr -restore /home/helios/oagData/controlFiles/Linac/conditioning/linacConditioning.snap} result] {
        return -code error "APSMpLConditionPS: $result"
    }
    set cycles [set ${arrayName}(StartConditioningInfo,cycles)]
    #    set tmpFile /tmp/[APSTmpString]
    #    if {[catch {
    #	sdds load /home/helios/oagData/controlFiles/Linac/conditioning/Linac.std data
    #	set data(Column.NumCycles) [list [APSReplicateItem -item $cycles -number [llength [lindex $data(Column.NumCycles) 0]]]]
    #	sdds save $tmpFile data
    #    } results]} {
    #	APSMpReturn error "APSMpLConditionPS: $result"
    #    }
    #    APSAddToTempFileList $tmpFile

    #    if [catch {exec standardize -configure $tmpFile} result] {
    #	APSMpReturn error "APSMpLConditionPS: $result"
    #    }
    if [catch {exec standardize -configure /home/helios/oagData/controlFiles/Linac/conditioning/Linac.std} result] {
        return -code error "APSMpLConditionPS: $result"
    }
    if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetConditioningCycles -deviceList $conditionList -value $cycles} result] {
        return -code error "APSMpLConditionPS: $result"
    }
    if {[string length $SCRFile] && [file exists $SCRFile]} {
        # extract the setpoints from the SCR file and use them as the 
        # conditioning endpoints
        APSMpStep "Configure conditioning from snapshot"

        if [catch {exec sddsselect $SCRFile /home/helios/oagData/pem/linac/filterFile -match=ControlName -pipe=out | sdds2stream -column=ControlName,ValueString -pipe=in} results] {
            return -code error "APSMpLConditionPS: Invalid SCR file"
        }
        set L3:BM2 0
        set L3:BM4 0
        foreach {controlName valueString} $results {
            if {$controlName == "L3:BM2T:CurrentAO"} {
                set L3:BM2 $valueString
            } elseif {$controlName == "L3:BM4T:CurrentAO"} {
                set L3:BM4 $valueString
            }
        }
        foreach mag1 "L3:BM2 L3:BM4" {
            set index [lsearch -exact $conditionList $mag1]
            if {$index != -1} {
                if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation SetCurrent -deviceList $mag1 -value [set $mag1]} result] {
                    return -code error "APSMpLConditionPS: $result"
                }
                APSWaitWithUpdate -waitSeconds 5
                set conditionList [lreplace $conditionList $index $index]
            }
        }

        set tmpRoot /tmp/[APSTmpString]
        if [catch {exec sddsprocess /home/helios/oagData/deviceConfig/linac/PSOps.pvTable \
                     $tmpRoot.setpt -match=column,Operation=SetCurrent 
            exec sddsprocess /home/helios/oagData/deviceConfig/linac/PSOps.pvTable \
                     $tmpRoot.setcond -match=column,Operation=SetConditioningEndpoint
            exec sddsxref -nowarning $SCRFile $tmpRoot.setpt -pipe=out \
                     -match=ControlName -take=DeviceName \
                     | sddsconvert -pipe -delete=column,ControlName \
                     | sddsxref -pipe=in $tmpRoot.setcond -nowarning \
                     $tmpRoot.snap -match=DeviceName -take=ControlName
            exec sddscasr -restore $tmpRoot.snap} result] {
            catch {eval file delete -force $tmpRoot.setpt $tmpRoot.setcond $tmpRoot.snap}
            return -code error "APSMpLConditionPS: $result"
        }
        catch {eval file delete -force $tmpRoot.setpt $tmpRoot.setcond $tmpRoot.snap}
    }

    global debugSwitch
    if $debugSwitch {
        puts "Conditioning: $conditionList"
        flush stdout
    }

    APSMpStep "Starting conditioning for [llength $conditionList] devices" -desc "Starting conditioning"
    if [catch {APSDevSend -releaseLinks 1 -group LinacPS -operation StartConditioning \
                 -deviceList $conditionList -timeout 0} result] {
        return -code error "APSMpLConditionPS: $result"
    }
    return [llength $conditionList]
}

proc APSMpLWaitForConditioningPS {args} {
    if [catch {APSLinkToLINACPVs} result] {
        APSMpReturn error "APSMpLWaitForConditioningPS: $result"
    }
    set deviceList [APSDevSend -releaseLinks 1 -group LinacPS -operation QueryConditioning]
    APSStrictParseArguments {deviceList}

    set timeToStop [expr [clock seconds]+20*60]
    set someConditioning 1
    APSMpStep "Waiting For Conditioning"
    set stepsTaken 0
    set query QueryConditioning
    while {$someConditioning && $timeToStop>[clock seconds]} {
        APSWaitWithUpdate -waitSeconds 10 -updateInterval 1
        set someConditioning 0
        incr stepsTaken
        if [catch {APSDevSend -releaseLinks 1 -timeout 30 -group LinacPS -operation $query \
                     -deviceList $deviceList} result] {
            APSMpReturn error "APSMpLWaitForConditionPS: $result"
        }
        set someConditioning 0
        foreach item $result {
            incr someConditioning $item
        }
        if $someConditioning {
            APSMpStep "Waiting For Conditioning of $someConditioning ganged devices"
            APSWaitWithUpdate -waitSeconds 15 -updateInterval 1
            if $stepsTaken==5 {
                APSMpStep "You are getting sleepy..."
            }
            if $stepsTaken==15 {
                APSMpStep "You are getting very sleepy..."
            }
            if $stepsTaken==20 {
                APSMpStep "You are getting very, very sleepy..."
            }
        } else {
           APSMpStep "Supplies finished conditioning" 
        }
    }
    if $someConditioning {
        if ![APSQueryToProceed -message "Some supplies still conditioning.  What do you want to do?"] {
            APSMpReturn error "Some supplies did not finish conditioning."
        }
    }
    APSMpReturn ok
}

proc APSMpLShutDownPSInfo {} {
    return "This procedure allows shutting down linac power supplies in groups.  You may choose from among L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:QM L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:QM L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM and L5:AM.  Shut down implies (optionally) conditioning and then turning off supplies."
}

proc APSMpLShutDownPS {args} { 
    set turnOffList [list L1:PC1 L1:RG1:H L1:RG1:V L1:RG1:Q L1:RG1:LFA L1:RG1:LFA:TRM L1:RG2:H L1:RG2:V L1:RG2:Q L1:RG2:LFA L1:RG2:LFA:TRM L1:H L1:V L1:Q L2:SC L2:QM L3:CHICANE L3:MATCHING L3:AM1T L4:SC L4:QM L5:SC L5:QM L5:AM]
    set turnOffListDetailed ""
    set conditionList ""
    set conditionListDetailed ""
    set configured 0
    set SCRFile ""
    if [catch {APSLinkToLINACPVs} result] {
        APSMpReturn error "APSMpLShutDownPS: $result"
    }

    APSStrictParseArguments {turnOffList conditionList configured turnOffListDetailed conditionListDetailed SCRFile}
    global status mpInterface execMode APSMpLControlPS
    
    set arrayName APSMpLControlPS

    if {![info exists $arrayName] || !$configured} {
        APSLGenericPSArraySetup -arrayName $arrayName \
          -turnOffList $turnOffList -conditionList $conditionList \
          -turnOffListDetailed $turnOffListDetailed \
          -conditionListDetailed $conditionListDetailed \
          -SCRFile $SCRFile
    }
    if {(![file exists $SCRFile]) && ($execMode == "Automatic")} {
        set execMode "Semi-Automatic"
    }

    APSMpStep init -promptDialog \
      "APSLGenericPSDialog -turnOff 1 -condition 1 -arrayName $arrayName -chooseSCR 1 -frame "
    set SCRFile $APSMpLControlPS(Filename)
    set conditionList [APSLGenericPSArrayQuery -arrayName $arrayName -operation StartConditioning]
    set conditionList [APSMpLConvertDeviceNames -operation StartConditioning -deviceList $conditionList]
    set conditionList [APSMpLConvertDetailedDeviceNames -operation StartConditioning -deviceList $conditionList -arrayName $arrayName]


    APSMpStep ConditionSupplies -proc APSMpLConditionPS
    if [catch {APSMpLConditionPS -arrayName $arrayName -configured 1 -SCRFile $SCRFile} conditioning] {
        if {[APSPEMTKDialog .warningDialog -text "Error while conditioning power supplies \n$conditioning"] == 1} {
            APSMpReturn error "APSMpLShutDownPS: $conditioning"
        }
        set conditioning 1
    }
    if $conditioning {
        if {[catch {APSMpLWaitForConditioningPS -deviceList $conditionList} result]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while waiting for power supplies to condition \n$result"] == 1} {
                APSMpReturn error "APSMpLShutDownPS: $result"
            }
        }
    }

    APSMpStep TurnOffSupplies
    if [catch {APSMpLTurnOffPS -arrayName $arrayName -configured 1} turningOff] {
        if {[APSPEMTKDialog .warningDialog -text "Error while turning off power supplies \n$turningOff"] == 1} {
            APSMpReturn error "APSMpLShutDownPS: $turningOff"
        }
    }

    APSMpReturn ok
}

proc APSMpConvertDeviceNames {args} {
    set operation ""
    set deviceList ""
    set system linac
    APSStrictParseArguments {operation deviceList system}
    set convertedNames ""
    if {($system == "booster") || ($system == "lts") || ($system == "lea")} {
        set fullDeviceList [APSDevSend -releaseLinks 1 -group PSOps -operation $operation]
      #  puts $fullDeviceList
        foreach deviceFull $fullDeviceList {
            foreach device $deviceList {
                if {[string match ${device}* $deviceFull]} {
                    lappend convertedNames $deviceFull
                    break
                }
            }
        }
    } else {
        set fullDeviceList [APSDevSend -releaseLinks 1 -group LinacPS -operation $operation]
        set index [lsearch -exact $deviceList "L3:CHICANE"]
        if {$index != -1} {
            set deviceList [lreplace $deviceList $index $index L3:BM L3:QM1 L3:QM2]
        }
        set index [lsearch -exact $deviceList "L3:MATCHING"]
        if {$index != -1} {
            set deviceList [lreplace $deviceList $index $index L3:SC L3:QM3 L3:QM4 L3:QM5 L3:QM6]
        }
        foreach deviceFull $fullDeviceList {
            foreach device $deviceList {
                if {[string match ${device}* $deviceFull]} {
                    if {([string match L1:RG?:LFA $device]) &&
                        ([string match ${device}:TRM* $deviceFull])} {
                        continue
                    }
                    lappend convertedNames $deviceFull
                    break
                }
            }
        }
        set index [lsearch -exact $convertedNames "L1:QM:RAW"]
        if {$index != -1} {
            set convertedNames [lreplace $convertedNames $index $index]
        }
        #set index [lsearch -exact $convertedNames "L1:RG1:SC1:HZ"]
        #if {$index != -1} {
            #set convertedNames [lreplace $convertedNames $index $index]
        #}
    }
    return $convertedNames
}

proc APSMpLConvertDeviceNames {args} {
    set operation ""
    set deviceList ""
    APSStrictParseArguments {operation deviceList}
    return [APSMpConvertDeviceNames -operation $operation -deviceList $deviceList -system linac]
}

proc APSMpConvertDetailedDeviceNames {args} {
    set operation ""
    set deviceList ""
    set arrayName APSMpLControlPS
    set invert 0
    APSStrictParseArguments {operation deviceList arrayName invert}
    global $arrayName
    set convertedNames ""
    foreach detailedDevice $deviceList {
        if {[set ${arrayName}(${operation}Detailed,$detailedDevice)]!=$invert} {
            lappend convertedNames $detailedDevice
        }
    }
    return $convertedNames
}

proc APSMpLConvertDetailedDeviceNames {args} {
    set operation ""
    set deviceList ""
    set arrayName APSMpLControlPS
    set invert 0
    APSStrictParseArguments {operation deviceList arrayName invert}
    APSMpConvertDetailedDeviceNames -operation $operation \
      -deviceList $deviceList \
      -arrayName $arrayName \
      -invert $invert
}

proc APSPEMTKDialogHelp {} {
    return "Usage: APSPEMTKDialogHelp widget\n\[-title <string>\]\n\[-text <string>\]\n\[-bitmap <string>\]\n\[-default <button index>\]\n\[-strings <button list>\]\n\[-wrapLength <length>\]\n\[-appendtext <1|0>\]"
}

proc APSPEMTKDialog {widget args} {
    set title "PEM Warning Message"
    set text "No Message Given"
    set bitmap warning
    set default -1
    set strings {Continue "Abort Procedure"}
    set wrapLength 10i
    set appendtext 1
    APSStrictParseArguments {title text bitmap default strings wrapLength appendtext}
    global apsNetworkDomain
    set procName [lindex [info level [expr [info level] - 1]] 0]


    set abortButton [lsearch -glob [string tolower $strings] *abort*]
    if {$appendtext} {
        append text "\n\nPlease investigate this problem."
        if {[lsearch -glob [string tolower $strings] *continue*] != -1} {
            append text "\nIf possible, fix the problem and then press Continue."
        }
        if {$abortButton != -1} {
            append text "\nIf the problem cannot be fixed or safely ignored, press Abort."
        }
    }
    set num [llength $strings]
    option add *Dialog.msg.wrapLength $wrapLength
    if {$num == 0} {
        set answer $default
    } else {
        if {[string length $text] > 3100} {
            set text "[string range $text 0 1500]\n...\n[string range $text end-1500 end]"
        }
        set answer [eval tk_dialog2 \"$widget\" \"$title\" \"$text\" \"$bitmap\" \"$default\" $strings]
    }
    update
    set state ok
    if {$answer == $abortButton} {
        tk_dialog2 $widget "Notification Message" "Warning: you have aborted a procedure\nprior to completion. As a result, the\nmachine is unlikely to be in the desired\nstate. You must manually continue the\noperation or else rerun the procedure." "" 0 "OK"
        set state abort
    }

    set action [string range [join [split $text \n]] 0 100]
    if {(![string compare $apsNetworkDomain "accel.ntw0rk"]) || (![string compare $apsNetworkDomain "aps4.anl.gov"])} {
	catch {APSLogScriptAction \
                 -procedure APSPEMTKDialog \
                 -state $state \
                 -action $action}
    }

    return $answer
}

proc ::tk_dialog2 {w title text bitmap default args} {
    global tcl_platform
    variable ::tk::Priv

    # Check that $default was properly given
    if {[string is int $default]} {
	if {$default >= [llength $args]} {
	    return -code error "default button index greater than number of\
		    buttons specified for tk_dialog"
	}
    } elseif {[string equal {} $default]} {
	set default -1
    } else {
	set default [lsearch -exact $args $default]
    }

    # 1. Create the top-level window and divide it into top
    # and bottom parts.

    catch {destroy $w}
    toplevel $w -class Dialog
    append title " [clock format [clock seconds] -format {%H:%M:%S}]"
    wm title $w $title
    wm iconname $w Dialog
    wm protocol $w WM_DELETE_WINDOW { }

    # Dialog boxes should be transient with respect to their parent,
    # so that they will always stay on top of their parent window.  However,
    # some window managers will create the window as withdrawn if the parent
    # window is withdrawn or iconified.  Combined with the grab we put on the
    # window, this can hang the entire application.  Therefore we only make
    # the dialog transient if the parent is viewable.
    #
    if {[winfo viewable [winfo toplevel [winfo parent $w]]] } {
	wm transient $w [winfo toplevel [winfo parent $w]]
    }    

    if {[string equal $tcl_platform(platform) "macintosh"]
	    || [string equal [tk windowingsystem] "aqua"]} {
	::tk::unsupported::MacWindowStyle style $w dBoxProc
    }

    frame $w.bot
    frame $w.print
    frame $w.top
    if {[string equal [tk windowingsystem] "x11"]} {
#	$w.bot configure -relief raised -bd 1
	$w.top configure -relief raised -bd 1
#	$w.print configure -relief raised -bd 1
    }
    pack $w.print -side bottom -anchor se
    pack $w.bot -side bottom -fill both
    pack $w.top -side top -fill both -expand 1

    # 2. Fill the top part with bitmap and message (use the option
    # database for -wraplength and -font so that they can be
    # overridden by the caller).

    option add *Dialog.msg.wrapLength 3i widgetDefault
    if {[string equal $tcl_platform(platform) "macintosh"]
	    || [string equal [tk windowingsystem] "aqua"]} {
	option add *Dialog.msg.font system widgetDefault
    } else {
	option add *Dialog.msg.font {Times 12} widgetDefault
    }

    label $w.msg -justify left -text $text
    pack $w.msg -in $w.top -side right -expand 1 -fill both -padx 3m -pady 3m
    if {[string compare $bitmap ""]} {
	if {([string equal $tcl_platform(platform) "macintosh"]
	     || [string equal [tk windowingsystem] "aqua"]) &&\
		[string equal $bitmap "error"]} {
	    set bitmap "stop"
	}
	label $w.bitmap -bitmap $bitmap
	pack $w.bitmap -in $w.top -side left -padx 3m -pady 3m
    }

    # 3. Create a row of buttons at the bottom of the dialog.
    set sec [clock seconds]
    set i 0
    foreach but $args {
	button $w.button$i -text $but -command [list set ::tk::Priv(apsbutton$sec) $i]
	if {$i == $default} {
	    $w.button$i configure -default active
	} else {
	    $w.button$i configure -default normal
	}
	grid $w.button$i -in $w.bot -column $i -row 0 -sticky ew \
		-padx 10 -pady 4
	grid columnconfigure $w.bot $i
	# We boost the size of some Mac buttons for l&f
	if {[string equal $tcl_platform(platform) "macintosh"]
	    || [string equal [tk windowingsystem] "aqua"]} {
	    set tmp [string tolower $but]
	    if {[string equal $tmp "ok"] || [string equal $tmp "cancel"]} {
		grid columnconfigure $w.bot $i -minsize [expr {59 + 20}]
	    }
	}
	incr i
    }
    global apsSilentDialog
    set apsSilentDialog 0
    checkbutton $w.button$i \
        -text Silent \
        -variable apsSilentDialog \
        -onvalue 1 -offvalue 0
    grid $w.button$i -in $w.bot -column $i -row 0 -sticky ew \
		-padx 10 -pady 4
    button $w.print.print -text "Print" -command "APSPrintText -text [list $text]" -font "-adobe-courier-medium-r-normal-*-10-*-*-*-*-*-*-*"
    pack $w.print.print
    # 4. Create a binding for <Return> on the dialog if there is a
    # default button.

    if {$default >= 0} {
	bind $w <Return> "
	[list $w.button$default] configure -state active -relief sunken
	update idletasks
	after 100
	set ::tk::Priv(apsbutton$sec) $default
	"
    }

    # 5. Create a <Destroy> binding for the window that sets the
    # button variable to -1;  this is needed in case something happens
    # that destroys the window, such as its parent window being destroyed.

    bind $w <Destroy> "set ::tk::Priv(apsbutton$sec) -1"

    # 6. Withdraw the window, then update all the geometry information
    # so we know how big it wants to be, then center the window in the
    # display and de-iconify it.

    wm withdraw $w
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]
    wm geom $w +$x+$y
    wm deiconify $w

    # 7. Set a grab and claim the focus too.

    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    catch {grab $w}
    if {$default >= 0} {
	focus $w.button$default
    } else {
	focus $w
    }
    catch {exec wmctrl -R $title -t -1}
    
    # 8. Wait for the user to respond, then restore the focus and
    # return the index of the selected button.  Restore the focus
    # before deleting the window, since otherwise the window manager
    # may take the focus away so we can't redirect it.  Finally,
    # restore any grab that was in effect.

    set value -1
    while {$value == -1} {
        if {(!$apsSilentDialog)} {
            bell
            bell
        }
        after 10000 "set ::tk::Priv(apsbutton$sec) -1"
        set ::tk::Priv(apsbutton$sec) -1
        vwait ::tk::Priv(apsbutton$sec)
        set value $Priv(apsbutton$sec)
    }
    catch {focus $oldFocus}
    catch {
	# It's possible that the window has already been destroyed,
	# hence this "catch".  Delete the Destroy handler so that
	# Priv(apsbutton$sec) doesn't get reset by it.

	bind $w <Destroy> {}
	destroy $w
    }
    if {[string compare $oldGrab ""]} {
        if {[string compare $grabStatus "global"]} {
            catch {grab $oldGrab}
        } else {
            catch {grab -global $oldGrab}
        }
    }
    return $value
}

proc APSMpLStartPSConditionLogging {args} {
    if {![llength [info commands blt::bgexec]]} {
	package require BLT
	global blt_library
	lappend auto_path $blt_library
    }
    set deviceList ""
    set fileName /tmp/[APSTmpString]
    APSStrictParseArguments "deviceList fileName"

    if [catch {APSDevSend \
                   -group LinacPS \
                   -operation SetCurrent \
                   -returnPVList 1 \
                   -deviceList $deviceList} setcurrentpvlist] {
        return -code error "APSMpLStartPSConditionLogging: $setcurrentpvlist"
    }
    if [catch {APSDevSend \
                   -group LinacPS \
                   -operation ReadCurrent \
                   -returnPVList 1 \
                   -deviceList $deviceList} readcurrentpvlist] {
        return -code error "APSMpLStartPSConditionLogging: $readcurrentpvlist"
    }
    if [catch {APSDevSend \
                   -group LinacPS \
                   -operation QueryConditioning \
                   -returnPVList 1 \
                   -deviceList $deviceList} queryconditioningpvlist] {
        return -code error "APSMpLStartPSConditionLogging: $queryconditioningpvlist"
    }
    set pvlist "$setcurrentpvlist $readcurrentpvlist $queryconditioningpvlist"

    APSAddToTempFileList ${fileName}.in
    if {[catch {exec sddsmakedataset -pipe=out -column=ControlName,type=string \
                    -data=[join $pvlist ","] | \
                    sddsprocess -pipe=in ${fileName}.in -edit=column,ReadbackUnits,ControlName,D} results]} {
        return -code error "APSMpLStartPSConditionLogging: $results"
    }

    global apsAPSMpLStartPSConditionLoggingAbortVariable
    if {[catch {blt::bgexec apsAPSMpLStartPSConditionLoggingAbortVariable sddslogger ${fileName}.in $fileName -sampleInterval=5 -time=180 &} results]} {
        return -code error "APSMpLStartPSConditionLogging: $results"
    }
}

proc APSMpLExaminePSConditionLogging {args} {
    set deviceList ""
    set fileName ""
    APSStrictParseArguments "deviceList fileName"
    
#Disabled until I can run myself to identify problem
    return

    global apsAPSMpLStartPSConditionLoggingAbortVariable
    set apsAPSMpLStartPSConditionLoggingAbortVariable 1
    if [catch {APSDevSend \
                   -group LinacPS \
                   -operation SetCurrent \
                   -returnPVList 1 \
                   -deviceList $deviceList} setcurrentpvlist] {
        return -code error "APSMpLExaminePSConditionLogging: $setcurrentpvlist"
    }
    if [catch {APSDevSend \
                   -group LinacPS \
                   -operation ReadCurrent \
                   -returnPVList 1 \
                   -deviceList $deviceList} readcurrentpvlist] {
        return -code error "APSMpLExaminePSConditionLogging: $readcurrentpvlist"
    }
    if [catch {APSDevSend \
                   -group LinacPS \
                   -operation QueryConditioning \
                   -returnPVList 1 \
                   -deviceList $deviceList} queryconditioningpvlist] {
        return -code error "APSMpLExaminePSConditionLogging: $queryconditioningpvlist"
    }
    set options ""
    set deviceListSpread ""
    foreach clist $deviceList setclist $setcurrentpvlist readclist $readcurrentpvlist qclist $queryconditioningpvlist {
        append options "\"-define=column,$clist,$setclist $readclist - abs\" \"-process=$clist,average,$clist\" \"-process=$qclist,sum,$qclist\" \"-process=$setclist,spread,${clist}Spread\" "
        append deviceListSpread "${clist}Spread "
    }
    if {[catch {eval exec sddsprocess ${fileName} -pipe=out $options \
                    | sdds2stream -pipe=in -param=[join $deviceList ","]} results1]} {
        return -code error "APSMpLExaminePSConditionLogging: $results1"
    }
    if {[catch {eval exec sddsprocess ${fileName} -pipe=out $options \
                    | sdds2stream -pipe=in -param=[join $queryconditioningpvlist ","]} results2]} {
        return -code error "APSMpLExaminePSConditionLogging: $results2"
    }
    if {[catch {eval exec sddsprocess ${fileName} -pipe=out $options \
                    | sdds2stream -pipe=in -param=[join ${deviceListSpread} ","]} results3]} {
        return -code error "APSMpLExaminePSConditionLogging: $results2"
    }
    set suspectpowersupplies ""
    set plotOptions ""
    foreach clist $deviceList result1 $results1 result2 $results2 result3 $results3 setclist $setcurrentpvlist readclist $readcurrentpvlist qclist $queryconditioningpvlist {
        if {($clist == "L3:BM2") || ($clist == "L3:BM4") || ($clist == "L3:AM1T")} {
            continue
        }
        #The average difference between the setpoint and the readback 
        #should be less than 40% than the difference between the min and max setpoints.
        #It also should have been conditioning for 30 seconds.
        set result3 [expr {$result3 * .40}]
        if {($result1 > $result3) || ($result2 < 6)} {
            lappend suspectpowersupplies $clist
            append plotOptions "-col=Time,(${setclist}) -graph=line,type=1 -topline=$clist -legend=specified=Setpoint -col=Time,(${readclist}) -graph=line,type=2 -legend=specified=Readback -col=Time,(${qclist}) -graph=line,type=0 -yscale=id=dcct -legend=specified=Conditioning -end "
        }
    }
    if {[string length $suspectpowersupplies]} {
        catch {eval exec sddsplot -tick=xtime $fileName $plotOptions &}
        if {[APSPEMTKDialog .warningDialog -text "These power supplies may not have conditioned correctly: $suspectpowersupplies"] == 1} {
            return -code error "APSMpLExaminePSConditionLogging: power supplies may not have conditioned correctly: $suspectpowersupplies"
        }
    }
}

