#!/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.20  2005/07/26 19:44:26  shang
# added LINACL3 beamline
#
# Revision 1.19  2005/01/17 22:09:58  shang
# removed the "qq" from the faked bpm name
#
# Revision 1.18  2004/12/07 16:43:14  shang
# added LTP beamline
#
# Revision 1.17  2004/11/12 22:23:51  shang
# added LINAC5 beamline
#
# Revision 1.16  2004/09/28 20:56:09  shang
# fixed a bug in switch statement
#
# Revision 1.15  2004/09/28 20:49:30  shang
# removed checking bpm name of lab2 since the bpm names are similar to other beamline
# bpms now.
#
# Revision 1.14  2004/09/28 20:39:58  shang
# changed the bpm names of lab2 since they were changed.
#
# Revision 1.13  2004/09/28 16:18:26  shang
# changed the actuator pv of lab2 to DIAG2:SetPower
#
# Revision 1.12  2004/09/13 20:14:41  shang
# added "data taking failed" message to the error message when the slope is zero
# in processing data.
#
# Revision 1.11  2004/09/13 20:08:30  shang
# added returning error message if the gain is zero
#
# Revision 1.10  2004/09/13 19:55:54  shang
# added PTB:SB:PV0 bpm to PTB beamline
#
# Revision 1.9  2004/09/13 14:47:32  shang
# added PTB:SB:PH0 bpm to PTB beamlina and removed "j" character from the bpm
# names of Linac4 beamline.
#
# Revision 1.8  2004/08/18 16:09:28  shang
# made further change on the bpm name of Lab1 beamline since they were totally
# different from before.
#
# Revision 1.7  2004/08/18 15:42:12  shang
# changed the monitor pv name of Lab1
#
# Revision 1.6  2004/08/18 14:54:33  shang
# changed the Lab1 actuator pv to DIAG5:SetPower
#
# Revision 1.5  2004/07/29 15:35:14  shang
# added Linac L4 beamline
#
# Revision 1.4  2004/07/09 14:32:16  shang
# added Linac L2 beam line.
#
# Revision 1.3  2003/09/12 19:32:34  shang
# changed the PV name of Lab1 beam and added difference processing, plots
# recalculated the gain and offset based on the relationship between calibrated voltage,
# raw voltage and power source, details see shang's notes.
#
# Revision 1.2  2003/09/11 15:19:20  shang
# changed the pv name for Lab2a system
#
# Revision 1.1  2003/09/10 15:29:11  shang
# first version, for measuring beamline gain and offsets
#
# first version: shang
#


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

APSApplication . -name BeamlineGainMeasurement -version "\$Revision: 1.21 $ \$Author: soliday $" \
  -overview {measure the bpm gain and offsets }

set ControlStatus "Ready."
set args $argv
set BeamlineSelection "PTB"
set PTBbpmList {PTB:SB:PH0 PTB:SB:PV0 PTB:SB1:PH1 PTB:SB1:PV1 PTB:SB2:PH1 PTB:SB2:PV1 PTB:PH1 PTB:PV1 PTB:PH2 PTB:PV2 PTB:PH3 PTB:PV3 PTB:PH4 PTB:PV4 PTB:PH5 PTB:PV5}
set BTSbpmList {oag:PM1:intensityM oag:PM2:intensityM}
set Lab2bpmList {P0:BPM.TOP P0:BPM.BOT P0:BPM.LFT P0:BPM.RHT \
                   P1:BPM.TOP P1:BPM.BOT P1:BPM.LFT P1:BPM.RHT}
set Lab1bpmList {P0:BPM.TOP P0:BPM.BOT P0:BPM.LFT P0:BPM.RHT \
                   P1:BPM.TOP P1:BPM.BOT P1:BPM.LFT P1:BPM.RHT \
                   P2:BPM.TOP P2:BPM.BOT P2:BPM.LFT P2:BPM.RHT \
                   P3:BPM.TOP P3:BPM.BOT P3:BPM.LFT P3:BPM.RHT  \
                   P4:BPM.TOP P4:BPM.BOT P4:BPM.LFT P4:BPM.RHT \
                   P5:BPM.TOP P5:BPM.BOT P5:BPM.LFT P5:BPM.RHT \
                   P6:BPM.TOP P6:BPM.BOT P6:BPM.LFT P6:BPM.RHT \
                   P7:BPM.TOP P7:BPM.BOT P7:BPM.LFT P7:BPM.RHT}
