#!/bin/sh
# \
  exec oagwish "$0" "$@"

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath

# $Log: not supported by cvs2svn $
# Revision 1.42  2008/01/17 16:45:29  soliday
# Updated by putting setfacl command inside of catch statement.
#
# Revision 1.41  2006/11/15 19:06:26  shang
# changed the checking conditions per DIAG user' request
#
# Revision 1.40  2006/10/11 15:57:44  shang
# added warning message for checking feedforward and orbit correction are suspended before starting experiment.
#
# Revision 1.39  2006/09/28 15:17:45  shang
# fixed a typo.
#
# Revision 1.38  2006/04/07 19:24:16  shang
# added "Scan P1 Only" option and changed the plots per DIAG requests.
#
# Revision 1.37  2006/02/15 22:12:09  shang
# fixed a bug in displaying BM xray data.
#
# Revision 1.36  2005/10/12 09:05:27  emery
# Added crates number 4 and 5.
#
# Revision 1.35  2005/03/25 15:46:47  shang
# added displaying the file date on the plots and changed the order of plots requested
# by DIAG users
#
# Revision 1.34  2005/03/04 22:18:10  shang
# added gap values to plots and the actual gap value to the filename
#
# Revision 1.33  2004/10/27 16:58:26  shang
# removed BM data from gap review scan and removed the main directory for the
# file list display window to make the items shorter.
#
# Revision 1.32  2004/02/02 23:54:04  shang
# fixed a typo (affer-->after)
#
# Revision 1.31  2003/09/30 14:14:19  shang
# replace mswAve by msAve (mswAve takes too long to be stable)
#
# Revision 1.30  2003/09/27 04:27:04  shang
# changed the initial waiting time and the pause time between measurements
#
# Revision 1.29  2003/09/27 04:18:51  shang
# added P1 gain measurement
#
# Revision 1.28  2003/08/14 16:45:18  shang
# changed the log plot mode from x-axis to y-axis
#
# Revision 1.27  2003/08/14 15:48:26  shang
# added log option for plot gap-scan data
#
# Revision 1.26  2003/06/13 19:58:56  shang
# made more changes to plots and fixed the bug in comment that did not accept
# double quote
#
# Revision 1.25  2003/06/11 18:22:21  shang
# set pause after change to 10 seconds
#
# Revision 1.24  2003/05/28 19:41:48  shang
# fixed bugs in generating bugs, which was not solved before
#
# Revision 1.23  2003/05/28 14:56:35  shang
# fixed the bug in generating new file names
#
# Revision 1.22  2003/03/18 18:59:15  shang
# changed the index of new file name to be one greater than the last file
# in the directory
#
# Revision 1.21  2003/03/18 18:19:32  shang
# fixed the type error in ID gap name
#
# Revision 1.20  2003/03/18 17:53:55  shang
# modified getIDGapName proc, it now runs much faster than before
#
# Revision 1.19  2003/03/18 17:25:10  shang
# added gap scan and review
#
# Revision 1.18  2003/02/21 18:54:29  shang
# added plot features
#
# Revision 1.17  2003/01/22 19:35:05  shang
# set motors back to zero after experiment
#
# Revision 1.16  2003/01/22 19:26:39  shang
# added version information
#
# Revision 1.15  2003/01/22 19:21:57  shang
# fixed bugs and added more features for BM
#
# Revision 1.14  2003/01/16 16:00:44  emery
# Added variable closeGap to hold value of answer to question
# for use in the following IGGapCommand wait command.
#
# Revision 1.13  2003/01/16 15:46:09  emery
# Applied H. Shang's changes: added setfacl to data directory.
#
# Revision 1.12  2002/10/05 19:22:06  shang
# added more features and made it more convinient, requested by Diag group.
#
# Revision 1.11  2002/08/13 22:20:22  shang
# finished data review and fixed bugs in postProcessScan procedure
#
# Revision 1.10  2002/08/06 11:15:32  emery
# Fixed some things in post-processing, such as
# missing sddsxref commands, and in display data procedure
# variable conversion of drive to motorCrate.
#
# Revision 1.9  2002/08/02 20:22:58  shang
# added data Review and plot gain features
#
# Revision 1.8  2002/07/23 22:11:52  shang
# removed return statement in SetAndRestore
#
# Revision 1.7  2002/07/23 21:25:04  shang
# fixed arguments parsing problems
#
# Revision 1.6  2002/07/23 20:36:28  shang
# fixed a bug in RunIDScan{} proc
#
# Revision 1.5  2002/07/23 14:22:57  shang
# added third motor controller
#
# Revision 1.4  2002/02/05 15:32:31  shang
# move make dialy directory into RunScan procedure so that the dialy dir will only
# be created when data is taking.
#
# Revision 1.3  2002/02/05 04:34:11  emery
# Gives error message when directories cannot be created.
#

set CVSRevisionAuthor "\$Revision: 1.43 $ \$Author: soliday $"

APSApplication . -name SRXrayBPMCalibration -version "\$Revision: 1.43 $ \$Author: soliday $" \
  -overview {SRXrayBPMCalibration: calculate xray bpm gains }

set ControlStatus "Ready."
set args $argv
# Make application and status window widgets.  Returns 1 when completed.
proc MakeStatusWidget {widget args} {
    global ControlStatus
    set parent ""
    APSParseArguments {parent}
    set w $parent$widget
    APSScrolledStatus .status -parent $w -textVariable\
      ControlStatus -width 50 -packOption {-side top}  -withButtons 1
    return 1
}

proc SetMainStatus {text} {
    global ControlStatus
    set ControlStatus $text
    update
}

proc CreateBMIDWidget {parent} {
    global deviceType motorCrate IDlocation initialValue finalValue
    global numToAve postChangePause numSteps

    APSFrame .radio -parent $parent 
    set w1 $parent.radio.frame
    $w1 configure -relief flat -bd 0
    APSRadioButtonFrame .type -parent $w1 -label "deviceType" \
      -variable deviceType -buttonList {ID BM} -orientation vertical \
      -valueList {ID BM} -contextHelp "choose the device type ID or BM" \
      -packOption "-side left"
    
    APSFrame .button -parent $parent
    set w2 $parent.button.frame
    $w2 configure -relief flat -bd 0
    APSButton .motor -parent $w2 -text "Center Blades" -command "CenterBlades"
    APSButton .run -parent $w2 -text "Run" -command "RunScan"
  #  APSButton .display -parent $w2 -text "Review/Install ..." -command "DisplayScanData"
    APSButton .scan -parent $w2 -text "Gap Scan" -command "ScanGapDialogBox"  
}

proc ScanGapDialogBox {args} {
    global StartGap EndGap GapInterval GapScanPause
    APSDialogBox .gap -name "GAP SCAN" -width 50 \
	-okCommand {ScanGap} -cancelCommand ""
    APSLabeledEntry .start -parent .gap.userFrame \
      -label "Start Gap (mm): " -textVariable StartGap -width 30 \
      -contextHelp "the start value for gap scan."
    APSLabeledEntry .end -parent .gap.userFrame \
      -label "End Gap (mm):" -textVariable EndGap -width 30 \
      -contextHelp "Enter the end value for gap scan"
    APSLabeledEntry .interval -parent .gap.userFrame \
      -label "Interval (mm):" -textVariable GapInterval -width 30  \
      -contextHelp "Enter the interval for changing the gap step."
    APSLabeledEntry .pause -parent .gap.userFrame \
      -label "Pause between gap scan (s):" -textVariable GapScanPause -width 30  \
      -contextHelp "enter the pause time in seconds after each gap setting."
}
proc ScanGap {args} {
    global StartGap EndGap GapInterval beamlineSector sectorf IDlocation mainDir
    global motorCrate GapScanPause numToAve
 
    if {![string length $StartGap] || ![string length $EndGap] || ![string length $GapInterval]} {
        return -code error "Please proved the start and end gap and the gap interval for running gap scan!"
    }
    if ![string length $beamlineSector] {
        return -code error "the sector is not given!"
    }
    #verify conditions
    set errorMessage [VerifyConditions -sector $beamlineSector -deviceType ID] 
    while {$errorMessage!=""} {
        set answer [tk_dialog .dialog "Warning" "Error:\n$errorMessage \n\nChoose one of the following:\n\n \
                        Check conditions again and continue if no errors. \n\nPress Abort \
                        to stop the procedure\n\n \
                        Continue the procedure without checking the conditions" \
                        warning -1 CheckAgain Abort Continue-at-your-own-risk]
        case $answer {
            0 {
                set errorMessage [VerifyConditions -sector $beamlineSector -deviceType ID]
            }
            1 {
                return
            }
            2 {
                break
            }
        }
    }
    
    set steps [expr abs($EndGap-$StartGap)/$GapInterval]
    SetMainStatus "Get ID gap name..."
    if [catch {getIDGapName -sector $beamlineSector -location $IDlocation } gap_name] {
        return -code error $gap_name
    }
    SetMainStatus "Get the original value of $gap_name gap"
    if [catch {exec cavget -list=$gap_name:Gap -pend=30} originalValue] {
	return -code error $originalValue
    }
    if [string compare $originalValue "?"]==0 {
	return -code error "Unable to get the gap value of $gap_name"
    }
    SetMainStatus "Setting $gap_name gap to $StartGap"
    if [catch {IDGapCommand -action set -IDName $gap_name -gap $StartGap} result] {
	return -code error $result
    }
    if [catch {IDGapCommand -action wait -IDName $gap_name -gap $StartGap} result] {
	return -code error "$result"
    }
    SetMainStatus "Setting initial gap done."
    set gapname ${gap_name}:GapSet.VAL
    set inputDir $mainDir/inputFiles
    set date  [clock format [clock seconds] -format "%Y-%m%d"]
    set outputDir $mainDir/gap_scan/$date
    if ![file exist $outputDir] {
        if [catch {exec mkdir -p $outputDir} result] {
            SetMainStatus "Error making directory $outputDir: $result"
            return
        }
        #catch {exec setfacl -m mask:rwx $outputDir}
    }
    set tmpfile /tmp/[APSTmpString]
    if ![string length $motorCrate] {
        set motor 1
    } else {
        set motor $motorCrate
    }
    if [catch {GetBlades $beamlineSector} nameList] {
        return -code error $nameList
    }
    if [llength $nameList] {
        set fid [open $tmpfile.add w]
        puts $fid "SDDS1"
        puts $fid "&column name=ControlName, type=string,  &end"
        puts $fid "&column name=ReadbackName, type=string,  &end"
        puts $fid "&data mode=ascii, no_row_counts=1 &end"
        foreach pv $nameList {
            puts $fid "$pv $pv"
        }
        puts $fid " "
        close $fid
    }
    APSAddToTmpFileList -ID 1 -fileList "$tmpfile $tmpfile.mon $tmpfile.add"
    set name S${beamlineSector}IDGap-00
    set genName [APSNextGenerationedName -directory $outputDir -name $name -newFile 1 -separator -]
    set output $outputDir/$genName
    exec replaceText $inputDir/IDtemplate.mon $tmpfile \
      "-orig=<sector>,<sectorf>,<motor>" "-repl=$beamlineSector,$sectorf,$motor"
    if [string length $nameList] {
        if [catch {exec sddscombine $tmpfile $tmpfile.add -merge $tmpfile.mon1 -overwrite} result] {
            return -code error $result
        }
        exec mv $tmpfile.mon1 $tmpfile
    }
    global gapScanDone
    SetMainStatus "gapname=$gapname, gap_name=$gap_name"
    exec replaceText $inputDir/GapScanTemplate.exp $output.exp \
	"-orig=<monitorFile>,<lo>,<hi>,<points>,<numToAve>,<pause>,<gap_name>" \
	"-repl=$tmpfile,$StartGap,$EndGap,$steps,$numToAve,$GapScanPause,$gap_name"
    set gapScanDone 0
    after 5000
    APSExecLog .gapscan -width 80 -unixCommand "sddsexperiment $output.exp $output -verbose" -callback "set gapScanDone done" \
	-abortCallback "set gapScanDone abort" \
	-cancelCallback "set gapScanDone cancel"
    if !$gapScanDone {
	tkwait variable gapScanDone
    }
    SetMainStatus "put $gap_name gap back to its original value $originalValue"
    if [catch {IDGapCommand -action set -IDName $gap_name -gap $originalValue} result] {
	return -code error $result
    }
    if [catch {IDGapCommand -action wait -IDName $gap_name -gap $originalValue} result] {
	return -code error "$result"
    }
    SetMainStatus "experiment done"
}

proc GapScanReview {args} {
    set sectorVar ""
    global mainDir StartYear StartMonth StartDay Fileselection EndYear EndMonth EndDay
    APSParseArguments {sectorVar}
    set sector *
    if [string length $sectorVar] {
        global $sectorVar
        set sector [set $sectorVar]
    }
    if [catch {MakeListOfArchives -sector $sector -subDir gap_scan -type IDGap} files] {
        SetMainStatus "$files"
        return
    }
    global FileSelection
    set Fileselection ""
    APSScrolledListWindow .process -name "Gap Scan Selection" \
      -label "Select a scan data file" \
      -itemList $files -selectionVar Fileselection
    global fileList
    set fileList $files
    APSDialogBoxAddButton .view -parent .process -text "View Comment" -command "ListCommand -action view -dataDir $mainDir/gap_scan/"
    APSDialogBoxAddButton .add -parent .process -text "Edit Comment" -command "ListCommand -action add -dataDir $mainDir/gap_scan/"
    APSDialogBoxAddButton .delete -parent .process -text "Delete" -command "ListCommand -action delete -dataDir $mainDir/gap_scan/"
    tkwait variable Fileselection
    if ![string length $Fileselection] {
        SetMainStatus "ReviewScanData1: No files chosen!"
        return
    }
    global logPlot
    PlotGapScanData -filename $Fileselection -log $logPlot -dataDir $mainDir/gap_scan
    tkwait variable Fileselection
    PlotGapScanData -filename $Fileselection -log $logPlot -dataDir $mainDir/gap_scan
}

