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

#
# $Log: not supported by cvs2svn $

#requested by Nick Sereno
#Make application to calibrate a user selectable PAR bpm sum signal to read charge.
#P:bpmSum:SelectC is the PV used to select the bpm. See the PAR daily log 
#/home/helios/PAR/daily/0407/12/2 for details on the calibration procedure 
#using the PTB current monitor. User should be able to select which CM to 
#use for calibration (either LTP or PTB current monitor).

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


set CVSRevisionAuthor "\$Revision: 1.1 $ \$Author: shang $"

APSApplication . -name PARBPMChargeCalibration -version $CVSRevisionAuthor \
  -overview {This application calibrates a user selectable PAR bpm sum signal calibrate the charge.}

set Status "ready."
APSScrolledStatus .status -parent .userFrame -textVariable\
  Status -width 50 -height 10 -packOption {-side top}  -withButtons 1

proc SetMainStatus {text} {
    global Status
    set Status $text
    update
}
proc MakeOptionFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    global SumBPMSelection SumBPMSelectionList StartFactor EndFactor Steps
    global Interval Average CurrentSelection PauseAfterChange

    APSFrame $widget -parent $parent 
    set w $parent$widget.frame
    APSRadioButtonFrame .bpm -parent $w -label "Ram BPM Sum PV:" -variable SumBPMSelection \
      -buttonList $SumBPMSelectionList -valueList $SumBPMSelectionList -limitPerRow 4 \
      -contextHelp "Select the bpm used in measurement for charge calibration."
    
    APSFrameGrid .fg -parent $w -xList {x1 x2}
    set w1 $w.fg.x1
    set w2 $w.fg.x2
    APSLabeledEntry .start -parent $w1 -label "Start Factor:" -textVariable StartFactor \
      -width 10 -contextHelp "input the starting value of varing factor"
    APSLabeledEntry .end -parent $w2 -label "End Factor: " -textVariable EndFactor \
      -width 10 -contextHelp "input the end value of varing factor"
    APSLabeledEntry .steps -parent $w1 -label "Steps: " -textVariable Steps \
      -width 10 -contextHelp "enter the steps for experiemnt, i.e., the number of steps for varying the factor from StartFactor to EndFactor."
    APSLabeledEntry .ave -parent $w2 -label "Average: " -textVariable Average \
      -width 10 -contextHelp "enter the number of average for measurement"
    APSLabeledEntry .interval -parent $w1 -label "Interval (s): " -textVariable Interval \
      -width 10 -contextHelp "Enter the interval time in seconds between two readings."
    APSLabeledEntry .pause -parent $w2 -label "Pause After Change (s): " -textVariable PauseAfterChange \
      -width 10 -contextHelp "Enter the time in seconds that pauses after changing the factor."
    APSRadioButtonFrame .current -parent $w1 -label "Current Selection: " -variable \
      CurrentSelection -buttonList {PTB LTP} -valueList {PTB LTP} -orientation horizontal \
      -contextHelp "selection PTB or LTP current for using in charge calibration."
}

proc MakeExecutionFrame {widget args} {
    set parent ""
    APSParseArguments {parent}

    APSFrame $widget -parent $parent 
    set w $parent$widget.frame
    APSButton .run -parent $w -text "RUN" -command "TakeData" -contextHelp \
      "take measurement and display the calibration at the end."
    APSButton .install -parent $w -text "INSTALL" -command "Install" -contextHelp \
      "install the calibration measured in the experiment."
}