set LINACL2bpmList {L0:P2 L1:P0 L1:P1 L2:P1 L2:P2 L2:P3 L2:P4 L:BPD:L1P1:L2AS1}
set LINACL3bpmList {L2:P4 L3:P1 L3:P2 L3:P3}
set LINACL4bpmList {L4:P1 L4:P2 L4:P3 L4:P4 L3:FCN}
set LINACL5bpmList {L5:P1 L5:P2 L5:P3 L5:P4 L5:FCN}
set LTPbpmList {LTP:PV4 LTP:PV3 LTP:PV2 LTP:PV1 LTP:PH4 LTP:PH3 LTP:PH2 LTP:PH1}
set Steps 8
set NumToAverage 10
set PostChangePause 4
set InitialValue -10
set FinalValue -30
set actuatorPV oag:H1:setCurrentC
set dataDir /home/helios/SHANG/test/data
set templateInput  $dataDir/inputFiles/gainMeasure.exp
set Comment ""
set refGain 0.033
set refOffset 1.0
set subBeam a
#set env(EPICS_CA_ADDR_LIST) 164.54.49.21
set date  [clock format [clock seconds] -format "%Y-%m%d"]
set outputDir /home/helios/oagData/diag/$BeamlineSelection
if ![file exist $outputDir] {
    exec mkdir $outputDir
    #exec /home/helios/OAG/bin/setFACL-oagPlus diag,emery,shang,sr $outputDir 
}
proc SetMainStatus {text} {
    global ControlStatus
    set ControlStatus $text
    update
}

proc MakeBeamlineWidget {widget args} {
    global BeamlineSelection BeamFrame PTBbpmList BTSbpmList Lab2bpmList Lab1bpmList
    global LINACL2bpmList LINACL3bpmList LINACL4bpmList LINACL5bpmList LTPbpmList
    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label ""
    set w1 $parent$widget.frame
   # $w1 configure -relief flat -bd 0
   
    set sectionList {Lab1 Lab2 LINACL2  LINACL3 LINACL4 LINACL5 PTB LTP}
    set tabWidgetList [APSTabFrame .type -parent $w1 -label "BPM Selection" \
                         -labelList $sectionList -width 550 -height 250 \
                         -packOption "-expand true" \
                         -commandList { {SetBeamline Lab1} {SetBeamline Lab2} \
                                          {SetBeamline LINACL2 } \
                                          {SetBeamline LINACL3 }
                                          {SetBeamline LINACL4} \
                                          {SetBeamline LINACL5} {SetBeamline PTB} \
                                          {SetBeamline LTP} }]
    pack $parent$widget.frame.type -side top
    $parent$widget.frame.type.frame.tn select 0
    set index 0
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $Lab1bpmList -multibeam 1
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $Lab2bpmList
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $LINACL2bpmList
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $LINACL3bpmList
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $LINACL4bpmList
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $LINACL5bpmList
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $PTBbpmList -limits 2
    incr index
    MakeBPMSelectionWidget .bpm -parent [lindex $tabWidgetList $index] \
      -bpmList $LTPbpmList    
}