proc PlotGapScanData {args} {
    set filename ""
    set log 0
    set dataDir ""
    APSParseArguments {filename log dataDir}
    if ![file exist $dataDir/$filename] {
        return -code error "$dataDir/$filename does not exist"
    }
    set filename $dataDir/$filename
    set columnNames [exec sddsquery $filename -column]
    set index 0
    set requests ""
   # SetMainStatus "$columnNames"
    foreach name $columnNames {
        if [string match ID*:Gap $name] {
            set gapname $name
            break
        }
        incr index
    }
    foreach name $columnNames {
        if [string match *ID*NormAveSU $name] {
            append requests " -col=$gapname,$name" 
	    append requests " \"-topline=Blade data vs. Gap\""
        }
	if [string match *ID*ms* $name] {
	    append requests " -col=$gapname,$name" 
	    append requests " \"-topline=Position vs. Gap\""
	}
    }
    if [string length $requests] {
        if !$log {
            eval exec sddsplot $filename  -layout=1,4 -sep -legend \
              -graphic=sym,connect,scale=2 $requests &
        } else {
            eval exec sddsplot $filename -mode=y=log   \
              -layout=1,4 -sep -legend \
              -graphic=sym,connect,scale=2 $requests &
        }
    } else {
        return -code error "No blades data for plotting"
    }
}

proc CreateP0Widget {parent} {
    global Bfactor1 Bfactor2 Afactor1 Afactor2 

    APSFrame .entry -parent $parent
    set w $parent.entry.frame
    $w configure -relief flat -bd 0
    APSFrame .f1 -label "B:P0 factors" -parent $w -packOption "-side left"
    set w1 $w.f1.frame
    APSLabeledEntry .ff1 -parent $w1 -width 15 -label "factor1: " -textVariable Bfactor1(P0) \
      -contextHelp "calibration factor for S{sector}B:P0"
    APSLabeledEntry .ff2 -parent $w1 -width 15 -label "factor2: " -textVariable Bfactor2(P0) \
      -contextHelp "calibration factor for S{sector}B:P0"
    APSFrame .f2 -label "A:P0 factors" -parent $w 
    set w2 $w.f2.frame
    APSLabeledEntry .ffa1 -parent $w2 -width 15 -label "factor1: " -textVariable Afactor1(P0) \
      -contextHelp "calibration factor for S{sector+1}A:P0"
    APSLabeledEntry .ffa2 -parent $w2 -width 15 -label "factor2: " -textVariable Afactor2(P0) \
      -contextHelp "calibration factor for S{sector}A:P0"
    APSFrame .button -parent $parent 
    set w2 $parent.button.frame
    $w2 configure -relief flat -bd 0
    APSButton .motor -parent $w2 -text "Center Blades" -command {
        setResetButtons 0 P0
        if [catch {CenterIDBlades} result] {
            bell
            SetMainStatus "$result"
        }
        setResetButtons 1 P0
    }
    APSButton .run -parent $w2 -text "Run" -command "RunP0P1Scan P0"
 #   APSButton .display -parent $w2 -text "Review/Install ..." -command "DisplayP0ScanData"

}

proc CreateP1Widget {parent} {
    global Bfactor1 Bfactor2 Afactor1 Afactor2 

    APSFrame .entry -parent $parent
    set w $parent.entry.frame
    $w configure -relief flat -bd 0
    APSFrame .f1 -label "B:P1 factors" -parent $w -packOption "-side left"
    set w1 $w.f1.frame
    APSLabeledEntry .ff1 -parent $w1 -width 15 -label "factor1: " -textVariable Bfactor1(P1) \
      -contextHelp "calibration factor for S{sector}B:P1"
    APSLabeledEntry .ff2 -parent $w1 -width 15 -label "factor2: " -textVariable Bfactor2(P1) \
      -contextHelp "calibration factor for S{sector}B:P1"
    APSFrame .f2 -label "A:P1 factors" -parent $w 
    set w2 $w.f2.frame
    APSLabeledEntry .ffa1 -parent $w2 -width 15 -label "factor1: " -textVariable Afactor1(P1) \
      -contextHelp "calibration factor for S{sector+1}A:P1"
    APSLabeledEntry .ffa2 -parent $w2 -width 15 -label "factor2: " -textVariable Afactor2(P1) \
      -contextHelp "calibration factor for S{sector}A:P1"
    APSFrame .button -parent $parent 
    set w2 $parent.button.frame
    $w2 configure -relief flat -bd 0
    APSButton .motor -parent $w2 -text "Center Blades" -command {
        setResetButtons 0 P1
        if [catch {CenterIDBlades} result] {
            bell
            SetMainStatus "$result"
        }
        setResetButtons 1 P1
    }
    APSButton .run -parent $w2 -text "Run" -command "RunP0P1Scan P1"
 #   APSButton .display -parent $w2 -text "Review/Install ..." -command "DisplayP0ScanData"

}


proc RunScan {} {
    global deviceType motorCrate beamlineSector IDCloseGap IDlocation outputDir mainDir
    global initialValue finalValue numToAve postChangePause numSteps IDBackGap initialTimeout
    set inputDir $mainDir/inputFiles
        
    
    if ![string length $beamlineSector] {
        SetMainStatus "the beamline sector is not given!"
        bell
        return
    }
    if ![string length $deviceType] {
        SetMainStatus "the deviceType is not choosen!"
        bell
        return
    }

    if ![string length $motorCrate] {
        SetMainStatus "the motorCrate is not choosen!"
        bell
        return
    }
    if ![file exist $outputDir] {
        if [catch {exec mkdir -p $outputDir} result] {
            SetMainStatus "Error making directory $outputDir: $result"
            bell
        }
        #catch {exec setfacl -m mask:rwx $outputDir}
    }
    setResetButtons 0 BM_ID
                               
    if {[string compare $deviceType BM]==0} {
        RunBMScan -Sector $beamlineSector -motorCrate $motorCrate \
          -outputDir $outputDir -inputDir $inputDir \
          -initialValue $initialValue -finalValue $finalValue \
          -numToAve $numToAve -postChangePause $postChangePause \
          -numSteps $numSteps -timeout $initialTimeout
    } else {
        RunIDScan -Sector $beamlineSector -motorCrate $motorCrate -closegap $IDCloseGap \
          -backgap $IDBackGap -location $IDlocation -outputDir $outputDir \
          -inputDir $inputDir \
          -initialValue $initialValue -finalValue $finalValue \
          -numToAve $numToAve -postChangePause $postChangePause \
          -numSteps $numSteps -timeout $initialTimeout
    }
    setResetButtons 1 BM_ID
}

proc RunBMScan {args} {
    global scandone Comment
    set Sector ""
    set motorCrate ""
    set errorMessage ""
    set timeout 25
    APSParseArguments {Sector motorCrate outputDir inputDir initialValue finalValue\
                         postChangePause numToAve numSteps timeout}
    #verify conditions
    set scandone 0
    set errorMessage [VerifyConditions -sector $Sector -deviceType BM] 
    while {$errorMessage!=""} {
        set answer [tk_dialog .dialog "Warning" "Error:\n$errorMessage \
              \n\nChoose one of the following:\n\n \
               Check conditions again and continue if no errors. \n\nPress Abort \
                to stop the procedure\n\n \
                Continue the procedure without checking the conditions" \
                      warning -1 CheckAgain Abort Continue-at-your-own-risk]
        case $answer {
            0 {
                set errorMessage [VerifyConditions -sector $Sector -deviceType BM]
            }
            1 {
                return
            }
            2 {
                break
            }
        }
    }
    if [APSYesNoPopUp "Do you want to center BM blades before running experiment ?"] {
        if [catch {CenterBMBlades -sector $Sector -motor $motorCrate} result] {
            SetMainStatus "$result"
            bell
            return
        }
    }
    #SetUpStage -plane y
    if [APSYesNoPopUp "Restore the gain to 1 ?"] {
        if [catch {exec cavput -list=S${Sector}BM:P -list=1,2 -list=:ms:y:GainAO=1} result] {
            SetMainStatus "Problem centering BM stage: $result"
            return
        }
    }
     set answer [APSMultipleChoice [APSUniqueName .] -name Warning \
                    -type warning  \
                    -question "Please enure that feedforward and orbit correction are suspended before running experiment!\nPress Continue button to continue or Abort button to abort experiment" \
                    -returnList {Continue Abort} -labelList {Continue Abort} ]
    if {$answer=="abort"} {
        SetMainStatus "RunBMScan was aborted."
        return
    }
    if [APSYesNoPopUp "Run the experiment now ?"] {
        #setting the setpoints to initial changes given by initialValue
        set controlList [list SXDRV:${motorCrate}:M1MT SXDRV:${motorCrate}:M3MT]
        #get the original values of set points
        if [catch {exec cavget -pend=30 -list=[join $controlList ,]} origList] {
            SetMainStatus "RunBMScan: $origList"
            bell
            return
        }
        #setting the initial changes
        # SetMainStatus "The original settings are: "
	set setvalueList ""
        foreach val $origList pv $controlList {
            set value [expr $val + $initialValue]
            #   SetMainStatus "$pv=$val"
            lappend setvalueList $value
        }
	set command "SetAndRestore -setpointList {$controlList} -setvalueList {$setvalueList} -timeout $timeout -type motor"
        if [catch {eval $command} result] {
            SetMainStatus "RunBMScan1: $result"
            bell
            if ![APSYesNoPopUp "Setting failed, do you still want to continue"] {
                return
            }
        }
        #   SetMainStatus "$result"
        set final [expr $finalValue - $initialValue]
        set initial 0
        SetMainStatus "$final $initial"
        #create Experiment file -plane y
        set files [CreateExperimentFile -Sector $Sector -deviceType BM \
                     -motorCrate $motorCrate -plane y \
                     -initialValue $initial -finalValue $final \
                     -postChangePause $postChangePause -numToAve $numToAve \
                     -inputDir $inputDir -outputDir $outputDir -numSteps $numSteps ]
        if {$files==-2} {
            return
        }
        set input [lindex $files 0]
        set output [lindex $files 1]
        
        if [APSYesNoPopUp "run the experiment?"] {
            after 5000
            APSExecLog .jon -width 80 -unixCommand "sddsexperiment $input $output -verbose" \
                -callback {set scandone done} \
                -abortCallback {set scandone abort} \
                -cancelCallback {set scandone cancel}
            tkwait variable scandone
        }

        #SetMainStatus "Restoring original settings..."
        SetMainStatus "Set motors back to zero ..."
        set valList ""
        foreach pv $controlList val $origList {
            # SetMainStatus "$pv=$val"
            lappend valList 0
        }
	set command "SetAndRestore -setpointList {$controlList} -setvalueList {$valList} -timeout $timeout -type motor"
        if [catch {eval $command} result] {
            SetMainStatus "RunBMScan: $result"
            bell
            return
        }
        SetMainStatus "restoring done."
        switch $scandone {
            cancel {
                SetMainStatus "scan canceled."
            }
            abort {
                SetMainStatus "scan aborted".
            }
            done {
                SetMainStatus "scan done"
		set date [clock format [clock seconds] -format %Y-%m%d]
                if ![string length $Comment] {
                    set comment "Experiment took on $date"
                }
		set comment [APSMakeSafeQualifierString $Comment]
	#	SetMainStatus "$comment"
		regsub -all "\"" $comment "\\\"" $comment
                if [catch {postProcessScan -file $output -motorCrate $motorCrate \
                             -sector $Sector -deviceType BM -plane y -comment $comment} result] {
                    SetMainStatus "$result"
                    file delete $output.proc
                }
		SetMainStatus "postProcessScan done"
            }
        }
        
    }
    SetMainStatus "experiment done!"
}

proc VerifyConditions {args} {
    set message ""
    #verify beam current
    set sector ""
    set deviceType ""
    APSParseArguments {sector deviceType}
    if [catch {exec cavget -list=S-DCCT:CurrentM} current] {
        return $current
    }
    SetMainStatus "Beamline current=$current now"
    if {$current<=50} {
        set message "Low Current! should be greater than 50.\n"
    }
    #verify PS1 shutter is open
    set ps1 ""
    set PS1 EPS:[format %02ld $sector]:$deviceType:PS1:POS:OP
    if {[catch {exec cavget -list=$PS1} ps1] ||
        ![string compare $ps1 ?]} {
        set message "${message}Unable to link to PS1 shutter.\n"
    }
    if [string compare $ps1 Open] {
        set message "${message}PS1 shutter is not open!\n"
    }
    #check status of orbit controllaws and RT feedback:
    set Error [VerifyOrbitAndRT]
    if {$Error!=""} {
        foreach error $Error {
            set message "${message}${error}\n"
        }
    }
    return $message
}

proc VerifyOrbitAndRT {} {
    global runControlDescList runControlCheckList 
    set errorMessage ""
    
    if [catch {exec cavget -list=[join $runControlCheckList ,] -list=.RUN -pend=30} runValList] {
        lappend errorMessage "Unable to read value of run control pvs: $runValList"
        return $errorMessage
    }
    foreach val $runValList pv $runControlCheckList desc $runControlDescList {
        if {$val=="?"} {
            lappend errorMessage "Unable to read value of $pv.RUN"
            return $errorMessage
        }
        if $val {
            lappend errorMessage "$desc is running."
        }
    }
    if [catch {exec cavget -list=S:rfFreqControlLawRC.RUN -pend=30} rfFreqRunning] {
        lappend errorMessage "Unable to read value of S:rfFreqControlLawRC.RUN: $rfFreqRunning"
        return $errorMessage
    }
    if {$rfFreqRunning=="?"} {
        lappend errorMessage "Unable to read value of S:rfFreqControlLawRC.RUN"
        return $errorMessage
    } elseif {!$rfFreqRunning} {
        lappend errorMessage "RF frequency controllaw is not running."
    }
    return $errorMessage
}


proc setResetButtons {state tabframe} {
    global tabFrameWidgetList
    if ![string compare $tabframe BM_ID] {
        set win [lindex $tabFrameWidgetList 0]
    } elseif ![string compare $tabframe P0] {
        set win [lindex $tabFrameWidgetList 1]
    } elseif ![string compare $tabframe P1] {
        set win [lindex $tabFrameWidgetList 2]
    } else {
        SetMainStatus "setResetButtons: unknown tab frame entered."
        return
    }
    if $state {
        APSEnableButton $win.button.frame.run.button
        APSEnableButton $win.button.frame.motor.button
    } else {
        APSDisableButton $win.button.frame.run.button
        APSDisableButton $win.button.frame.motor.button
    }
}