proc TakeData {args} {
    
    global inputDir Average StartFactor EndFactor Steps Interval
    global SumBPMSelection scanDone Average PauseAfterChange
    
    set output /tmp/[APSTmpString].$SumBPMSelection
    APSAddToTmpFileList -ID chargecal -fileList $output
    set macro "-macro=monitorFile=$inputDir/ChargeTemplate.mon,start=$StartFactor,end=$EndFactor,steps=$Steps,interval=$Interval,average=$Average,pause=$PauseAfterChange"
    #set Ram BPM sum PV
    foreach pv {PTB LTP} {
        if [catch {exec cavget -list=${pv}:FCM:qTotalAI.VAL -pend=10} current] {
            SetMainStatus "Error in reading value of ${pv}:FCM:qTotalAI.VAL : $current"
            return
        }
        if {$current<0.3} {
            SetMainStatus "The $pv current is less than 0.3 nC, experiment is cancelled."
            return
        }
    }
    if [catch {exec cavput -list=P:bpmSum:SelectC=$SumBPMSelection -pend=10} result] {
        SetMainStatus "Error in setting value of P:bpmSum:SelectC: $result"
        return
    }
    if [catch {exec cavget -list=P:bpmSum:SelectC -pend=10} bpmSum] {
        SpetMainStatus "Error in reading value of P:bpmSum:SelectC: $bpmSum"
        return
    }
    if [string compare $bpmSum $SumBPMSelection] {
        SetMainStatus "The sum bpm (P:bpmSum:SelectC) was not able to set to $SumBPMSelection!"
        return
    }
    SetMainStatus "taking data ..."
    set scanDone 0
    APSExecLog .jon -width 80 -unixCommand "sddsexperiment $inputDir/ChargeScanTemplate.exp $output -verbose $macro " \
      -callback "set scanDone done" \
      -abortCallback "set scanDone abort" \
      -cancelCallback "set scanDone cancel"
    if !$scanDone {
        tkwait variable scanDone
    }
    switch $scanDone {
        done {
            PostProcessScan -file $output -bpm $SumBPMSelection
        }
        abort {
            SetMainStatus "Scan Aborted!"
        }
        cancel {
            SetMainStatus "Scan Canceled!"
        }
    }
}

proc PostProcessScan {args} {
    set file ""
    set bpm ""
    global CurrentSelection InstallFactor
    APSParseArguments {file bpm}
    
    if ![file exist $file] {
        return -code error "$file does not exist!"
    }
    APSAddToTmpFileList -ID chargecal -fileList "$file.1 $file.fit"
    if [catch {exec sddsprocess $file ${file}.1 -process=PTBCurrent,average,PTB \
                 -process=LTPCurrent,average,LTP } result] {
        return -code error $result
    }
    if [catch {exec sddspfit $file.1 $file.fit -terms=2 -generate \
                 -col=Factor,BPMCharge} result] {
        return -code error $result
    }
    exec sddsplot $file.fit -legend -col=Factor,BPMCharge -graph=sym,scale=2 \
      -col=Factor,BPMChargeFit -graph=line,type=1 &
    set current [exec sdds2stream -par=$CurrentSelection $file.1]
    set slope [exec sdds2stream -par=Slope $file.fit]
    set intercept [exec sdds2stream -par=Intercept $file.fit]
    set factor [expr ($current - ($intercept / 1000.0)) / ($slope)]
    SetMainStatus "The calibrated factor is $factor."
    if [APSYesNoPopUp "The calibrated factor from $bpm is $factor, install it now?"] {
        set InstallFactor($bpm) $factor
        if [catch {Install} result] {
            return -code error $result
        }
    }
    SetMainStatus "done."
}

proc Install {args} {
    global InstallFactor SumBPMSelection
    
    if ![info exist InstallFactor($SumBPMSelection)] {
        SetMainStatus "The factor was not calibrated through $SumBPMSelection bpm."
        return
    }
    set factor [set InstallFactor($SumBPMSelection)]
    if ![APSYesNoPopUp "Confirm: install the factor (P:bpmSum:FactorP) to $factor?"] {
        SetMainStatus "Installation was cancelled."
        return
    }
    if [catch {expr $factor / 2.0} result] {
        return code error "The value of factor to be installed should be numeric"
    }
    if [catch {exec cavput -list=P:bpmSum:FactorP=$factor -pend=10} result] {
        return -code error $result
    }
    SetMainStatus "P:bpmSum:FactorP was set to $factor"  
}

set SumBPMSelection P1P1
set SumBPMSelectionList {P1P1 P1P2 P1P3 P1P4 P2P1 P2P2 P2P3 P2P4 P3P1 P3P2 P3P3 P3P4}
set StartFactor 0
set EndFactor 1
set Steps 15
set Average 10
set PauseAfterChange 1.0
set Interval 0.5
set CurrentSelection PTB
set inputDir /home/helios/oagData/par/chargeCalibration/inputFiles

MakeOptionFrame .option -parent .userFrame
MakeExecutionFrame .exe -parent .userFrame