proc SetBeamline {beamline} {
    global BeamlineSelection actuatorPV subBeam outputDir
    set BeamlineSelection $beamline
    switch $BeamlineSelection {
        Lab2 {
            set actuatorPV DIAG2:SetPower
        }
        Lab1 {
            set actuatorPV DIAG5:SetPower
        }
	PTB {
	    set actuatorPV diag:twrRampC
	}
        LINACL2 {
            set actuatorPV LIBPM2:SetPower
        }
        LINACL3 {
            set actuatorPV LIBPM3:SetPower
        }
        LINACL4 {
            set actuatorPV LIBPM4:SetPower
        }
        LINACL5 {
            set actuatorPV LIBPM5:SetPower
        }
        LTP {
            set actuatorPV LET1BPM:SetPower
        }
        default {
            set actuatorPV oag:H1:setCurrentC
        }
    }
    set outputDir /home/helios/oagData/diag/$BeamlineSelection
    if ![file exist $outputDir] {
        if ![file exist $outputDir] {
            exec mkdir $outputDir
            #exec /home/helios/OAG/bin/setFACL-oagPlus diag,emery,shang,sr $outputDir 
        }
    }
    SetMainStatus "$BeamlineSelection selected, actuatorPV=$actuatorPV."
}
proc MakeBPMSelectionWidget {widget args} {
    set parent ""
    set bpmList ""
    set multibeam 0
    set limits 4
    APSParseArguments {parent bpmList multibeam limits}
    
    if ![llength $bpmList] {
        SetMainStatus "Not available."
        return
    }
    APSFrame $widget -parent $parent 
    $parent$widget.frame configure -relief flat -bd 0
    
    APSCheckButtonFrame .check -parent $parent$widget.frame -label "" \
      -buttonList $bpmList -variableList $bpmList -allNone 1 \
      -packOption "-side left -fill y" \
      -contextHelp "select the bpms to measure" \
      -orientation horizontal -limitPerRow $limits
    
}

proc MakeOptionFrame {widget args} {
    global Steps InitialValue NumToAverage FinalValue PostChangePause outputDir
    global refGain refOffset

    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 Steps -width 10 \
      -contextHelp "The number of steps for taking experiments."
    APSLabeledEntry .initial -parent $w1 -label \
      "initial value:    " -textVariable InitialValue -width 10 
    APSLabeledEntry .final -parent $w1 -label \
      "final value:" -textVariable FinalValue -width 10 
   
    set w2 $w0.fg.x2
    APSLabeledEntry .ave -parent $w2 -label \
      "average number:   " -textVariable NumToAverage -width 10 \
      -contextHelp "The average number of measurements."
    
    APSLabeledEntry .post -parent $w2 -label \
      "pause after change (s):" -textVariable PostChangePause -width 10 \
      -contextHelp "The pause time after change the settings."
    APSLabeledEntryFrame .ref -parent $w2 -label "Reference gain(V/db)/offset(V):" \
      -variableList {refGain refOffset} \
      -contextHelp "the reference gain and offset of Lab2 beamline" \
      -orientation horizontal -width 10

    APSLabeledEntry .dir -parent $w0 -label "Output maindir:" \
      -textVariable outputDir -contextHelp "enter the main directory for saving output files." \
      -width 55
    #APSButton .daily -parent $w0.dir -text "daily" -packOption "-side right" -size small \
    #  -command {set outputDir [APSGoToDailyDirectory]} 
    #APSButton .archinve -parent $w0.dir -text "archive" -packOption "-side right" -size small \
     # -command {set outputDir $dataDir} 
    APSLabeledEntry .desc -parent $w0 -label "Comment: " -textVariable Comment \
      -width 55 -contextHelp "Please enter the comment for taking experiment."
    
}

proc MakeActionFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent
    set w $parent$widget.frame
    APSButton .run -parent $w -text "Run" -command "RunExperiment"
    APSButton .review -parent $w -text "Reprocess Review/Install" -command "ReviewScanData" \
      -contextHelp "review and isntall gain and offset."
    
}