proc CreateExperimentFile {args} {
    global sectorf ScanP1Only
    set Sector ""
    set deviceType ""
    set motorCrate ""
    set plane ""
    set initialValue ""
    set finalValue ""
    set postChangPause ""
    set numToAve ""
    set inputDir ""
    set outputDir ""
    set gap ""
    APSParseArguments {Sector deviceType motorCrate plane gap \
                         initialValue finalValue postChangePause numToAve inputDir outputDir numSteps}

    #following two files should exists in mainDir/inputFiles
    if {![file exists ${inputDir}/${deviceType}template.mon]} {
        SetMainStatus "template file (${deviceType}template.mon does not exist"
        bell
        return -2
    }
    set config /home/helios/oagData/sr/BPMStatus/config.sdds
    #create output file for sddsexperiment
    set nameList ""
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID XrayCalibration -fileList $tmpfile
    switch $deviceType {
        BM {
            set name S${Sector}${deviceType}${plane}-00
        }
        ID {
            set name S${Sector}${deviceType}Gap${gap}mm${plane}-00
            if [catch {GetBlades $Sector} nameList] {
                return -code error $nameList
            }
            if [llength $nameList] {
            set fid [open $tmpfile w]
                puts $fid "SDDS1"
                puts $fid "&column name=ControlName, type=string,  &end"
                puts $fid "&column name=ReadbackName, type=string,  &end"
                puts $fid "&data mode=ascii, no_row_counts=1 &end"
                foreach pv $nameList {
                    puts $fid "$pv $pv"
                }
                puts $fid " "
                close $fid
            }
        }
    }
    
    set genName [APSNextGenerationedName -directory $outputDir \
                     -name $name -newFile 1 -separator -]
    
    set tmpMon ${outputDir}/${genName}.mon
    set output ${outputDir}/${genName}
    if $ScanP1Only {
        set monFile ${inputDir}/${deviceType}P1template.mon
    } else {
        set monFile ${inputDir}/${deviceType}template.mon 
    }
    switch $deviceType {
        ID {
            exec replaceText $monFile $tmpMon \
                "-orig=<sector>,<sectorf>,<motor>" "-repl=$Sector,$sectorf,$motorCrate"
            if [llength $nameList] {
                if [catch {exec sddscombine $tmpMon $tmpfile -merge $tmpMon.1 -overwrite} result] {
                    return -code error $result
                }
                exec mv $tmpMon.1 $tmpMon
            }
            APSAddToTmpFileList -ID XrayCalibration -fileList $tmpMon~
        }
        BM {
            exec replaceText  $monFile  $tmpMon \
                "-orig=<sector>,<motor>" "-repl=$Sector,$motorCrate"
	    
        }
        default {
            SetMainStatus "Wrong device Type!"
            bell
            return
        }
    }
    
    #create input file for sddsexperiment
    set tmpInput ${outputDir}/${genName}.exp
    
    switch $plane {
        y {
            set firstMotor 1
            set secondMotor 3
        }
        x {
            set firstMotor 2
            set secondMotor 4
        }
        default {
            SetMainStatus "The plane should be x or y"
            bell
            return -2
        }
    }
    SetMainStatus "$output"
    if $ScanP1Only {
        set expFile ${inputDir}/ControllerP1ScanTemplate.exp
    } else {
        set expFile ${inputDir}/ControllerScanTemplate.exp
    }
    exec replaceText $expFile $tmpInput \
        "-orig=<monitorFile>,<numToAve>,<drive>,<motor1>,<motor2>,<lo>,<hi>,<points>,<pause>" \
        "-repl=$tmpMon,$numToAve,$motorCrate,$firstMotor,$secondMotor,$initialValue,$finalValue,$numSteps,$postChangePause"
    
    set inputOutput [list $tmpInput $output]
    return $inputOutput
}

proc RunIDScan {args} {
    global RunIDScanDone Comment ScanP1Only
    set Sector ""
    set motorCrate ""
    set errorMessage ""
    set closegap 15
    set backgap 16
    set timeout 50
    APSParseArguments {Sector motorCrate outputDir inputDir \
                         initialValue finalValue timeout\
                         postChangePause numToAve numSteps closegap backgap location}
    #verify conditions
    set errorMessage [VerifyConditions -sector $Sector -deviceType ID] 
    while {$errorMessage!=""} {
        set answer [tk_dialog .dialog "Warning" "Error:\n$errorMessage \n\nChoose one of the following:\n\n \
                        Check conditions again and continue if no errors. \n\nPress Abort \
                        to stop the procedure\n\n \
                        Continue the procedure without checking the conditions" \
                      warning -1 CheckAgain Abort Continue-at-your-own-risk]
        case $answer {
            0 {
                set errorMessage [VerifyConditions -sector $Sector -deviceType ID]
            }
            1 {
                return
            }
            2 {
                break
            }
        }
    }
    
    #get the ID Gap name
    if [catch {getIDGapName -sector $Sector -location $location} IDName] {
        SetMainStatus "$IDName"
        return
    }
    if [APSYesNoPopUp "Do you want to center ID blades before running experiment ?"] {
        if [catch {CenterIDBlades -IDName $IDName} result] {
            SetMainStatus "$result"
            bell
            if ![APSYesNoPopUp "$result, do you still want to continue"] {
                return
            }
        }
    }
    SetMainStatus "$IDName"
    # set oldGap, and wait for gap to stop moving, but first, one
    # should some other command run first.
    set closeGap 0
    if [APSYesNoPopUp "Close the gap to $closegap ?"] {
        if [catch {IDGapCommand -action set -IDName $IDName -gap $closegap} result] {
            SetMainStatus "RunIDScan: $result"
            bell
            return
        }
        # wait for gap to be closed.
        
        if [catch {IDGapCommand -action wait -IDName $IDName -gap $closegap} result] {
            SetMainStatus "RunIDScan: $result"
            bell
            return
        }
        set closeGap 1
    } 
    
    #SetUpStage -plane x and y
    if [APSYesNoPopUp "Restore gain to 1 ?"] {
	if $ScanP1Only {
	    if [catch {exec cavput -list=S${Sector}ID:P1 -list=:ms: -list=x,y -list=:GainAO=1} result] {
		bell
		SetMainStatus "RunIDScan: $result"
		return
	    }
	} else {
	     if [catch {exec cavput -list=S${Sector}ID:P -list=1,2 -list=:ms: -list=x,y -list=:GainAO=1} result] {
		bell
		SetMainStatus "RunIDScan: $result"
		return
	    }
	}
    }
    
    #start experiment
    set answer [APSMultipleChoice [APSUniqueName .] -name Warning \
                    -type warning  \
                    -question "Please enure that feedforward and orbit correction are suspended before running experiment!\nPress Continue button to continue or Abort button to abort experiment" \
                    -returnList {Continue Abort} -labelList {Continue Abort} ]
    if {$answer=="abort"} {
        SetMainStatus "RunIDScan was abort."
        return
    }
    #create Experiment file
    if [APSYesNoPopUp "Run the experiment now ?"] {
        foreach plane {x y} {
            if ![APSYesNoPopUp "Scanning $plane plane?"] {
                continue
            }
            set RunIDScanDone 0
            #wait for gap to be closed.
            if {$closeGap} {
                if [catch {IDGapCommand -action wait -IDName $IDName -gap $closegap} result] {
                    SetMainStatus "$result"
                    bell
                    return
                }
            }
            #setting the setpoints to initial changes given by initialValue
            switch $plane {
                y {
		    if $ScanP1Only {
			set controlList SXDRV:${motorCrate}:M1MT
		    } else {
			set controlList [list SXDRV:${motorCrate}:M1MT SXDRV:${motorCrate}:M3MT]
		    }
                }
                x {
		    if $ScanP1Only {
			set controlList SXDRV:${motorCrate}:M2MT
		    } else {
			set controlList [list SXDRV:${motorCrate}:M2MT SXDRV:${motorCrate}:M4MT]
		    }
                }
            }
            #get the original values of set points
            if [catch {exec cavget -pend=30 -list=[join $controlList ,]} origList] {
                SetMainStatus "RunBMScan: $origList"
                bell
                return
            }
            #setting the initial changes
            set setvalueList ""
            foreach val $origList {
                set value [expr $val + $initialValue]
                lappend setvalueList $value
            }
	    SetMainStatus "setting initial settings ..."
	    set command "SetAndRestore -setpointList {$controlList} -setvalueList {$setvalueList} -timeout $timeout -type motor"
	    
            if [catch {eval $command} result] {
                SetMainStatus "RunIDScan: $result"
                bell
                if ![APSYesNoPopUp "Setting failed, do you still want to continue"] {
                    return
                }
            }
	    SetMainStatus "setting values done."
            set final [expr $finalValue - $initialValue]
            set initial 0
            if [catch {exec cavget -list=$IDName:Gap -pend=30} gap] {
                SetMainStatus "$gap"
                return
            }
            set files [CreateExperimentFile -Sector $Sector -deviceType ID \
                         -motorCrate $motorCrate -plane $plane -gap [format %.0f $gap] \
                         -initialValue $initial -finalValue $final \
                         -postChangePause $postChangePause -numToAve $numToAve \
                         -inputDir $inputDir -outputDir $outputDir -numSteps $numSteps ]
            if {$files==-2} {
                return
            }
            set input [lindex $files 0]
            set output [lindex $files 1]
            after 5000
            APSExecLog .jon -width 80 -unixCommand "sddsexperiment $input $output -verbose" \
              -callback "set RunIDScanDone done" \
              -abortCallback "set RunIDScanDone abort" \
              -cancelCallback "set RunIDScanDone cancel"
            tkwait variable RunIDScanDone
            switch $RunIDScanDone {
                abort {
                    SetMainStatus "Scan Aborted!"
                }
                cancel {
                    SetMainStatus "Scan Canceled!"
                }
                done {
                    SetMainStatus "Scan done, processing..."
		    set date [clock format [clock seconds] -format %Y-%m%d]
                    if ![string length $Comment] {
                        set comment "Experiment took on $date"
                    }
		    set comment [APSMakeSafeQualifierString $Comment]
		    regsub -all "\"" $comment "\\\"" $comment
		   # SetMainStatus "$comment"
                    if [catch {postProcessScan -file $output -motorCrate $motorCrate -sector $Sector \
                                 -deviceType ID -plane $plane -gap $closegap -comment $comment} result] {
                        SetMainStatus "$result"
                        file delete $output.proc
                    }
                }
            }
            SetMainStatus "Restoring original settings ..."
	    set valList ""
            foreach pv $controlList val $origList {
                #SetMainStatus "$pv=$val"
	        lappend valList 0
            }
	    set command "SetAndRestore -setpointList {$controlList} -setvalueList {$valList} -timeout $timeout -type motor"
            if [catch {eval $command} result] {
                SetMainStatus "RunIDScan: $result"
                bell
                return
            }
	    SetMainStatus "Restoring original settings done"
        }
    }
    SetMainStatus "experiment done!"
}

proc getIDGapName {args} {
    global sectorf
    set sector ""
    set location ""
    set file /home/helios/oagData/sr/IDs/sectors.sdds
    APSParseArguments {sector location}
    if {$sector=="" || $location==""} {
        return -code error "wrong arguments passed to getIDGapName"
    }
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID getIDGapName -fileList $tmpfile.1
    if [catch {exec sddsprocess $file $tmpfile.1 -filter=col,Sector,[expr $sector - 0.5],[expr $sector + 0.5]} result ] {
	return -code error $result
    }
    set rows [exec sdds2stream $tmpfile.1 -rows=bare]
    if !$rows {
	return -code error "sector $sector is not found in $file."
    }
    set Downstream [exec sdds2stream $tmpfile.1 -column=Downstream]
    set Upstream [exec sdds2stream $tmpfile.1 -column=Upstream]
    set DownstreamLabel [exec sdds2stream $tmpfile.1 -column=DownstreamLabel]
    set UpstreamLabel [exec sdds2stream $tmpfile.1 -column=UpstreamLabel]
    switch $location {
	Downstream {
	    if $Downstream {
		if {[string length $DownstreamLabel] && [string compare $DownstreamLabel \"\"]!=0} {
		    set IDName ID[format %02ld $sector]${DownstreamLabel}
		    set sectorf [format %02ld $sector]${DownstreamLabel}
		} else {
		    set IDName ID[format %02ld $sector]
		    set sectorf [format %02ld $sector]
		}
	    } else {
		return -code error "No ID found in downstream!"
	    }
	}
	Upstream {
	    if $Upstream {
		if {[string length $UpstreamLabel] && [string compare $UpstreamLabel \"\"]!=0} {
		    set IDName ID[format %02ld $sector]${UpstreamLabel}
		    set sectorf [format %02ld $sector]${UpstreamLabel}
		} else {
		    set IDName ID[format %02ld $sector]
		    set sectorf [format %02ld $sector]
		}
	    } else {
		return -code error "No ID found in upstream!"
	    }
	}
	default {
	    return -code error  "ID location has to be Downstream or Upstream"
	}
    }
    return $IDName
}

proc IDGapCommand {args} {
    set gap 180
    set action ""
    set IDName ""
    APSParseArguments {action IDName gap}
    if {$action=="" || $IDName==""} {
        bell
        return -code error "wrong arguments passed to IDGapCommand"
    }
    set tolerance 0.01
    set retries 100
    #read the gap every 10 seconds
    set timeout 10
    switch $action {
        set {
            SetMainStatus "Setting ID gap to $gap"
            if [catch {exec cavput -list=${IDName}:GapSet.VAL=$gap} result] {
                return -code error $result
            }
            if [catch {exec cavput -list=${IDName}:Start=1} result] {
                return -code error $result
            }
        }
        wait {
            SetMainStatus "Waiting for setting ID gap ..."
            if [catch {exec cavget -pend=5 -list=${IDName}:GapSet.VAL} setGap] {
                return -code error "$setGap"
            }
            set upperLimit [expr $setGap+$tolerance]
            set lowerLimit [expr $setGap-$tolerance]
            set cawaitOptions -waitFor=${IDName}:Gap,lower=$lowerLimit,upper=$upperLimit
            while {$retries>0} {
                if {[catch {eval exec cawait -interval=1 -timelimit=$timeout \
                              $cawaitOptions} result]} {
                    if [catch {eval exec cavget -list=${IDName}:Gap -pend=30} gap] {
                        SetMainStatus "$gap"
                    }
                    SetMainStatus "Gap is $gap now"
                    #SetMainStatus "IDGapCommand: still waiting for ID gap closure"
                } else {
                    SetMainStatus "Gap setting done"
                    break
                }
                incr retries -1
            }
            if {$retries==0} {
                return -code error "The ID gap is not closed!"
            }
        }
    } 
    return 0
}

proc postProcessScan {args} {
    set file ""
    set motorCrate ""
    set sector ""
    set deviceType ""
    set plane ""
    set gap 0
    set comment ""
    APSStrictParseArguments {file deviceType motorCrate sector plane gap comment}
    
    set name [list deviceType motorCrate Sector plane]
    set value [list $deviceType $motorCrate $sector $plane]
    set type [list string short long string]
    set options ""
    foreach nm $name vv $value tt $type {
        if {[string compare $tt string]==0} {
            append options " -print=parameter,$nm,$vv"
        } else {
            append options " -define=parameter,$nm,$vv,type=$tt"
        }
    }
    #fit to obtain the gain
    switch $plane {
        x {
            set motor1 2
            set motor2 4
        }
        y {
            set motor1 1
            set motor2 3
        }
        default {
           # SetMainStatus "PostProcessScan: plane should be x or y"
            return -code error "PostProcessScan: plane should be x or y"
        }
    }
    if [catch {sdds load $file test} result] {
       # SetMainStatus "Error in reading $file, $result"
        return -code error "Error in reading $file, $result"
    }
    set colList [exec sddsquery -col $file]
    if [string match "*:P2:ms*" $colList] {
        set xbpmList {1 2}
    } else {
        set xbpmList 1
    }
    foreach xbpm $xbpmList {
        if {$xbpm==1} {
            set motor $motor1
        }
        if {$xbpm==2} {
            set motor $motor2
        }
        set fitfile $file.proc.fit$xbpm
        if [catch {exec sddspfit $file $fitfile \
                       -columns=SXDRV:${motorCrate}:M${motor}MT,S${sector}${deviceType}:P${xbpm}:msAve:${plane} } result] {
            #  SetMainStatus "$result SXDRV:${motorCrate}:M${motor}MT"
            return -code error "$result:  SXDRV:${motorCrate}:M${motor}MT"
        }
        set val1 [exec sdds2stream -par=Slope $fitfile]
        if {$val1<0} {
            set fc -1
        } else {
            set fc 1
        }
        #gain is always positive
        if [catch {set val2 [expr 1/$val1* $fc]} result] {
            if [APSYesNoPopUp "Error in PostProcessScan: $result, continue or exit ?"] {
                set val2 0
            } else {
             #   SetMainStatus "PostProcessScan: $result"
                return -code error "PostProcessScan: $result"
            }
        }
        lappend values $val2
        SetMainStatus "PostProcessScan: motor=$motor slope=$val1"
        if {$val2>10} {
            #  SetMainStatus "Gain=$val2 is too big, quite processing data!"
           # return -code error "Gain=$val2 is too big, quite processing data!"
        }
        set point S${sector}${deviceType}:P${xbpm}:ms:${plane}:GainAO
        append options " -define=parameter,${point},${val2},type=double"
    }
    
    if [file exist $file.proc] {
        set pars [exec sddsquery $file.proc -par]
        if [lsearch -exact $pars comment]>=0 {
            set comment "[exec sdds2stream $file.proc -par=comment] $comment"
        }
    }
    if [string length $comment] {
        set comment [APSMakeSafeQualifierString $comment]
        regsub -all "\"" $comment "\\\"" comment
        append options " \"-reprint=par,comment,$comment\""
    }
    #SetMainStatus "$comment"
    
    if [catch {eval exec sddsprocess $file $file.proc $options} result] {
        SetMainStatus "Postprocessscan: $result"
        return -code error "Postprocessscan: $result"
    }
    SetMainStatus "Postprocessing done!"
    return
}

proc getScanDataFiles {args} {
    set dataDir /home/helios/oagData/sr/bpmCalibration/xray/data
  #  set dataDir /home/oxygen/SHANG/test/oag/xraycal/
    set bpm ""
    APSParseArguments {bpm}
    if {![string length $bpm]} {
        return
    }
    if ![string compare $bpm P0] {
        if [catch {glob -nocomplain $dataDir/p0/*/S*${bpm}*-??.proc} files] {
            APSAlertBox [APSUniqueName .] -errorMessage $files
            return
        }
    } else {
        if [catch {glob -nocomplain $dataDir/*/S*${bpm}*-??.proc} files] {
            APSAlertBox [APSUniqueName .] -errorMessage $files
            return
        }
    }
    return [lsort -ascii $files]
}

proc displayFile {args} {
    set filename ""
    set values ""
    set setpoints ""
    set P1Gain ""
    set type ""
    set width 80
    APSParseArguments {filename values setpoints type width P1Gain}
    set w .[APSUniqueName printout]
    APSFileDisplayWindow $w -fileName $filename -width 80 -printCommand "enscript -r" -width $width
    if {![string compare $type P0] || ![string compare $type P1]} {
        set command "InstallP0P1GainAO -pv $setpoints -average $values -P1Gain $P1Gain -bpmType $type"
        APSDialogBoxAddButton .install1 -parent $w  -text "Install $type Gain..." \
          -command  $command \
          -contextHelp "click to install P0/P1 gain"
    } else {
        set point1 [lindex $setpoints 0]
        set val1 [lindex $values 0]
        set point2 [lindex $setpoints 1]
        set val2 [lindex $values 1]
        APSDialogBoxAddButton .install1 -parent $w  -text "Install P1 Gain..." \
          -command "InstallGainAO $point1 $val1" \
          -contextHelp "click to install [lindex $setpoints 0]"
        APSDialogBoxAddButton .install2 -parent $w  -text "Install P2 Gain..." \
          -command "InstallGainAO $point2 $val2" \
          -contextHelp "click to install [lindex $setpoints 1]" 
        APSDialogBoxAddButton .installAll -parent $w  -text "Install Both..." \
          -command "InstallGainAO $point1 $val1; InstallGainAO $point2 $val2" \
          -contextHelp "click to install $setpoints "
    }
}

proc InstallGainAO {point value} {
    if [APSYesNoPopUp "Confirm: Set $point to $value ?"] {
        if [catch {exec cavput -list=$point=$value} result] {
            SetMainStatus "$result"
            return
        }
    }
}

proc InstallP0P1GainAO {args} {
    set bpmType ""
    set pv ""
    set average ""
    set P1Gain ""
    APSParseArguments {pv average P1Gain bpmType}
    if ![string compare $bpmType P1] {
        if ![string length $P1Gain] {
            return -code error "The gain value is not provided!"
        }
        set answer [tk_dialog .dialog "Choice" "Set $pv to average or P1 gain?" \
                      warning -1 Average P1]
        if !$answer {
            set value $average
        } else {
            set value $P1Gain
        }
    } else {
        set value $average
    }
    if [APSYesNoPopUp "Confirm: Set $pv to $value ?"] {
        if [catch {exec cavput -list=$pv=$value} result] {
            SetMainStatus "$result"
            return
        }
    }
}

proc CenterBlades {} {
    global deviceType beamlineSector motorCrate
    if ![string length $beamlineSector] {
        SetMainStatus "CenterBlades: the beam line sector is not given.!"
        bell
        return
    }
    if ![string length $deviceType] {
        SetMainStatus "CenterBlades: the device type ID or BM is not choosen.!"
        bell
        return
    }
    setResetButtons 0 BM_ID
    switch $deviceType {
        BM {
            if [catch {CenterBMBlades -sector $beamlineSector -motor $motorCrate}  result] {
                SetMainStatus "CenterBlades3: $result"
                setResetButtons 1 BM_ID
                bell
                return
            }
        }
        ID {
            if [catch {CenterIDBlades}  result] {
                SetMainStatus "CenterBlades2: $result"
                setResetButtons 1 BM_ID
                bell
                return
            }
        }
    }
    SetMainStatus "Center Blades done."
    setResetButtons 1 BM_ID
}

proc CenterBMBlades {args} {
    set sector ""
    set motor ""
    APSParseArguments {sector motor}

    if ![string length $sector] {
        return -code error "CenterBMBlades: the beam line sector is not given."
    }
    if ![string length $motor] {
        return -code error "CenterBMBlades: please choose the motorCrate before center BM blades."
    }

    set readback [list S${sector}BM:P1:msAve:y S${sector}BM:P2:msAve:y]
    set variable [list SXDRV:${motor}:M1MT SXDRV:${motor}:M3MT]

    set answer [tk_dialog .dialog "warning" "Center the motors?" \
                  warning -1 Yes No]
    while !$answer {
        if [catch {exec cavget -pend=30 -list=[join $readback ,]} checkList] {
            return -code error "CenterBMBlades: $checkList"
        }
        if [catch {exec cavget -pend=30 -list=[join $variable ,]} origList] {
            return -code error "CenterBMBlades: $checkList"
        }
        SetMainStatus "The beam position is:"
        foreach value $checkList pv $readback setpv $variable orig $origList {
            SetMainStatus "$pv=$value"
            if [string compare $orig "?"]==0 {
                return -code error "unable to get the initial value of $setpv"
            }
            set val [expr $value + $orig]
            lappend comm $setpv=$val
            if {$value>0.5 || $value<-0.5} {
                if ![APSYesNoPopUp "The beam position is out of range, do you still want to continue?"] {
                    return -code error "CenterBMBlades: the beam position is out of range."
                }
            }
        }
        SetMainStatus "centering motors as following:"
        foreach com $comm {
            SetMainStatus "$com"
        }
        if [catch {exec cavput -pend=30 -list=[join $comm ,]} result] {
            return -code error "CenterBMBlades: $result"
        }
        set answer [tk_dialog .dialog "warning" "Center the motors again?" \
                      warning -1 Yes No]
        if !$answer {
            continue
        } else {
            break
        }
    }
    return 0
}


proc CenterIDBlades {args} {
    global motorCrate beamlineSector IDCloseGap IDlocation IDBackGap
    
    if ![string length $beamlineSector] {
        return -code error "CenterIDBlades: beam line sector is not given"
    }
    if ![string length $motorCrate] {
        return -code error "CenterIDBlades: the motor crate is not chosen"
    }
    if ![string length $IDCloseGap] {
        return -code error "CenterIDBlades: the gap close value is not given"
    }
    if ![string length $IDBackGap] {
        return -code error "CenterIDBlades: the gap open value is not given"
    }
    if ![string length $IDlocation] {
        return -code error "CenterIDBlades: the gap location is not chosen"
    }
    set IDName ""
    APSParseArguments {IDName}
    set planeL [list x y]
    #get the ID gap name
    if ![string length $IDName] {
        if [catch {getIDGapName -sector $beamlineSector -location $IDlocation} IDName] {
            return -code error "CenterIDBlades1: $IDName"
        }
    }
    SetMainStatus "$IDName"
    
    #1. close gap
    set answer [tk_dialog .dialog "warning" "Do you want to close the gap to $IDCloseGap?" \
                  warning -1 Yes Abort No-and-Continue]
    case $answer {
        0 {
            if [catch {IDGapCommand -action set -IDName $IDName -gap $IDCloseGap} result] {
                return -code error "CenterIDBlades5: $result"
            }
            #SetMainStatus "waiting for gap closing..."
            if [catch {IDGapCommand -action wait -IDName $IDName -gap $IDCloseGap} result] {
                return -code error "CenterIDBlades6: $result"
            }
        }
        1 {
            return -code error "CenterIDBlades: abort close gap"
        }
    }
    
    #2. center motors
    set answer [tk_dialog .dialog "warning" "Do you want to center the motors?" \
                  warning -1 Yes Abort No-and-Continue]
    case $answer {
        0 {
            if [catch {CenterMotors -sector $beamlineSector -motor $motorCrate} result] {
                return -code error "CenterIDBlades: $result"
            }
        }
        1 {
            return -code error "CenterIDBlades: abort centering motors"
        }
    }
}

proc CenterMotors {args} {
    set sector ""
    set motor ""
    APSParseArguments {sector motor}
    if {![string length $sector] || ![string length $motor]} {
        return -code error "CenterMotors: the beam line sector is not given or the motor crate is not choosed."
    }

    #for P1 --- motor1 (1,2) , P2 ---- motor2 (3,4)
    set variablex [list SXDRV:${motor}:M2MT SXDRV:${motor}:M4MT]
    set readbackx [list S${sector}ID:P1:msAve:x S${sector}ID:P2:msAve:x]
    set variabley [list SXDRV:${motor}:M1MT SXDRV:${motor}:M3MT]
    set readbacky [list S${sector}ID:P1:msAve:y S${sector}ID:P2:msAve:y]

    set answer 1
    while $answer {
        if [catch {exec cavget -pend=30 -list=[join $readbackx ,]} checkxList] {
            return -code error "CenterMotors1: $checkList"
        }
        if [catch {exec cavget -pend=30 -list=[join $variablex ,]} origxList] {
            return -code error "CenterMotors2: $checkList"
        }
        if [catch {exec cavget -pend=30 -list=[join $readbacky ,]} checkyList] {
            return -code error "CenterMotors3: $checkList"
        }
        if [catch {exec cavget -pend=30 -list=[join $variabley ,]} origyList] {
            return -code error "CenterMotors4: $checkList"
        }
        
        SetMainStatus "The beam position is as following:"
        foreach value $checkxList pv $readbackx setpv $variablex orig $origxList {
            SetMainStatus "$pv=$value"
            if [string compare $orig "?"]==0 {
                return -code error "unable to get initial value of $setpv"
            }
            set val [expr $orig - $value]
            lappend comm $setpv=$val
            if {$value>0.5 || $value<-0.5} {
                if ![APSYesNoPopUp "The beam position is out of range,\ndo you still want to continue?"] {
                    return -code error "CenterMotors: the beam position is out of range."
                }
            }
        }
        foreach value $checkyList pv $readbacky setpv $variabley orig $origyList {
            SetMainStatus "$pv=$value"
            if [string compare $orig "?"]==0 {
                return -code error "unable to get initial value of $setpv"
            }
            set val [expr $value + $orig]
            lappend comm $setpv=$val
            if {$value>0.5 || $value<-0.5} {
                if ![APSYesNoPopUp "The beam position is out of range, \ndo you still want to continue?"] {
                    return -code error "CenterMotors: the beam position is out of range."
                }
            }
        }
        SetMainStatus "Center the motors as following:"
        foreach com $comm {
            SetMainStatus "$com"
        }
        if [catch {exec cavput -pend=30 -list=[join $comm ,]} result] {
            return -code error "TransferBlades5: $result"
        }
        set again [tk_dialog .dialog "warning" "Center the motors again?" \
                     warning -1 Yes No]
        if !$again {
            continue
        } else {
            break
        }
    }
    return 0
}

#transfer ID blades  
proc GetBlades {Sector} {
    set ID1 S${Sector}ID:P1
    set ID2 S${Sector}ID:P2
    set configFile /home/helios/oagData/sr/BPMStatus/config.sdds
    
    set deviceName [APSGetSDDSColumn -fileName $configFile -column DeviceName -page 0]
    set deviceType [APSGetSDDSColumn -fileName $configFile -column DeviceType -page 0]
    
    set i1 [lsearch -exact $deviceName $ID1]
    set i2 [lsearch -exact $deviceName $ID2]
    if {$i1==-1 || $i2==-1} {
        return -code error "TransferBlades: $ID1 or $ID2 not found in $configFile"
    }
    set type1 [lindex $deviceType $i1]
    set type2 [lindex $deviceType $i2]
    set bladesList ""
    if ![string compare $type1 "Xray ABCD"] {
        foreach type {A C B D} {
            lappend bladesList S${Sector}ID:P1:${type}:NormAveSU
        }
    } elseif ![string compare $type1 "Xray ABEF"] {
        foreach type {A E B F} {
            lappend bladesList S${Sector}ID:P1:${type}:NormAveSU
        }
    } else {
        return -code error "TransferBlades: unknown device type!"
    }
    if ![string compare $type2 "Xray ABCD"] {
         foreach type {A C B D} {
             lappend bladesList S${Sector}ID:P2:${type}:NormAveSU
        }
    } elseif ![string compare $type2 "Xray ABEF"] {
        foreach type {A E B F} {
            lappend bladesList S${Sector}ID:P2:${type}:NormAveSU
        }
    } else {
        return -code error "TransferBlades: unknown device type!"
    }
    return $bladesList
}

proc TransferBlades {Sector} {

    set ID1 S${Sector}ID:P1
    set ID2 S${Sector}ID:P2
    set configFile /home/helios/oagData/sr/BPMStatus/config.sdds

    set deviceName [APSGetSDDSColumn -fileName $configFile -column DeviceName -page 0]
    set deviceType [APSGetSDDSColumn -fileName $configFile -column DeviceType -page 0]
    
    set i1 [lsearch -exact $deviceName $ID1]
    set i2 [lsearch -exact $deviceName $ID2]
    if {$i1==-1 || $i2==-1} {
        return -code error "TransferBlades: $ID1 or $ID2 not found in $configFile"
    }
    set type1 [lindex $deviceType $i1]
    set type2 [lindex $deviceType $i2]
    if ![string compare $type1 "Xray ABCD"] {
        set suffix1 [list A B C D]
    } elseif ![string compare $type1 "Xray ABEF"] {
        set suffixe1 [list A B E F]
    } else {
        return -code error "TransferBlades: unknown device type!"
    }
    if ![string compare $type2 "Xray ABCD"] {
        set suffix2 [list A B C D]
    } elseif ![string compare $type2 "Xray ABEF"] {
        set suffix2 [list A B E F]
    } else {
        return -code error "TransferBlades: unknown device type!"
    }

    #get offset bpm name
    if [catch {exec cavget -pend=30 -list=$ID1 \
                 -list=: -list=[join $suffix1 ,] -list=:OffsetP -dry} ID1List] {
        return -code error "TransferBlades1:  $ID1List"
    }
    #SetMainStatus "$ID1List"
    if [catch {exec cavget -pend=30 -list=$ID2 \
                 -list=: -list=[join $suffix2 ,] -list=:OffsetP -dry} ID2List] {
        return -code error "TransferBlades2: $ID2List"
    }
    #SetMainStatus "$ID2List"
    #read normalized value
    if [catch {exec cavget -pend=30 -list=$ID1 \
                 -list=: -list=[join $suffix1 ,] -list=:CorrectedM} dataID1List] {
        return -code error "TransferBlades3: $dataID1List"
    }
    #SetMainStatus "$dataID1List"
    if [catch {exec cavget -pend=30 -list=$ID2 \
                 -list=: -list=[join $suffix2 ,] -list=:CorrectedM} dataID2List] {
        return -code error "TransferBlades4: $dataID2List"
    }
    #SetMainStatus "$dataID2List"
    
    #set offset to normalized value
    set pvList $ID1List
    set dataList $dataID1List
    foreach pv $ID2List bp $dataID2List {
        lappend pvList $pv
        lappend dataList $bp
    }
    SetMainStatus "transferring ID blades as following:"
    foreach pv $pvList datum $dataList {
        lappend commandOptList $pv=$datum
        SetMainStatus "$pv=$datum"
    }
    if [catch {exec cavput -pend=30 -list=[join $commandOptList ,]} result] {
        return -code error "TransferBlades5: $result"
    }
}

proc RunP0P1Scan {type} {
    global beamlineSector IDCloseGap IDBackGap outp0Dir outp1Dir mainDir scanDone outputDir
    global initialValue finalValue numToAve postChangePause numSteps IDlocation
    global Bfactor1 Bfactor2 Afactor1 Afactor2 tabFrameWidgetList initialTimeout

    
    if ![string length $beamlineSector] {
        SetMainStatus "RunP0P1Scan: the beamline sector is not given."
        bell
        return
    }
    switch $type {
        P0 {
            set outDir $outp0Dir
        }
        P1 {
            set outDir $outp1Dir
        }
        default {
            return -code error "The bpm type should be P0 or P1!"
        }
    }
    if ![file exist $outDir] {
        if [catch {exec mkdir -p $outDir} result] {
            SetMainStatus "Error making directory $outDir: $result"
            bell
        }
        #catch {exec setfacl -m mask:rwx $outDir}
    }
    #verify condition
    set errorMessage [VerifyConditions -sector $beamlineSector -deviceType ID]
    set win [lindex $tabFrameWidgetList 1]
    setResetButtons 0 $type
    
    while {$errorMessage!=""} {
        set answer [tk_dialog .dialog "Warning" "Error:\n$errorMessage \
              \n\nChoose one of the following:\n\n \
               Check conditions again and continue if no errors. \n\nPress Abort \
               to stop the procedure\n\n \
               Continue the procedure without checking the conditions" \
                      warning -1 CheckAgain Abort Continue-at-your-own-risk]
        case $answer {
            0 {
                set errorMessage [VerifyConditions -sector $beamlineSector -deviceType ID]
            }
            1 {
                setResetButtons 1 $type
                return
            }
            2 {
                break
            }
        }
    }
    
    set IDnames ""
    #get the ID Gap name
    if [catch {getIDGapName -sector $beamlineSector -location $IDlocation} IDName] {
        SetMainStatus "$IDName"
        setResetButtons 1 $type
        return
    }
    SetMainStatus "$IDName"
    # set oldGap, and wait for gap to stop moving, but first, one
    # should some other command run first.
    if [APSYesNoPopUp "close the gap to $IDCloseGap?"] {
        if [catch {IDGapCommand -action set -IDName $IDName -gap $IDCloseGap} result] {
            SetMainStatus "$result"
            setResetButtons 1 $type
            bell
            return
        }
        # wait for gap to be closed.
        if [catch {IDGapCommand -action wait -IDName $IDName -gap $IDCloseGap} result] {
            SetMainStatus "$result"
            bell
            setResetButtons 1 $type
            return
        }
    }

    #set P0 gain to 1
    set sector1 [expr $beamlineSector +1]
    set bpmName [list S${beamlineSector}B:$type S${sector1}A:$type]
    set names [list S${beamlineSector}B$type S${sector1}A$type]
    if [APSYesNoPopUp "restoring $type gain to 1?"] {
        if [catch {exec cavput -list=[join $bpmName ,] -list=:ms: -list=x,y \
                     -list=:GainAO=1 -pend=5} result] {
            SetMainStatus "RunP0P1Scan: $result"
            setResetButtons 1 $type
            return
        }
    }
    
    set inputMon ${mainDir}/inputFiles/P0template.mon
    set inputfile ${mainDir}/inputFiles/P0template.exp
    
    set sectorf [string range $IDName 2 end]
    
    set factorB [list $Bfactor1($type) $Bfactor2($type)]
    set factorA [list $Afactor1($type) $Afactor2($type)]
    set factors [list $factorB $factorA]
    set j 0
    set answer [APSMultipleChoice [APSUniqueName .] -name Warning \
                    -type warning  \
                    -question "Please enure that feedforward and orbit correction are suspended before running experiment!\nPress Continue button to continue or Abort button to abort experiment" \
                    -returnList {Continue Abort} -labelList {Continue Abort} ]
    if {$answer=="abort"} {
        SetMainStatus "RunP0P1Scan was aborted."
        return
    }
    if [APSYesNoPopUp "run experiment now?"] {
        foreach name $bpmName factor $factors nm $names {
            foreach plane {x y} {
                if ![APSYesNoPopUp "Scanning $name $plane plane?"] {
                    continue
                }
                #setting the setpoints to initial changes given by initialValue
                
                set control ${name}:ms:${plane}
                #get the original values of set points
                if [catch {exec cavget -pend=30 -list=${control}:SetpointAO } orig] {
                    SetMainStatus "RunP0P1Scan: $orig"
                    bell
                    setResetButtons 1 $type
                    return
                }
                if [string compare $orig "?"]==0 {
                    return -code error "unable to get initial value of ${control}:SetpointAO "
                }
                #setting the initial changes
                set setvalue [expr $orig + $initialValue]
		if [catch {exec cavput -list=${control}:SetpointAO=$setvalue -pend=30} result] {
                    return -code error $result
                }
                SetMainStatus "setting $control:SetpointAO=$setvalue"
                SetMainStatus "Waiting for $initialTimeout seconds for initial setting..."
                after [expr $initialTimeout * 1000]
                set final [expr $finalValue - $initialValue]
                set initial 0
                #SetMainStatus "$outp0Dir"
                set file ${nm}Gap${IDCloseGap}${plane}-00
		set genname ${nm}Gap${IDCloseGap}${plane}-00
                
                set genName [APSNextGenerationedName -directory $outDir -name $genname -newFile 1 -separator -]
		set genName $outDir/$genName
                exec replaceText $inputMon ${genName}.mon \
                  "-orig=<sectorf>,<sector>,<sector1>" \
                  "-repl=$sectorf,$beamlineSector,$sector1"
                
                #run experiment (scan data)
                set scanDone 0
                after 5000
                #data is collected into $genName
                set macro -macro=measFile=$genName.mon,bpm=$name,numToAve=$numToAve,plane=$plane,initialValue=$initial,finalValue=$final,steps=$numSteps,postChange=$postChangePause
                APSExecLog .jon -width 80 -unixCommand "sddsexperiment $inputfile $genName -verbose $macro" \
                  -callback "set scanDone done" \
                  -abortCallback "set scanDone abort" \
                  -cancelCallback "set scanDone cancel"
                if !$scanDone {
                    tkwait variable scanDone
                }
                switch $scanDone {
                    done {
                        postProcessScanP0P1 -type $type -file $genName -bpmName $name -plane $plane \
                          -factors $factor -sector $beamlineSector -sectorf $sectorf
                    }
                    abort {
                        SetMainStatus "Scan Aborted!"
                    }
                    cancel {
                        SetMainStatus "Scan Canceled!"
                    }
                }
                SetMainStatus "Restoring original settings ..."
               # foreach pv $control val $setvalue {
                #    SetMainStatus "$pv=$val"
                #}
                if [catch {exec cavput -list=${control}:SetpointAO=$orig } result] {
                    SetMainStatus "RunP0P1Scan: $result"
                    bell
                    setResetButtons 1 $type
                    if ![APSYesNoPopUp "Setting failed, do you still want to continue"] {
                        setResetButtons 1 $type
                        return
                    }
                }
		SetMainStatus "Restore original settings done."
                if {![string compare $scanDone abort] || ![string compare $scanDone cancel]} {
                    setResetButtons 1 $type
                    return
                }
            }
        }                
    }
    setResetButtons 1 $type
    SetMainStatus "experiment done!"
}

proc postProcessScanP0P1 {args} {
    set file ""
    set bpmName ""
    set plane ""
    set factors ""
    set sector ""
    set sectorf ""
    set type ""
    APSParseArguments {file bpmName plane factors sector sectorf type}
    if ![string length $type] { return -code error "no type (P0 or P1) provided!" }
    set factor1 [lindex $factors 0]
    set factor2 [lindex $factors 1]
    set ID1 S${sector}ID:P1:msAve:${plane}
    set ID2 S${sector}ID:P2:msAve:${plane}
    lappend options "-define=col,${bpmName}:P1mapped:${plane},$ID1 $factor1 /,type=double"
    lappend options "-define=col,${bpmName}:P2mapped:${plane},$ID2 $factor2 /,type=double"
    lappend options "-process=${bpmName}:ms:${plane}:SetpointAO,average,xOffset"
    set name [list bpmName plane sector IDName]
    set value [list $bpmName $plane $sector ID${sectorf}]
    set type [list string string long string]
    foreach nm $name vv $value tt $type {
        if {[string compare $tt string]==0} {
            lappend options "-print=parameter,$nm,$vv"
        } else {
            lappend options "-define=parameter,$nm,$vv,type=$tt"
        }
    }

    if [catch {eval exec sddsprocess $file $file.proc $options -nowarning} result] {
        SetMainStatus "$result"
        bell 
        return
    } 
    SetMainStatus "postprocessing done!"
}


proc DisplayP0P1ScanData {type} {
    global Fileselection
    set files [getScanDataFiles -bpm $type]
    if ![string length $files] {
        SetMainStatus "No files found!"
        bell
        return
    }
    set Fileselection ""
    APSScrolledListWindow .process -name "Scan Data Selection for $type xray bpm" \
      -label "Select a scan data file" \
      -itemList $files -selectionVar Fileselection
    tkwait variable Fileselection
    if ![string length $Fileselection] {
        SetMainStatus "No files chosen!"
        return
    }
    #SetMainStatus "$Fileselection  is chosed"
    if ![file exist $Fileselection] {
        SetMainStatus "$Fileselection does not exist"
        return
    }
    if [catch {sdds load $Fileselection data} result] {
        SetMainStatus "Error in reading $Fileselection: $result"
        return
    }
    set bpmName [lindex $data(Parameter.bpmName) 0]
    set sector [lindex $data(Parameter.sector) 0]
    set plane [lindex $data(Parameter.plane) 0]
    set xOffset [lindex $data(Parameter.xOffset) 0]

    set ID1 S${sector}ID:P1:msAve:${plane}
    set ID2 S${sector}ID:P2:msAve:${plane}

    set col1 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P1mapped:${plane}
    set col2 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P1mapped:${plane}Fit
    set col3 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P2mapped:${plane}
    set col4 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P2mapped:${plane}Fit
    set col5 -col=${bpmName}:ms:${plane}:SetpointAO,$ID1
    set col6 -col=${bpmName}:ms:${plane}:SetpointAO,$ID2
    # SetMainStatus "$col1"
    if ![file exist $Fileselection.P1${plane}.fit] {
        if [catch {eval exec sddspfit ${Fileselection} ${Fileselection}.P1${plane}.fit -xOffset=$xOffset \
                     $col1} result] {
            SetMainStatus "DisplayP0P1ScanData5: $result"
            return
        }
    }
    if ![file exist $Fileselection.P2${plane}.fit] {
        if [catch {eval exec sddspfit ${Fileselection} ${Fileselection}.P2${plane}.fit -xOffset=$xOffset \
                     $col3 } result] {
            SetMainStatus "DisplayP0P1ScanData6: $result"
            return
        }
    }
    set requests ""
    lappend requests -layout=1,3 -sep=2 -legend
    lappend requests $col1 ${Fileselection}.P1${plane}.fit -graphic=symbol
    lappend requests $col2 ${Fileselection}.P1${plane}.fit -graphic=line
    lappend requests $col3 ${Fileselection}.P2${plane}.fit -graphic=symbol
    lappend requests $col4 ${Fileselection}.P2${plane}.fit -graphic=line
    lappend requests $col5 ${Fileselection}.P1${plane}.fit -graphic=line,type=1
    lappend requests $col6 ${Fileselection}.P2${plane}.fit -graphic=line,type=2
    set slope1 [ exec sdds2stream -par=Slope ${Fileselection}.P1${plane}.fit]
    set slope2 [exec sdds2stream -par=Slope ${Fileselection}.P2${plane}.fit]
    set Gain [expr $slope1/2 + $slope2/2]
    set setpoint ${bpmName}:ms:${plane}:GainAO
    SetMainStatus "calibrationed $setpoint=$Gain"
    if [lsearch $data(ParameterNames) *GainAO]==-1 {
        lappend process "-redefine=parameter,${setpoint},${Gain},type=double"
        if [catch {eval exec sddsprocess ${Fileselection} \
                     $process \
                     -nowarning -pipe=out | sddsconvert -pipe=in ${Fileselection} } result] {
            SetMainStatus "DisplayP0P1ScanData: $result"
            return
        }
    }
    if [catch {exec sddsprintout ${Fileselection} ${Fileselection}.print \
                 -parameters=${setpoint} } result] {
        SetMainStatus "DisplayP0P1ScanData: $result"
        return
    }
    if [catch {eval exec sddsplot $requests &} result] {
        SetMainStatus "DisplayP0P1ScanData: $result"
        return
    }
    displayFile -filename ${Fileselection}.print -values $Gain -setpoints $setpoint -P1Gain $slope1 -type $type
}

proc SetAndRestore {args} {
    set setpointList ""
    set setvalueList ""
    set timeout 5
    set type ""
    APSParseArguments {setpointList setvalueList timeout type}
  #  SetMainStatus "Waiting for setting ..."
    set comm ""
    
    if {![llength $setpointList] || ![llength $setvalueList] } {
	return -code error "SetAndRestore: control list or value is not given!"
    }
    foreach pv $setpointList val $setvalueList {
        if {![string compare $type P0] || ![string compare $type P1]} {
            lappend comm ${pv}:SetpointAO=${val}
        } else {
            lappend comm ${pv}=${val}
        }
    }
    if [catch {eval exec cavput -list=[join $comm ,] -pend=30} result] {
        return -code error "SetAndRestore1: $result"
    }
    set time [expr $timeout + 50]
   # SetMainStatus "timeout=$timeout"
    if [catch {WaitForSettingDone -timeout $time -bpm $setpointList -setValue $setvalueList \
                 -type $type} result] {
        return -code error "SetAndRestore2: $result"
    }

    return "done"
}

proc WaitForSettingDone {args} {
    global ReadList PVList
    set timeout 5
    set type ""
    set bpm ""
    set setValue 0
    set success 0
    set lowerLimit ""
    set upperLimit ""
    APSParseArguments {timeout bpm setValue type}
    if ![string length $type] {
        return -code error "the control pv type is not given!"
    }
    set PVList ""
    set ReadList ""
    set i 0

    
    foreach pv $bpm val $setValue {
        lappend ReadList read${i}
        incr i
        if {![string compare $type P0] || ![string compare $type P1] } {
            lappend lowerLimit -0.002
            lappend upperLimit 0.002
            lappend PVList ${pv}:SetpointAO
        }
        if {![string compare $type motor]} {
            if ![string length $setValue] {
                return -code error "the set values is not given"
            }
            lappend lowerLimit [expr $val - 0.002]
            lappend upperLimit [expr $val + 0.002]
            lappend PVList ${pv}.RBV
        }
    }
    # SetMainStatus "$type"
    #SetMainStatus "Waiting for setting $bpm..."
    if [pv linkw $ReadList $PVList] {
        return -code error "WaitForSettingDone1: unable link to $PVList"
    }
    set stopTime [expr [clock seconds]+ $timeout + 50]
    while {[clock seconds]<$stopTime} {
        pv getw $ReadList
        foreach val $ReadList pv $PVList lower $lowerLimit upper $upperLimit {
            set success 0
            global $val
            set read [set $val]
          #  SetMainStatus "now $pv=$read"
            if {$read>=$lower && $read <=$upper} {
                set success 1
            }
        }
        if $success {
            break
        }
        APSWaitWithUpdate -waitSeconds 10 -updateInterval 1
    }
    update
    if !$success {
        return -code error "Setting $bpm failed."
    }
    return "Setting $bpm done!"
}

#for data review
set rootname BM
proc MakeDataRevieFrame {args} {
    set parent ""
    global rootname plotSector plotPlane logPlot
    
    APSStrictParseArguments {parent}
    
    APSFrame .review -parent $parent -label "Data Review"
    $parent.review configure -bd 2 -relief ridge
    APSFrame .f1 -parent $parent.review.frame
    APSRadioButtonFrame .root -parent $parent.review.frame.f1.frame  \
      -variable rootname -buttonList \
      {BM ID P0 P1} -valueList {BM ID p0 p1} \
      -label "BPM type" -orientation horizontal \
      -packOption "-side left"
    APSLabeledEntry .sec -parent $parent.review.frame.f1.frame \
      -textVariable plotSector -label \
      "  Sector:" -width 10 \
      -contextHelp "Enter the sector for plotting." -packOption "-side left"
    APSRadioButtonFrame .plane -parent $parent.review.frame.f1.frame \
      -variable plotPlane -label " Plane:" -packOption "-side left" \
      -buttonList {x y} -valueList {x y} -orientation horizontal
    APSCheckButtonFrame .log -parent $parent.review.frame.f1.frame -packOption "-side left" \
      -variableList logPlot -buttonList log  -label "" \
      -contextHelp "check for plot option for gap scan -- log or linear mode for y-axis"
    # set tabList {Review GainPlot}
    # set tabFrames [APSTabFrame .rev -parent $parent.review -label "" \
        #                  -labelList $tabList -width 800 -height 200 -packOption "-expand true"]
    # set f1 [lindex $tabFrames 0]
    # set f2 [lindex $tabFrames 1]
    # Data review window
    APSDateTimeAdjEntry .startDate -parent $parent.review \
      -yearVariable StartYear \
      -monthVariable StartMonth \
      -dayVariable StartDay \
      -label "Starting date/time (year, month, day): " 
    APSDateTimeAdjEntry .endDate -parent $parent.review \
          -yearVariable EndYear \
          -monthVariable EndMonth \
          -dayVariable EndDay \
          -label "Ending date/time (year, month, day, hour):   " 
    APSButton .same -parent $parent.review -text "SameDay" -command SetSameDay \
      -contextHelp "Set the end date same as the start date."
    APSButton .display -parent $parent.review -text "Review/Install ..." \
      -command "ReviewScanData -rootvar rootname -sectorVar plotSector -planVar plotPlane"
    APSButton .gainplot -parent $parent.review -text "Gain~Gap plot" \
      -command "PlotGainOfScanData -rootvar rootname -sectorVar plotSector -planVar plotPlane"
    APSButton .gapscan -parent $parent.review -text "Review Gap Scan" \
      -command "GapScanReview -sectorVar plotSector"
    SetDateTimeToToday -rootname Start -hour 0
    SetDateTimeToToday -rootname End -hour 0
}

proc SetDateTimeToToday {args} {
    set rootname ""
    set hour 0
  
    APSStrictParseArguments {rootname hour}
    global todayMonth todayYear todayDay 
    global ${rootname}Month ${rootname}Year ${rootname}Day ${rootname}Hour
    
    APSDateBreakDown -dayVariable todayDay -yearVariable todayYear \
      -monthVariable todayMonth -twoDigitYear 0 -leadingZeros 0
    set ${rootname}Hour $hour
    set ${rootname}Month $todayMonth
    set ${rootname}Day $todayDay
    set ${rootname}Year $todayYear
}

proc PlotGainOfScanData {args} {
    set rootvar ""
    set sectorVar ""
    set planeVar ""
    APSParseArguments {rootvar sectorVar planVar}
    if {![string length $rootvar] || ![string length $sectorVar] || ![string length $planVar]} {
        SetMainStatus "Sector or rootname or plan is not given!"
        return
    }
    global $rootvar $sectorVar $planVar
    set rootname [set $rootvar]
    if [string compare $rootname ID]!=0 {
        SetMainStatus "Gain~gap plot only works for ID bpm!"
        return
    }
    set sector [set $sectorVar]
    if [catch {expr $sector / 2} result ] {
        SetMainStatus "sector has to be a number!"
        return
    }
    set plane [set $planVar]
    if {![string length $sector] || ![string length $plane] } {
        SetMainStatus "%he sector or plane is not given for plotting data.!"
        return
    }
    if ![string length $sector] {
        SetMainStatus "sector is not given for plotting data!"
        return
    }
    set selectedfiles [ReviewScanData -rootvar $rootvar -getfiles 1 -sectorVar $sectorVar -planVar $planVar]

    set i 0
    set filenames ""
    set gain1 ""
    set gain2 ""
    set gapList ""
    set SaveData(ColumnNames) ""
    foreach file $selectedfiles {
        #get gap value from filename
        set file1 [file tail $file]
        if [regexp {([^mm]*)mm(.+)} $file1 f1 f2 f3]==0 {
            SetMainStatus "Can not get gap value from file $file1!"
            return
        }
        if [regexp {([^Gap]*)Gap(.+)} $f2 a b gapValue]==0 {
            SetMainStatus "Can not get the gap value from $file1"
            return
        }
        if [catch {exec sddsprintout $file -par=*GainAO -notitle} result] {
            SetMainStatus "PlotGainOfScanData: $result in $file, reprocessing [file rootname $file]"
            if [catch {ReprocessFile -file $file} result] {
                SetMainStatus "$result"
                continue
            }
            if [catch {exec sddsprintout $file -par=*GainAO} result] {
                SetMainStatus "$result"
                continue
            }
        } 
        set filename $file
        if ![string length $result] {
            continue
        }
        #an example of the result of the above sddsprintout
        #S16ID:P1:ms:x:GainAO =  1.466605e+00  S16ID:P2:ms:x:GainAO =  1.194506e+00
        if ![string length $SaveData(ColumnNames)] {
            set SaveData(ColumnNames) [list S${sector}ID:P1:ms:${plane}:GainAO \
                               S${sector}ID:P2:ms:${plane}:GainAO Gap FileName]
            
            set SaveData(ColumnInfo.S${sector}ID:P1:ms:${plane}:GainAO) "type SDDS_DOUBLE"
            set SaveData(ColumnInfo.S${sector}ID:P2:ms:${plane}:GainAO) "type SDDS_DOUBLE"
            set SaveData(ColumnInfo.Gap) "type SDDS_LONG"
            set SaveData(ColumnInfo.FileName) "type SDDS_STRING"
        }
        set name1 [lindex $result 0]
        set name2 [lindex $result 3]
        if [string compare $name1 S${sector}ID:P1:ms:${plane}:GainAO]==0 {
            lappend gain1 [lindex $result 2]
            lappend gain2 [lindex $result 5]
        } else {
            lappend gain1 [lindex $result 5]
            lappend gain2 [lindex $result 2]
        }
        lappend gapList $gapValue
        lappend filenames $filename
    }
    if ![llength $gapList] {
        SetMainStatus "No data for plot!"
        return
    }
    set SaveData(Column.Gap) [list $gapList]
    set SaveData(Column.FileName) [list $filenames]
    set SaveData(Column.S${sector}ID:P1:ms:${plane}:GainAO) [list $gain1]
    set SaveData(Column.S${sector}ID:P2:ms:${plane}:GainAO) [list $gain2]
    set oldname S${sector}IDGainAndGap-00
    #set outputDir /home/helios/oagData/sr/bpmCalibration/xray/data/IDgain
    set outputDir /tmp
    set genName [APSNextGenerationedName -directory $outputDir -name $oldname -separator - -newFile 1]
    set tmpName /tmp/[APSTmpString]
    if [catch {sdds save $tmpName SaveData} result] {
        SetMainStatus "$result"
        return
    }
    #puts $genName
    APSAddToTmpFileList -ID 1 -fileList $tmpName
    if [catch {exec sddssort $tmpName $outputDir/$genName -col=Gap} result] {
        SetMainStatus "$result"
        return
    }
    SetMainStatus "Gap-Gain saved in file $outputDir/$genName"
    APSAddToTmpFileList -ID 1 -fileList "$outputDir/$genName"
    if [catch {eval exec sddsplot $outputDir/$genName -file \
                 -col=Gap,S${sector}ID:P1:ms:${plane}:GainAO -graphic=symbol,scale=2,sub=1,type=1 -leg\
                 -col=Gap,S${sector}ID:P2:ms:${plane}:GainAO -graphic=symbol,scale=2,sub=4,type=2 -leg  &} result] {
        SetMainStatus "$result"
        return
    }
}


proc SetSameDay {} {
    global StartYear StartMonth StartDay EndYear EndMonth EndDay
    
    set EndYear $StartYear
    set EndMonth $StartMonth
    set EndDay $StartDay

}

set ScanP1Only 0
proc MakeOptionFrame {widget args} {
    global beamlineSector IDBackGap initialValue numToAve numSteps IDCloseGap motorCrate 
    global postChangePause IDlocation initialTimeout finalValue Comment ScanP1Only
    set parent ""
    APSParseArguments {parent}

    APSFrame $widget -parent $parent -label "bpm calibration options" 
    set w0 $parent$widget.frame
    APSFrameGrid .fg -parent $w0 -xList {x1 x2}
    set w1 $w0.fg.x1
    APSLabeledEntry .step -parent $w1 -label \
      "steps: " -textVariable numSteps -width 10 
    APSLabeledEntry .sector -parent $w1 -label \
      "beamline sector:  " -textVariable beamlineSector -width 10 \
      -contextHelp "Enter the beamline sector between 1 and 40"
    
    APSLabeledEntry .initial -parent $w1 -label \
      "initial value:    " -textVariable initialValue -width 10 
    APSLabeledEntry .final -parent $w1 -label \
      "final value:" -textVariable finalValue -width 10 
   
    APSRadioButtonFrame .crate -parent $w1 -label "motorCrate" \
      -variable motorCrate -buttonList {1 2 3 4 5 } -orientation horizontal \
      -valueList {1 2 3 4 5 } -contextHelp "Choose the motor crate 1 through 5" \
      -commandList {"GetSector 1" "GetSector 2" "GetSector 3" "GetSector 4" "GetSector 5"}
    APSRadioButtonFrame .location -parent $w1 -label "IDlocation" \
      -variable IDlocation -buttonList {Downstream Upstream} -orientation horizontal \
      -valueList {Downstream Upstream} -contextHelp "choose the ID location: \
                    downstream or upStream"
    set w2 $w0.fg.x2
    APSLabeledEntry .gap1 -parent $w2 -label \
      "ID close gap (mm):" -textVariable IDCloseGap -width 10 \
      -contextHelp "Enter ID gap (range 0 to 180) in mm units."
    APSLabeledEntry .gap2 -parent $w2 -label \
      "ID gap for blades transfer (mm):" -textVariable IDBackGap -width 10 \
      -contextHelp "Enter ID gap (range 0 to 180) in mm units for taking background data."
     APSLabeledEntry .ave -parent $w2 -label \
      "average number:   " -textVariable numToAve -width 10 
    
    APSLabeledEntry .post -parent $w2 -label \
      "pause after change (s):" -textVariable postChangePause -width 10 
    APSLabeledEntry .timeout -parent $w2 -label "initial setting timeout (s):" \
      -textVariable initialTimeout -width 10 \
      -contextHelp "the maximum waiting time for the initial setting to be done."
    APSRadioButtonFrame .p1only -parent $w2 -label "Scan P1 only?" \
        -orientation horizontal \
        -variable ScanP1Only -buttonList {Yes No} -valueList {1 0} \
      -contextHelp "check yes to do only P1 scans, otherwise, scan both P1 and P2 ."
    APSLabeledEntry .desc -parent $w0 -label "Comment: " -textVariable Comment \
      -width 70 -contextHelp "Please enter the comment for taking experiment."
    
}


proc ReviewScanData {args} {
    set rootvar ""
    set getfiles 0
    set sectorVar ""
    set planVar ""
    APSParseArguments {rootvar getfiles sectorVar planVar}
    
    set sector *
    if [string length $sectorVar] {
        global $sectorVar
        set sector [set $sectorVar]
    }
    set plane ""
    if [string length $planVar] {
        global $planVar
        set plane [set $planVar]
    }
    global $rootvar mainDir
    set rootname [set $rootvar]
    set dataDir /home/helios/oagData/sr/bpmCalibration/xray/data
    global StartYear StartMonth StartDay Fileselection EndYear EndMonth EndDay
    set month [format %.2d $StartMonth]
    set day [format %.2d $StartDay]
    set starttime [clock scan $StartYear-${month}-${day}]
    set month [format %.2d $EndMonth]
    set day [format %.2d $EndDay]
    set endtime [clock scan $EndYear-${month}-${day}]
    if {$endtime < $starttime } {
        SetMainStatus "The end time should be later than the start time!"
        return
    }
    set oneday [expr 24*3600]
    set files ""
    set time $starttime
    while {$time<=$endtime} {
        set date [clock format $time -format %Y-%m%d]
        set currentList ""
        switch $rootname {
            BM -
            ID {
                if [file exist $dataDir/$date] {
                    set currentList [glob -nocomplain $dataDir/$date/S${sector}${rootname}*${plane}-*.proc]
                }
                if ![llength $currentList] {
                    set currentList [glob -nocomplain $dataDir/$date/S${sector}${rootname}*${plane}-??]
                }
            }
            p0 {
                if [file exist $dataDir/${rootname}/$date] {
                    set currentList [glob -nocomplain $dataDir/${rootname}/$date/S${sector}*${plane}-*.proc]
                } 
            }
            p1 {
                if [file exist $dataDir/${rootname}/$date] {
                    set currentList [glob -nocomplain $dataDir/${rootname}/$date/S${sector}*${plane}-*.proc]
                } 
            }
            default {
                SetMainStatus "Incorrect bpm type!"
                return
            }
        }
        set files [concat $files $currentList]
        set time [expr $time + $oneday]
    }
    if ![llength $files] {
        SetMainStatus "No processed files found for $rootname for the dates desired."
        return
    }
    if $getfiles {
        return $files
    }
    global fileList
    set fileList $files
    set deviceType $rootname
    set Fileselection ""
    APSScrolledListWindow .process -name "Scan Data Selection for $deviceType xray bpm" \
      -label "Select a scan data file" \
      -itemList $files -selectionVar Fileselection
    APSDialogBoxAddButton .view -parent .process -text "View Comment" -command "ListCommand -action view "
    APSDialogBoxAddButton .add -parent .process -text "Edit Comment" -command "ListCommand -action add"
    APSDialogBoxAddButton .delete -parent .process -text "Delete" -command "ListCommand -action delete"
    tkwait variable Fileselection
    if ![string length $Fileselection] {
        SetMainStatus "ReviewScanData1: No files chosen!"
        return
    }
    PlotData -rootname $rootname
}

proc AddCommentTo {args} {
    global AddComment
    set file ""
    APSParseArguments {file}
    if ![string length $file] {
        return
    }
    if ![file exist $file] {
        SetMainStatus "$file does not exist, cannot add comment to it!"
    }
   
    set pars [exec sddsquery $file -par]
    set comment [APSMakeSafeQualifierString $AddComment]
    regsub -all "\"" $comment "\\\"" $comment
    if [string length $comment] {
        if [catch {exec sddsprocess $file "-reprint=par,comment,$comment" -pipe=out | \
                     sddsconvert -pipe=in $file} result] {
            return -code error $result
        }
        SetMainStatus "Added comment to $file"
    } else {
        SetMainStatus "No comments for $file"
    }
    set AddComment ""
}
proc ListCommand {args} {
    global fileList AddComment
    set action ""
    set dataDir ""
    APSParseArguments {files action dataDir}
    set chosenList [.process.userFrame.sl.listbox curselection]
    if ![llength $chosenList] {
        return -code error "No files are chosen!"
    }
    set viewList ""
    foreach index $chosenList {
        set file $dataDir[lindex $fileList $index]
        set expfile [file rootname $file]
        switch $action {
            view {
                set parameters [exec sddsquery $file -par]
                if [lsearch -exact $parameters comment]>=0 {
                    exec sddsprintout $file -par=comment /tmp/view$index
                    lappend viewList /tmp/view$index
                } else {
                    bell
                    APSAlertBox [APSUniqueName .] -type warning -errorMessage "No comments for $file, press Edit Comment to add"
                }
            }
            delete {
                if [APSYesNoPopUp "Are you sure to delete file $file and related files?"] {
                    file delete -force $file* $expfile $expfile.mon $expfile.exp 
                }
            }
            add {
                set pars [exec sddsquery $file -par]
                if [lsearch -exact $pars comment]>=0 {
                    set AddComment [exec sdds2stream $file -par=comment]
                }
                APSDialogBox .question -name "Input Comment for $file" -width 70 \
                  -okCommand "AddCommentTo -file $file"
                APSLabeledEntry .comment -parent .question.userFrame -textVariable AddComment \
                  -width 70 -label "Comment: " 
            }
        }
    }
    if [llength $viewList] {
        APSAddToTmpFileList -ID XrayBPMCalibration -fileList $viewList
        eval exec cat $viewList > /tmp/viewList
        APSAddToTmpFileList -ID XrayBPMCalibration -fileList "/tmp/viewList"
        APSFileDisplayWindow .view -fileName /tmp/viewList -width 80 -printCommand "enscript -r"
    }
}

proc PlotData {args} {
    set rootname ""
    global Fileselection
    APSParseArguments {rootname}
    switch $rootname {
        BM -
        ID {
            if [catch {DisplayGainAndPlotData -filename $Fileselection} result] {
                SetMainStatus "ReviewScanData2: $result"
                return
            } 
        }
        p0 -
        p1 {
            if [catch {DisplayP0P1GainAndPlotData -filename $Fileselection \
                         -type [string toupper $rootname]} result] {
                SetMainStatus "ReviewScanData2: $result"
                return
            } 
        }
    }
    tkwait variable Fileselection
    PlotData -rootname $rootname
}

proc DisplayGainAndPlotData {args} {
    set filename ""
    global drive 
    APSParseArguments {filename}
    
    if ![string length $filename] {
        return -code error "filename is not given"
    }
    set list0 [split $filename /]
    set len [llength $list0]
    set date [lindex $list0 [expr $len-2]]
    if ![string match *.proc $filename] {
        set filename $filename.proc
        if ![file exist $filename] {
            if [catch {ReprocessFile -file $filename} result] {
                return -code error $result
            }
        }
    }
    if {![APSCheckSDDSFile -fileName $filename]} {
        return -code error "$filename is not an SDDS file or has been damaged.!"
    }
    if [catch {sdds load $filename bar} result] {
        SetMainStatus "$filename is damaged, reprocessing..."
        if [catch {ReprocessFile -file $filename} result] {
            return -code error "$result"
        }
        if [catch {sdds load $filename bar} result] {
            return -code error "Can not read file $filename: $result"
        }
    }
    
    set parameterNames $bar(ParameterNames)
    set columnNames $bar(ColumnNames)
    if {[lsearch -exact $parameterNames Sector]==-1 ||
        [lsearch -exact $parameterNames deviceType]==-1 ||
        [lsearch -exact $parameterNames motorCrate ]==-1 ||
        [lsearch -exact $parameterNames plane]==-1 } {
        SetMainStatus "The choosed file does contain the needed parameters!"
        return
    } 
    
    set motorCrate $bar(Parameter.motorCrate)
    set sector $bar(Parameter.Sector)
    set deviceType $bar(Parameter.deviceType)
    set plane $bar(Parameter.plane)
    switch $plane {
        x {
            set motor1 2
            set motor2 4
            set title horizontal
        }
        y {
            set motor1 1
            set motor2 3
            set title vertical
        }
        default {
            SetMainStatus "plane should be x or y"
            return
        }
    }
    
    set requests ""
    set process ""
    set setpoints ""
    lappend requests -layout=1,2 -sep=2 -legend
    set colList [exec sddsquery -col $filename]
    
    if [string match "*:P2:ms*" $colList] {
	set p1Only 0
        set xbpmList {1 2}
    } else {
	set p1Only 1
        set xbpmList 1
    }   
    foreach xbpm $xbpmList {
        if {$xbpm==1} {
            set motor $motor1
        }
        if {$xbpm==2} {
            set motor $motor2
        }
        set fitfile $filename.fit${xbpm}
        if ![file exist $fitfile] {
            if [catch {exec sddspfit $filename $fitfile \
			   -columns=SXDRV:${motorCrate}:M${motor}MT,S${sector}${deviceType}:P${xbpm}:msAve:${plane} } result] {
                SetMainStatus "$result SXDRV:${motorCrate}:M${motor}MT"
                return
            }
        }
        set col1 -col=SXDRV:${motorCrate}:M${motor}MT,S${sector}${deviceType}:P${xbpm}:msAve:${plane}
        set col2 -col=SXDRV:${motorCrate}:M${motor}MT,S${sector}${deviceType}:P${xbpm}:msAve:${plane}Fit
        
        lappend requests ${col1} $fitfile -graphic=symbol,scale=2 ${col2} -graphic=line $fitfile \
            -string=S${sector}${deviceType}:P${xbpm}:msAve:${plane},p=0.4,q=0.7-end
        set val1 [exec sdds2stream -par=Slope $fitfile]
        
        if {$val1<0} {
            set fc -1
        } else {
            set fc 1
        }
        #gain is always positive
        if [catch {set val2 [expr 1/$val1* $fc] } result] {
            if [APSYesNoPopUp "Error: $result, continue or not?"] {
                set val2 0
            } else {
                SetMainStatus "$result"
                return
            }
        }
        lappend values $val2
        SetMainStatus "motor=$motor slope=$val1"
        set point S${sector}${deviceType}:P${xbpm}:ms:${plane}:GainAO
        lappend setpoints $point
        if {[lsearch -exact $bar(ParameterNames) $point]==-1} {
            lappend process "-define=parameter,${point},${val2},type=double"
        } else {
            lappend process "-redefine=parameter,${point},${val2}"
        }
    }
    if {[string length $process] && [lsearch $bar(ParameterNames) *GainAO]==-1} {
        if [catch {eval exec sddsprocess $filename $process $filename.gain} result] {
            SetMainStatus "DisplayScanFile3: $result"
            return
        }
        exec mv $filename.gain $filename
    }
    if [llength $setpoints]>1 {
	set param "[lindex $setpoints 0],[lindex $setpoints 1]"
    } else {
	set param $setpoints
    }
    set printfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $printfile
    set root [file tail $filename]
    if [regexp {Gap(.+)} $root a b c] {
        set gap [scan $b %ld]
        set gapString "(gap=$gap mm)"
    } else {
        set gapString ""
    }
  
    if [catch {exec sddsprintout $filename $printfile \
                 -parameters=(${param}) \
               } result ] {
        SetMainStatus "$result"
        return
    }
    if [catch {eval exec sddsplot \"-topline=data collected on $date\" $requests &} result] {
        SetMainStatus "$result"
        return
    }
    #plot potentiometer data and blade data for ID and BM   
    if [lsearch $columnNames SXDRV:${motorCrate}:ADC:Ch0AveM.VAL]>=0 {
        switch $plane {
            x {
                set col1 "-col=SXDRV:${motorCrate}:M${motor}MT,SXDRV:${motorCrate}:ADC:Ch1AveM.VAL"
		set str1 "-string=SXDRV:${motorCrate}:ADC:Ch1AveM.VAL $gapString,p=0.1,q=0.8"
		if {!$p1Only} {
		    set col2 "-col=SXDRV:${motorCrate}:M${motor}MT,SXDRV:${motorCrate}:ADC:Ch3AveM.VAL"
		    set str2 "-string=SXDRV:${motorCrate}:ADC:Ch3AveM.VAL $gapString,p=0.1,q=0.8"
		}
            }
            y {
                set col1 "-col=SXDRV:${motorCrate}:M${motor}MT,SXDRV:${motorCrate}:ADC:Ch0AveM.VAL"
		set str1 "-string=SXDRV:${motorCrate}:ADC:Ch0AveM.VAL $gapString,p=0.1,q=0.8"
		if {!$p1Only} {
		    set col2 "-col=SXDRV:${motorCrate}:M${motor}MT,SXDRV:${motorCrate}:ADC:Ch2AveM.VAL" 
		    set str2 "-string=SXDRV:${motorCrate}:ADC:Ch2AveM.VAL $gapString,p=0.1,q=0.8"
		}  
            }
        }
	if {!$p1Only} {
	    exec sddsplot "-title=potential of $title (collected on $date)" -graphic=sym,connect,scale=2,sub=1 -layout=1,2 -sep -legend $filename $col1 $str1 $col2 $str2 &        
	} else {
	    exec sddsplot "-title=potential of $title (collected on $date)" -graphic=sym,connect,scale=2,sub=1 -layout=1,2 -sep -legend $filename $col1 $str1 &     
	}
    }
    if [string compare $deviceType ID]==0 {
        if [lsearch $columnNames S${sector}ID:P1:A:NormAveSU]>=0 {
            set bladesPV [GetBlades $sector]
            set requests ""
            foreach pv $bladesPV {
		if {$p1Only && [regexp {P2} $pv]} {
		    continue
		}
                append requests " -col=SXDRV:${motorCrate}:M${motor}MT,$pv \"-string=$pv (gap=$gap mm),p=0.2,q=0.8\""
            }
            eval exec sddsplot \"-title=blade data of $title (collected on $date)\" \
              -layout=2,4 -sep -graphic=sym,connect,scale=2,sub=2 $filename $requests &
        }
    }
    if [string compare $deviceType BM]==0 {
        if [lsearch $columnNames S${sector}BM:P1:A:NormAveSU]>=0 {
            set col1 "-col=SXDRV:${motorCrate}:M${motor}MT,S${sector}BM:P1:A:NormAveSU"
            set str1 "-string=S${sector}BM:P1:A:NormAveSU,p=0.4,q=0.7"
            set col2 "-col=SXDRV:${motorCrate}:M${motor}MT,S${sector}BM:P1:B:NormAveSU"
            set str2 "-string=S${sector}BM:P1:B:NormAveSU,p=0.4,q=0.7"
            if [string match "*:P2:ms*" $colList] {
                set col3 "-col=SXDRV:${motorCrate}:M${motor}MT,S${sector}BM:P2:A:NormAveSU"
                set str3 "-string=S${sector}BM:P2:A:NormAveSU,p=0.4,q=0.7"
                set col4 "-col=SXDRV:${motorCrate}:M${motor}MT,S${sector}BM:P2:B:NormAveSU"
                set str4 "-string=S${sector}BM:P2:B:NormAveSU,p=0.4,q=0.7"
            } else {
                set col3 ""
                set str3 ""
                set col4 ""
                set str4 ""
            }
            eval exec sddsplot \"-title=blade data of $title (collected on $date)\"  -layout=1,4 -sep \
                -graphic=sym,connect,scale=2 $filename \
                $col1 $str1 $col2 $str2 $col3 $str3 $col4 $str4 &
        }
    }
    displayFile -filename $printfile -values $values -setpoints $setpoints     
}

proc DisplayP0P1GainAndPlotData {args} {
    set filename ""
    set type ""
    APSParseArguments {filename type}
    if ![string length $type] {return -code error "type is not given"}
    if ![string length $filename] {
        return -code error "filename is not given"
    }
    if {![APSCheckSDDSFile -fileName $filename]} {
        return -code error "$filename is not an SDDS file or has been damaged.!"
    }
    if [catch {sdds load $filename bar} result] {
        return -code error "Can not read file $filename: $result"
    }
    set parameterNames $bar(ParameterNames)
    if {[lsearch -exact $parameterNames bpmName]==-1 ||
        [lsearch -exact $parameterNames sector]==-1 ||
        [lsearch -exact $parameterNames xOffset ]==-1 ||
        [lsearch -exact $parameterNames plane]==-1 } {
        SetMainStatus "The choosed file does contain the needed parameters!"
        return
    } 
    
    set bpmName [lindex $bar(Parameter.bpmName) 0]
    set sector [lindex $bar(Parameter.sector) 0]
    set plane [lindex $bar(Parameter.plane) 0]
    set xOffset [lindex $bar(Parameter.xOffset) 0]
    set ID1 S${sector}ID:P1:msAve:${plane}
    set ID2 S${sector}ID:P2:msAve:${plane}

    set col1 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P1mapped:${plane} 
    set str1 -string=${bpmName}:P1mapped:${plane},p=0.4,q=0.7
    set col2 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P1mapped:${plane}Fit 
    set col3 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P2mapped:${plane} 
    set str2 -string=${bpmName}:P2mapped:${plane},p=0.4,q=0.7
    set col4 -col=${bpmName}:ms:${plane}:SetpointAO,${bpmName}:P2mapped:${plane}Fit
    
    set col5 -col=${bpmName}:ms:${plane}:SetpointAO,$ID1
    set col6 -col=${bpmName}:ms:${plane}:SetpointAO,$ID2

    # SetMainStatus "$col1"
    set fitfile1  /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $fitfile1
    if [catch {eval exec sddspfit $filename $fitfile1 -xOffset=$xOffset \
                 $col1} result] {
        SetMainStatus "DisplayP0P1ScanData5: $result"
        return
    }
    set fitfile2  /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $fitfile2
    
    if [catch {eval exec sddspfit $filename $fitfile2 -xOffset=$xOffset \
                 $col3 } result] {
        SetMainStatus "DisplayP0P1ScanData6: $result"
        return
    }

    set requests ""
    lappend requests -layout=1,3 -sep=2 -legend
    lappend requests $col1 $str1 $fitfile1 -graphic=symbol
    lappend requests $col2 $fitfile1 -graphic=line,type=1
    lappend requests $col3 $str2 $fitfile2 -graphic=symbol
    lappend requests $col4 $fitfile2 -graphic=line,type=1
    lappend requests $col5 $filename -graphic=symbol,scale=2,sub=1,conn,type=1
    lappend requests $col6 $filename -graphic=symbol,scale=2,sub=4,conn,type=2
    
    set slope1 [ exec sdds2stream -par=Slope $fitfile1]
    set slope2 [exec sdds2stream -par=Slope $fitfile2]
    set Gain [expr $slope1/2 + $slope2/2]
    set setpoint ${bpmName}:ms:${plane}:GainAO
    SetMainStatus "calibrationed $setpoint=$Gain"
    set parNames $bar(ParameterNames)
    set tmpfile /tmp/[APSTmpString]
    if [catch {eval exec sddsprocess $filename $tmpfile.gain \
                 -redefine=par,${bpmName}:P1mapped:${plane}:Slope,$slope1,type=double \
                 -redefine=par,${bpmName}:P2mapped:${plane}:Slope,$slope2,type=double \
                 -redefine=parameter,${setpoint},${Gain},type=double } result] {
        SetMainStatus "DisplayP0P1ScanData: $result"
        
        return
    }
    #exec mv $tmpfile.gain $filename
   
    APSAddToTmpFileList -ID 1 -fileList $tmpfile
    if [catch {exec sddsprintout $tmpfile.gain $tmpfile \
                 -parameter=*Slope,format=%.5f -par=*GainAO,format=%.5f } result] {
        SetMainStatus "DisplayP0P1ScanData: $result"
        return
    }
    if [catch {eval exec sddsplot $requests &} result] {
        SetMainStatus "DisplayP0P1ScanData: $result"
        return
    }
    displayFile -filename $tmpfile -values $Gain -setpoints $setpoint -type $type -P1Gain $slope1
}

proc ReprocessFile {args} {
    set file ""
    global Comment
    APSParseArguments {file}
    if ![string length $file] {
        return -code error "Proc file name is not given!"
    }
    
    set procFile [file rootname $file]
    set i [string last - $procFile]
    set i [expr $i - 1]
    set plane [string range $procFile $i $i]
    set i1 [string first S $procFile ]
    if [string match *BM* $procFile] {
        set deviceType BM
        set i2 [string first B $procFile]
    }
    if [string match *ID* $procFile] {
        set deviceType ID
        set i2 [string first I $procFile]
    }
    set sector [string range $procFile [expr $i1+1] [expr $i2 -1]]
    set columns [exec sddsquery $procFile -col]
    set index [lsearch $columns SXDRV*]
    if {$index<0} {
        return -code error "Motor is not included in $file, quite reprocessing!"
    }
    set motor [lindex $columns $index]
    #note that motor name is SXDRV:?:M2MT
    set motorCrate [string range $motor 6 6]
    SetMainStatus "plane=$plane, sector=$sector deviceType=$deviceType, motorcrate=$motorCrate"
    set date [clock format [clock seconds] -format %Y-%m%d]
    set comment "reprocessed on $date"
    if [catch {postProcessScan -file $procFile -deviceType $deviceType \
                 -motorCrate $motorCrate -sector $sector \
                 -plane $plane -comment $comment} result1] {
        return -code error "Error in reprocessing: $result1"
    }
}

proc GetSector {motor} {
    global beamlineSector deviceType
    
    if [catch {exec cavget -list=SXDRV:${motor}:BMorIDMI -pend=5} deviceType] {
        SetMainStatus "$deviceType"
        set  beamlineSector ""
        return
    }
    if [catch {exec cavget -list=SXDRV:${motor}:SectorNumX1MI -pend=5} d1] {
        SetMainStatus "$d1"
        set  beamlineSector ""
        return
    }
    if [catch {exec cavget -list=SXDRV:${motor}:SectorNumX10MI -pend=5} d10] {
        SetMainStatus "$d10"
        set  beamlineSector ""
        return
    }
    if {[string compare $d1 ?]==0 || [string compare $d10 ?]==0} {
        SetMainStatus "Unable to get the value of SXDRV:${motor}:SectorNumX1MI or SXDRV:${motor}:SectorNumX10MI"
        set  beamlineSector ""
        return
    }
    set beamlineSector [expr int($d10 *10 + $d1)]
    
}

proc MakeListOfArchives {args} {
    global mainDir StartYear StartMonth StartDay Fileselection EndYear EndMonth EndDay
    set sector *
    set subDir ""
    set type *
    APSParseArguments {sector subDir type}
   
    set dataDir $mainDir/$subDir
    set month [format %.2d $StartMonth]
    set day [format %.2d $StartDay]
    set starttime [clock scan $StartYear-${month}-${day}]
    set month [format %.2d $EndMonth]
    set day [format %.2d $EndDay]
    set endtime [clock scan $EndYear-${month}-${day}]
    if {$endtime < $starttime } {
        SetMainStatus "The end time should be later than the start time!"
        return
    }
    set oneday [expr 24*3600]
    set files ""
    set time $starttime
    while {$time<=$endtime} {
        set date [clock format $time -format %Y-%m%d]
        set currentList ""
        if [file exist $dataDir/$date] {
            set currentList [glob -nocomplain $dataDir/$date/S${sector}${type}-??]
        }
        set files [concat $files $currentList]
        set time [expr $time + $oneday]
    }
    if ![llength $files] {
        return -code error "No files found for $subDir on sector $sector"
    }
    set newList ""
    foreach file $files {
        set itemList [file split $file]
        set listLength [llength $itemList]
        set item [eval file join [lrange $itemList [expr $listLength - 2] end] ]
        lappend newList $item
    }
    set newList [lsort -decreasing $newList]
    return $newList
}

set GapScanPause 20
set StartGap ""
set EndGap ""
set GapInterval 5
set comment ""
set AddComment ""
set deviceType "" 
set motorCrate ""
set beamlineSector ""
set IDCloseGap 15 
set IDBackGap 60
set IDlocation Downstream
set initialValue -0.2
set finalValue 0.2
set numToAve 5
set numSteps 7
set Bfactor1(P0) -2.803
set Bfactor2(P0) -3.559
set Afactor1(P0) 3.803
set Afactor2(P0) 4.559
set Bfactor1(P1) -1.561
set Bfactor2(P1) -2.033
set Afactor1(P1) 2.561
set Afactor2(P1) 3.033
set postChangePause 25
set initialTimeout 60 
set runControlCheckList {S:OrbitControlLawXRC S:OrbitControlLawYRC \
                             DP:S:OrbitControlLawXSDDS DP:S:OrbitControlLawYSDDS \
                             S:ID:GapFeedForwardRC}
set runControlDescList {"Horizontal WS orbit correction" "Vertical WS orbit correction" \
                            "Horizontal DP orbit correction" "Vertical DP orbit correction" \
                            "ID offset feedforward"}

set mainDir /home/helios/oagData/sr/bpmCalibration/xray

set date  [clock format [clock seconds] -format "%Y-%m%d"]
set outputDir $mainDir/data/$date
set outp0Dir $mainDir/data/p0/$date
set outp1Dir $mainDir/data/p1/$date
set plotSector *
set plotPlane y
set logPlot 0

APSScrolledStatus .status -parent .userFrame -width 60 \
  -textVariable ControlStatus
MakeOptionFrame .options -parent .userFrame
APSFrame .tab -parent .userFrame -label "Run Experiment"
.userFrame.tab configure -relief ridge -bd 2
set sectionList [list BM_ID P0 P1]
set tabFrameWidgetList [APSTabFrame .main -parent .userFrame.tab.frame -label "" \
                          -labelList $sectionList -width 550 -height 150 -packOption "-expand true"]
CreateBMIDWidget [lindex $tabFrameWidgetList 0]
CreateP0Widget [lindex $tabFrameWidgetList 1]
CreateP1Widget [lindex $tabFrameWidgetList 2]
MakeDataRevieFrame -parent .userFrame