proc ReviewScanData {args} {
    global dataDir BeamlineSelection Fileselection outputDir
    set plot 0
    set process 0
    APSParseArguments {plot process}
    #set directory $dataDir/$BeamlineSelection
    #temporary
    set directory /home/helios/oagData/diag/$BeamlineSelection
    set dirs [glob -nocomplain $directory/*] 
    if ![llength $dirs] {return -code error "No files found in $directory!"}
    set files ""
    foreach dir $dirs {
        set expfiles [glob -nocomplain $dir/*-????] 
        foreach file $expfiles {
            lappend files $file
        }
    }
    if ![llength $files] {return -code error "No files found in $directory!"}
    set Fileselection ""
    if [winfo exist .review] {
        destroy .review
    }
    APSScrolledListWindow .review -name "Gap Scan Selection" \
      -label "Select a scan data file" \
      -itemList $files -selectionVar Fileselection
    global fileList
    set fileList $files
    APSDialogBoxAddButton .process -parent .review -text "ReProcess" -command "ListCommand -action process"
    APSDialogBoxAddButton .view -parent .review -text "View Comment" -command "ListCommand -action view"
    APSDialogBoxAddButton .add -parent .review -text "Edit Comment" -command "ListCommand -action add"
    APSDialogBoxAddButton .delete -parent .review -text "Delete" -command "ListCommand -action delete"
    tkwait variable Fileselection
    PlotAndInstallScanData -filename ${Fileselection} 
    tkwait variable Fileselection
    PlotAndInstallScanData -filename ${Fileselection} 
}
proc RunExperiment {args} {
    global dataDir BeamlineSelection Steps PostChangePause InitialValue FinalValue actuatorPV
    global NumToAverage ExperimentDone templateInput Steps Comment
    
    if [catch {exec caget $actuatorPV} result] {
        return -code error "RunExperiment: $result"
    }
    if [string match "*Invalid*" $result] {
        return -code error "RunExperiment: $actuatorPV pv not found!"
    }
    #set directory $dataDir/$BeamlineSelection/[clock format [clock seconds] -format %Y-%m%d]
    #temporary
    global outputDir
    set directory $outputDir/[clock format [clock seconds] -format %Y-%m%d]
    if ![file exist $directory] {
        SetMainStatus "Create dir: $directory"
        if [catch {exec mkdir -p $directory} result] {
            return -code error "Error making directory $directory: $result"
        }
        #exec /home/helios/OAG/bin/setFACL-oagPlus shang,sr,emery,diag $directory
    }
    #make monitor file
    if { $BeamlineSelection == "Lab1"} {
        #global subBeam
        set name Lab2-0000
    } else {
        set name ${BeamlineSelection}-0000
    }
    if [file exist $directory/$name] {
        set name [APSNextGenerationedName -directory $directory -name $name -separator - -newFile 1]
    }
    set monFile $directory/${name}.mon
    if [catch {MakeMonitorFile -filename $monFile } result] {
        return -code error "RunExperiment: $result"
    }
    if [string length $Comment] {
        set Comment [APSMakeSafeQualifierString $Comment]
    } else {
        set Comment ""
    }
    set ExperimentDone 0
    set macro -macro=monitorFile=$monFile,numToAve=$NumToAverage,actuatorName=$actuatorPV,steps=$Steps,initialValue=$InitialValue,finalValue=$FinalValue,postChangePause=$PostChangePause
    APSExecLog .runExperiment -width 80 -unixCommand \
      "sddsexperiment $templateInput  $directory/${name} $macro \"-comment=$Comment\" -verbose" \
      -cancelCallback "set ExperimentDone cancelled" \
      -abortCallback "set ExperimentDone aborted" \
      -callback "set ExperimentDone done"
    if !$ExperimentDone {
        tkwait variable ExperimentDone
    }
    if {$ExperimentDone!="done"} {
        SetMainStatus "Experiment was cancelled!"
        return
    } else {
        #process data
        if [catch {ProcessScanData -filename $directory/$name} result] {
            SetMainStatus "$result!"
            return
        }
    }
    SetMainStatus "Experiment done."
}

proc MakeMonitorFile {args} {
    global BeamlineSelection PTBbpmList BTSbpmList Lab2bpmList Lab1bpmList subBeam
    global LINACL2bpmList LINACL3bpmList  LINACL4bpmList LINACL5bpmList LTPbpmList

    set filename ""
    APSParseArguments {filename}
    if ![string length $filename] {
        return -code error "MakeMonitorFile: filename for saving monitor file is not given!"
    }
    SetMainStatus "beamline=$BeamlineSelection"
    set variableList [set ${BeamlineSelection}bpmList]
    set monPVList ""
    foreach var $variableList {
        global $var
        if [set $var] {
            switch $BeamlineSelection {
                Lab2 {
                    lappend monPVList DIAG2:${var}V
                }
                Lab1 {
                    lappend monPVList DIAG5:${var}V
                }
                LINACL2 {
                    if {$var=="L:BPD:L1P1:L2AS1"} {
                        lappend monPVList $var
                    } else {
                        lappend monPVList ${var}:BPM.TOPV
                        lappend monPVList ${var}:BPM.BOTV
                        lappend monPVList ${var}:BPM.LFTV
                        lappend monPVList ${var}:BPM.RHTV
                    }
                }
                LINACL3 -
                LINACL4 -
                LINACL5 {
                    lappend monPVList ${var}:BPM.TOPV
                    lappend monPVList ${var}:BPM.BOTV
                    lappend monPVList ${var}:BPM.LFTV
                    lappend monPVList ${var}:BPM.RHTV
                }
                PTB -
                LTP {
                    if [string match *H* $var] {
			lappend monPVList ${var}:BPM.LFTV
                        lappend monPVList ${var}:BPM.RHTV
                    } elseif [string match *V* $var] {
			lappend monPVList ${var}:BPM.TOPV
			lappend monPVList ${var}:BPM.BOTV
                    } else {
                        return -code error "MakeMonitorFile: Unknown PTB bpm name: $var"
                    }
                }
                BTS {
                    lappend monPVList $var
                }
                default {
                    return -code error "MakeMonitorFile: unkown beam line!"
                }
            }
        }
    }
    if ![llength $monPVList] {return -code error "None bpm was selected."}
    if [catch {exec sddsmakedataset $filename -defaultType=string \
                 -col=ControlName -data=[join $monPVList ,] \
                 -col=ReadbackName -data=[join $monPVList ,] } result] {
        return -code error "MakeMonitorFile: $result (sddsmakedataset)"
    }
}

proc ProcessScanData {args} {
    global Comment
    set filename ""
    set reprocess 0
    APSParseArguments {filename reprocess}
    
    global actuatorPV BeamlineSelection refGain refOffset
    
    if ![file exist $filename] {return -code error "ProcessScanData: $filename does not exist!"}
    if [regexp {(.*)\.proc} $filename a b] {
        #reprocessing file if a processed file is chosen
        set filename $b
    } 
    set outputFile ${filename}.proc
    if {[file exist $outputFile] && !$reprocess } {
        if ![APSYesNoPopUp "$outputFile already exist, reproces it?"] {
            return
        }
    }
    SetMainStatus "Processing $filename..."
    set columnNames [exec sddsquery $filename -col]
    set readbacks ""
    foreach col $columnNames {
        if {$col=="ElapsedTime" || $col=="Time" || $col=="TimeOfDay"} {continue}
        if [string compare $col $actuatorPV]==0 {continue}
        lappend readbacks $col
    }
    set tmpRoot /tmp/[APSTmpString]
    set fileList ""
    foreach readback $readbacks {
        if [string match "*RAW" $readback] {continue}
        switch $BeamlineSelection {
            Lab1 -
            Lab2 -
            PTB -
            LTP -
            LINACL2 -
            LINACL4 -
            LINACL3 -
            LINACL5 {
                if [catch {exec sddspfit $filename -pipe=out -col=$actuatorPV,$readback \
                             | sddsprocess -pipe \
                             "-redefine=col,Reference,$actuatorPV $refGain * $refOffset +" \
                             "-define=col,${readback}Diff,${readback}Fit Reference -" \
                             | sddsconvert -pipe=in -rename=par,Slope=${readback}_slope \
                             -rename=par,Intercept=${readback}_offset $tmpRoot.$readback } result] {
                    return -code error "ProcessScanData: $result"
                }
            }
            default {
                if [catch {exec sddspfit $filename -pipe=out -col=$actuatorPV,$readback \
                             | sddsconvert -pipe=in -rename=par,Slope=${readback}_slope \
                             -rename=par,Intercept=${readback}_offset $tmpRoot.$readback } result] {
                    return -code error "ProcessScanData: $result"
                }
            }
        }
        lappend fileList $tmpRoot.$readback
    }
    APSAddToTmpFileList -ID gainmeasure -fileList $fileList
    APSAddToTmpFileList -ID gainmeasure -fileList $outputFile.1
    if [llength $fileList]>1 {
        if [catch {eval exec sddsxref $fileList $outputFile.1 -leave=$actuatorPV -transfer=par,*slope,*offset } result] {
            return -code error "ProcessScanData: $result"
        }
    } else {
        file copy [lindex $fileList 0] $outputFile.1
    }
    
    if !$reprocess {
	set comment [APSMakeSafeQualifierString $Comment]
    } else {
	set comment [exec sdds2stream $filename -par=Comment]
	set commane [APSMakeSafeQualifierString $comment]
    }
    if [catch {exec sddsprocess $outputFile.1 $outputFile \
		   "-reprint=par,Comment,$comment" } result] {
	return -code error $result
    }
    file delete -force $outputFile.1
    SetMainStatus "Processing done."
}

proc ListCommand {args} {
    global fileList AddComment
    set action ""
    APSParseArguments {files action}
    set chosenList [.review.userFrame.sl.listbox curselection]
    if ![llength $chosenList] {
        return -code error "No files are chosen!"
    }
    set viewList ""
    foreach index $chosenList {
        set file [lindex $fileList $index]
        set expfile [file rootname $file]
        switch $action {
            process {
                ProcessScanData -filename $file -reprocess 1
            }
            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?"] {
                    catch {eval file delete -force $file $file.mon $file.proc}
                }
            }
            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 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 PlotAndInstallScanData {args} {
    set filename ""
    APSParseArguments {filename}

    if {![file exist $filename]} {return -code error "$filename does not exist!"}
    if ![file exist $filename.proc] {
        if [catch {ProcessScanData -filename $filename} result] {
            return -code error $result
        }
    }
    set parameterNames [exec sddsquery $filename.proc -par]
    global Offset Gain BeamlineSelection actuatorPV

    if [info exist Offset] {unset Offset}
    if [info exist Gain] {unset Gain}
    set tmpfile /tmp/[APSTmpString].printout
    APSAddToTmpFileList -ID gainmeasure -fileList $tmpfile
    set fd [open $tmpfile w]
    puts $fd "Gain and Offset printout for $filename\n"
    set nameList ""
    foreach par $parameterNames {
        if [string match "*_offset" $par] {
            regexp {(.*)\_offset} $par a b
            set Offset($b) [exec sdds2stream $filename.proc -par=$par]
        }
        if [string match "*_slope" $par] {
            regexp {(.*)\_slope} $par a b
            lappend nameList $b
            set Gain($b) [exec sdds2stream $filename.proc -par=$par]
            if {$Gain($b)==0} {
                return -code error "The gain of $b is zero, data takiing failed or file $filename is corrupted, can not process it.!"
            }
        }
    }
    if [lsearch $parameterNames Comment]>=0 {
	set comment [exec sdds2stream $filename.proc -par=Comment]
    } else {
	set comment ""
    }
    set requests ""
    set otherRequests ""
    set index 1
    puts $fd "Comment: $comment\n"
    foreach name $nameList {
        puts $fd "$name: slope=[format %.3f $Gain($name)]   offset=[format %.3f $Offset($name)] \n"
        switch $BeamlineSelection {
            Lab1 -
            Lab2 -
            PTB -
            LTP -
            LINACL2 {
                lappend requests -layout=1,1 -sep=3 -legend 
            } 
            default {
                lappend requests -layout=1,1 -sep=2 -legend
            }
        }
        lappend requests -col=$actuatorPV,$name $filename.proc -graphic=symbol,scale=2,sub=1 -string=$name,p=0.4,q=0.7
        lappend requests -col=$actuatorPV,${name}Fit $filename.proc -graphic=line,type=1
        switch $BeamlineSelection {
            Lab2 {
                lappend requests -col=$actuatorPV,Reference $filename.proc -graphic=sym,conn,scale=2,sub=2,type=2
            }
            Lab1 -
            PTB -
            LTP -
            LINACL2 -
            LINACL3 -
            LINACL4 -
            LINACL5 {
                lappend requests -col=$actuatorPV,Reference $filename.proc -graphic=sym,conn,scale=2,sub=2,type=2
                lappend otherRequests -col=$actuatorPV,${name}Diff -graphic=line,type=$index 
            }
        }
        incr index
    }
    global gainPVList offsetPVList gainValList offsetValList
    if [catch {CalculateGainAndOffset -nameList $nameList} result] {
	return -code error $result
    }
    foreach gainpv $gainPVList gain $gainValList offsetpv $offsetPVList offset $offsetValList {
	puts $fd "$gainpv=[format %.3f $gain]       $offsetpv=[format %.3f $offset]\n"
    }
    close $fd
    DisplayFile -filename $tmpfile
    #plot raw and fit data
    eval exec sddsplot $requests &
    switch $BeamlineSelection {
        Lab1 -
        PTB -
        LTP -
        LINACL2 -
        LINACL3 -
        LINACL4 -
        LINACL5 {
            eval exec sddsplot $filename.proc -legend -layout=1,1 $otherRequests &
        }
    }
}
proc DisplayFile {args} {
    set filename ""
    APSParseArguments {filename}
    set w .[APSUniqueName printout]
    APSFileDisplayWindow $w -fileName $filename -width 80 -printCommand "enscript -r"
    APSDialogBoxAddButton .install -parent $w -text "Install..." \
      -command "InstallGainAndOffset" -contextHelp "click to install the measured gain and offset."   
}

proc CalculateGainAndOffset {args} {
    global BeamlineSelection Gain Offset refGain refOffset gainPVList offsetPVList gainValList offsetValList
    set nameList ""
    APSParseArguments {nameList}
    
    set gainPVList ""
    set offsetPVList ""
    set gainValList ""
    set offsetValList ""

    foreach name $nameList {
	if [string match "*RAW" $name] {
	    continue
	}
        set gain $Gain($name)
        set offset $Offset($name)
        switch $BeamlineSelection {
            Lab2 -
            Lab1 -
            PTB  -
            LTP -
            LINACL2 -
            LINACL3 -
            LINACL4 -
            LINACL5 {
                if [regexp {(.*)OPV} $name a PV] {
                    #TOPV top
                    set gainPV ${PV}GAI
                    set offsetPV ${PV}OFF
                } elseif [regexp {(.*)OTV} $name a PV] {
                    #BOTV bottom
                    set gainPV ${PV}GAI
                    set offsetPV ${PV}OFF
                } elseif [regexp {(.*)FTV} $name a PV] {
                    #LFTV left
                    set gainPV ${PV}GAI
                    set offsetPV ${PV}OFF
                } elseif [regexp {(.*)HTV} $name a PV] {
                    #RHTV right
                    set gainPV ${PV}GAI
                    set offsetPV ${PV}OFF
                } else {
                    set gainPV ${name}:P:GainC
                    set offsetPV ${name}:P:TestC
                }
                if [catch {exec cavget -list=$gainPV -pend=10} currGain] {
                    return -code error $prevGain
                }
                if [catch {exec cavget -list=$offsetPV -pend=10} currOffset] {
                    return -code error $prevOffset
                }
                if {$currGain=="?" || $currOffset=="?"} {
                    return -code error "Can not obtian value of $gainPV or $offsetPV!"
                } 
                set gain [expr $refGain/$Gain($name) * $currGain ]
                set offset [expr $refOffset - ($Offset($name)-$currOffset)/$currGain * $gain ]
            }
            BTS {
                set gainPV ${name}:GainAO
                set offsetPV ${name}:OffsetAO
            }
            default {
                return -code error "Unknown beamline: $BeamlineSelection"
            }
        }
	lappend gainPVList $gainPV
	lappend gainValList $gain
	lappend offsetPVList $offsetPV
	lappend offsetValList $offset
    }
}
proc InstallGainAndOffset {args} {
    global BeamlineSelection gainPVList gainValList offsetPVList offsetValList
    foreach gainPV $gainPVList gain $gainValList offsetPV $offsetPVList offset $offsetValList {
        if ![APSYesNoPopUp "Are you sure to install: \n $gainPV=$gain \n $offsetPV=$offset ?"] {
            SetMainStatus "The gain and offset for $gainPV, $offsetPV is not installed."
        } else {
            if [catch {exec cavput -list=$gainPV=$gain -pend=30 
                exec cavput -list=$offsetPV=$offset -pend=30 } result] {
                return -code error $result
            }
        }
    }
}


APSScrolledStatus .status -parent .userFrame -width 60 \
  -textVariable ControlStatus
MakeBeamlineWidget .beam -parent .userFrame
MakeOptionFrame .options -parent .userFrame
MakeActionFrame .action -parent .userFrame
