#!/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)]

set statusText ""
proc SetStatus { text } {
    global statusText
    set statusText "$text ([clock format [clock seconds] -format "%H:%M:%S"])"
    update
}

proc StartScan {args} {
    global aveType outputDir rootname adcSteps sleepTime initialValue finalValue plotOnly
    switch $aveType {
        msAve {
          set monFile /home/helios/oagData/sr/FPGAbpm/inputFiles/sr.all.ave.mon
        }
        mswAve {
          set monFile /home/helios/oagData/sr/FPGAbpm/inputFiles/sr.all.wave.mon
        }
    }
    if ![expr $adcSteps%2] {
        set adcSteps [expr $adcSteps +1]
    }
    set fpgaSectors [exec sdds2stream -col=Sector  /home/helios/oagData/sr/FPGAbpm/sectors.sdds]
    set tmpRoot /tmp/[APSTmpString]
    #adc change by 1 each step (delta=1)
    set initialValue [expr ((1 - ${adcSteps}) / 2)]
    set finalValue [expr ${initialValue} + ${adcSteps} -1]
    foreach sector $fpgaSectors {
        foreach bpm {A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2} {
            if [catch {exec replaceText /home/helios/oagData/sr/FPGAbpm/inputFiles/ADCscan.template.exp \
                         -orig=<bpm>,<initialValue>,<finalValue>,<steps> \
                         -repl=S${sector}$bpm,$initialValue,$finalValue,$adcSteps $tmpRoot.S${sector}$bpm } result] {
                return -code error $result
            }
            lappend fileList $tmpRoot.S${sector}$bpm
        }
    }
   
    set pause1 [expr 3.0*$sleepTime]
    if [catch {exec replaceText /home/helios/oagData/sr/FPGAbpm/inputFiles/ADCscan.template1.exp \
                 -orig=<monFile>,<pauseAfterChange>,<steps> \
                 -repl=$monFile,$sleepTime,$adcSteps $tmpRoot.mon} result] {
        return -code error $result
    }
    lappend fileList $tmpRoot.mon
    set timestring [clock format [clock seconds] -format %H%M%S]
    set expFile $outputDir/adcScan-${timestring}.exp
    set outputFile $outputDir/${rootname}-${timestring}.sdds
    if [catch {eval exec cat $fileList > $expFile} result] {
        return -code error $result
    }
    if $plotOnly {
        set opt -dryRun
    } else {
        set opt ""
    }
    APSExecLog .scan -width 80 -lineLimit 2048 -width 95 -height 30 -name "AdcScan" -lineLimit 2048 -unixCommand \
      "sddsexperiment $expFile $outputFile $opt -verbose" \
      -callback "ProcessFile -file $outputFile -initialValue $initialValue -finalValue $finalValue -steps $adcSteps -aveType $aveType" \
      -cancelCallback "set scanstatus cancelled" \
      -abortCallback "set scanStatus aborted"
    
}

proc PlotFiles {args} {
    global outputDir selectFile

    cd $outputDir
    set files [glob -nocomplain *.sdds]
    if ![llength $files] {
        SetStatus "no files found."
        return
    }
    APSScrolledListWindow .process -name "Select a file" \
      -label "Select File" \
      -itemList $files -selectionVar selectFile
    tkwait variable selectFile
    
    PlotData -file $outputDir/$selectFile

}

proc PlotData {args} {
    set file ""
    APSParseArguments {file}

    set aveType [lindex [exec sdds2stream -par=AveType $file.proc] 0]
    
    exec sddsplot  -layout=1,2 -split=page  ${file}.proc \
	-grap=line,vary -topT -groupby=page -sep=2 -subticksettings=xDivisions=5,yDivisions=5 \
	-ylabel=@BPMName  -drawline=x0par=StartDelay,x1par=StartDelay,q0value=0,q1value=0.8 \
	\
	-col=ADCDelay,${aveType}Pn:x -leg=spec=X  -col=ADCDelay,${aveType}Pn:y -leg=spec=Y  \
	"-title=NarrowBand Sum 200 Hz PVs" \
	-col=ADCDelay,${aveType}Pw:x  -leg=spec=X -col=ADCDelay,${aveType}Pw:y  -leg=spec=Y \
	"-title=WideBand Sum 5 kHz PVs"  &

    exec sddsplot -layout=2,1 $file.proc -leg -same=y -split=page -group=page -grap=line,vary -topT  \
      "-title=X Position Average Offset Data" \
      -col=ADCDeltaStep,*:xOffset    -end \
      "-title=Y Position Average Center Offset Data" \
      -col=ADCDeltaStep,*:yOffset -end &

    
     exec sddsplot  -split=page -layout=1,2  ${file}.proc \
      -grap=line,vary -topT -groupby=page -sep=2 -subticksettings=xDivisions=5,yDivisions=5 \
      -ylabel=@BPMName -drawline=x0par=StartDelay,x1par=StartDelay,q0value=0,q1value=0.95  \
      "-title=Position PVs" -col=ADCDelay,${aveType}:x  -leg=spec=X -col=ADCDelay,${aveType}:y  -leg=spec=Y  & 

    APSFileDisplayWindow .out -fileName $file.print -width 80 -height 30 -printCommand "enscript -r"
}

proc SelectFile {args} {
    global selectFile outputDir
    
    cd $outputDir
    set files [glob -nocomplain *.sdds.proc]
    if ![llength $files] {
        SetStatus "no files found."
        return ""
    }
    APSScrolledListWindow .process -name "select file " \
      -label "select a  file" \
      -itemList $files -selectionVar selectFile
    tkwait variable selectFile
    if ![string length $selectFile] {
        SetStatus "no file chosen."
        return ""
    }
    return $selectFile
}

set fitPoints 5
proc ReprocessFile {args} {
    global outputDir fitPoints
    
    set file1 [SelectFile]
    if ![string length $file1] {
        return
    }
    set tmpRoot /tmp/[APSTmpString]
    set file [file root $file1]
   
    if [catch {exec sddsconvert $file1 $tmpRoot.adc -retain=col,ADCDeltaStep -topage=1 } result] {
        return -code error $result
    }
    APSAddToTempFileList $tmpRoot.adc
    set cols [exec sddsquery $file -col | grep AvePw:x]
    
    set aveType [exec sdds2stream -par=AveType $tmpRoot.adc]
    set steps [exec sdds2stream -rows=bar $tmpRoot.adc]
    set delays [exec sdds2stream -col=ADCDeltaStep $tmpRoot.adc]
    set delta [expr [lindex $delays 1] - [lindex $delays 0]]
    if [expr $fitPoints%2]==0 {
        set fitPoints [expr $fitPoints +1]
    }
    set halfSteps [expr ($fitPoints-1)/2]
    set highDelta [expr $delta * $halfSteps]
    set lowDelta [expr -$delta * $halfSteps]
  
    foreach col $cols {
        if ![regexp {(.*):ms} $col a bpm c] {
            continue
        }
        lappend bpmList $bpm
        if [catch {exec sddsconvert $file -pipe=out \
                     -retain=col,*Time*,${bpm}* \
                     -edit=col,S*,%/${bpm}://%/${bpm}ADC/ADC/ \
                     | tee $tmpRoot.$bpm.1 \
                     | sddsxref -pipe $tmpRoot.adc -take=ADCDeltaStep \
                     | sddsprocess -pipe=in $tmpRoot.$bpm.cent \
                     -filter=col,ADCDeltaStep,-0.5,0.5 \
                     -process=*${aveType}:x,first,%sCent \
                     -process=*${aveType}:y,first,%sCent } result] {
            return -code error $result
        }
        APSAddToTempFileList $tmpRoot.$bpm.cent $tmpRoot.$bpm.1
        if [catch {exec sddsxref $tmpRoot.$bpm.1 $tmpRoot.$bpm.cent -leave=* -transfer=par,* -pipe=out \
                     | sddsxref -pipe $tmpRoot.adc -take=ADCDeltaStep \
                     | sddsprocess -pipe \
                     -reprint=par,AveType,$aveType \
                     -reprint=par,BPMName,$bpm \
                     -process=*ms*Ave*,min,%s_Min \
                     -process=*ms*Ave*,min,%s_MinADCDelay,functionof=ADCDelay,position \
                     "-redefine=col,%sOffset,%s %sCent -,select=*${aveType}:x" \
                     "-redefine=col,%sOffset,%s %sCent -,select=*${aveType}:y" \
                     -process=ADCDelay,first,StartDelay,functionof=ADCDeltaStep,lowerLimit=0,upperLimit=0 \
                     | sddsprocess -pipe=in $tmpRoot.$bpm \
                     -process=*Offset,slope,%sSlope,functionOf=ADCDeltaStep,lowerlimit=$lowDelta,upperLimit=$highDelta } result] {
            return -code error $result
        }
        lappend fileList $tmpRoot.$bpm
        APSAddToTempFileList $tmpRoot.$bpm
    }
    if [catch {eval exec sddscombine $fileList -over $file.proc } result] {
        return -code error "ProcessFile2: error combine files: $result"
    }
    if [catch {exec sddscollapse $file.proc $file.slope
        exec sddsoutlier $file.slope $file.slope.xfilt \
                 -col=${aveType}:xOffsetSlope -stDevLimit=2 -invert
        exec sddsoutlier $file.slope $file.slope.yfilt \
                 -col=${aveType}:yOffsetSlope -stDevLimit=2 -invert } result] {
        return -code error "ProcessFile3: $result"
    }
    
    if [catch {exec sddsprintout $file.slope.xfilt $tmpRoot.1 "-title=Horizontal BPMs with Slopes > 2 standard deviations from the mean.." \
                 -col=BPMName -col=${aveType}:xOffsetSlope
        exec sddsprintout $file.slope.yfilt $tmpRoot.2 "-title=\nVertical BPMs with Slopes > 2 standard deviations from the mean.." \
                 -col=BPMName -col=${aveType}:yOffsetSlope
        exec cat $tmpRoot.1 $tmpRoot.2 > $file.print } result] {
         return -code error "ProcessFile4: $result"
    }
    PlotData -file $file
}

proc ProcessFile {args} {
    set file ""
    set initialValue ""
    set finalValue ""
    set aveType ""
    set steps ""
    APSParseArguments {file initialValue finalValue aveType steps}
    global fitPoints
    
    set cols [exec sddsquery $file -col | grep AvePw:x]
    set option ""
    set bpmList ""
    set tmpRoot /tmp/[APSTmpString]
    set fileList ""
    if [expr $fitPoints%2]==0 {
        set fitPoints [expr $fitPoints +1]
    }
    set halfSteps [expr ($fitPoints-1)/2]
    set delta [expr ($finalValue - $initialValue)/($steps-1)]
    set highDelta [expr $delta * $halfSteps]
    set lowDelta [expr -$delta * $halfSteps]
    if [catch {exec sddsprocess $file $tmpRoot.1 "-redefine=col,ADCDeltaStep,$initialValue i_row $delta * +" } result] {
        return -code error $result
    }
    APSAddToTempFileList $tmpRoot.1
    foreach col $cols {
        if ![regexp {(.*):ms} $col a bpm c] {
            continue
        }
        lappend bpmList $bpm
        
        if [catch {exec sddsconvert $tmpRoot.1 -pipe=out \
                     -retain=col,*Time*,${bpm}*,ADCDeltaStep \
                     -edit=col,S*,%/${bpm}://%/${bpm}ADC/ADC/ \
                     | tee $tmpRoot.$bpm.1 \
                     | sddsprocess -pipe=in $tmpRoot.$bpm.cent \
                     -filter=col,ADCDeltaStep,-0.5,0.5 \
                     -process=*${aveType}:x,first,%sCent \
                     -process=*${aveType}:y,first,%sCent } result] {
            return -code error $result
        }
        APSAddToTempFileList $tmpRoot.$bpm.cent $tmpRoot.$bpm.1
        if [catch {exec sddsxref $tmpRoot.$bpm.1 $tmpRoot.$bpm.cent -leave=* -transfer=par,* -pipe=out \
                     | sddsprocess -pipe \
                     -reprint=par,AveType,$aveType \
                     -reprint=par,BPMName,$bpm \
                     -process=*ms*Ave*,min,%s_Min \
                     -process=*ms*Ave*,min,%s_MinADCDelay,functionof=ADCDelay,position \
                     "-redefine=col,%sOffset,%s %sCent -,select=*${aveType}:x" \
                     "-redefine=col,%sOffset,%s %sCent -,select=*${aveType}:y" \
                     -process=ADCDelay,first,StartDelay,functionof=ADCDeltaStep,lowerLimit=0,upperLimit=0 \
                     | sddsprocess -pipe=in $tmpRoot.$bpm \
                     -process=*Offset,slope,%sSlope,functionOf=ADCDeltaStep,lowerlimit=$lowDelta,upperLimit=$highDelta } result] {
            return -code error $result
        }
        lappend fileList $tmpRoot.$bpm
        APSAddToTempFileList $tmpRoot.$bpm
    }
    if [catch {eval exec sddscombine $fileList -over $file.proc } result] {
        return -code error "ProcessFile2: error combine files: $result"
    }
    
    if [catch {exec sddscollapse $file.proc $file.slope
        exec sddsoutlier $file.slope $file.slope.xfilt \
                 -col=${aveType}:xOffsetSlope -stDevLimit=2 -invert
        exec sddsoutlier $file.slope $file.slope.yfilt \
                 -col=${aveType}:yOffsetSlope -stDevLimit=2 -invert } result] {
        return -code error "ProcessFile3: $result"
    }
    
    if [catch {exec sddsprintout $file.slope.xfilt $tmpRoot.1 "-title=Horizontal BPMs with Slopes > 2 standard deviations from the mean.." \
                 -col=BPMName -col=${aveType}:xOffsetSlope
        exec sddsprintout $file.slope.yfilt $tmpRoot.2 "-title=\nVertical BPMs with Slopes > 2 standard deviations from the mean.." \
                 -col=BPMName -col=${aveType}:yOffsetSlope
        exec cat $tmpRoot.1 $tmpRoot.2 > $file.print } result] {
         return -code error "ProcessFile4: $result"
    }
    eval file delete -force $fileList
    PlotData -file $file
}

proc ChangeSleepTime {args} {
    global aveType sleepTime
    switch $aveType {
        msAve {
            set sleepTime 5
        } 
        mswAve {
            set sleepTime 30
        }
    }
}
set CVSRevisionAuthor "\$Revision: 1.6 $ \$Author: shang $"
APSApplication . \
  -name FPGAadcDelayScan \
  -version "$CVSRevisionAuthor" \
  -overview {LCLS experiment.}

APSScrolledStatus .status  \
  -parent .userFrame \
  -textVariable statusText \
  -width 60 \
  -height 8 \
  -withButtons 1 \
  -packOption "-fill both -expand true"

APSFrame .par -parent .userFrame -label "Setup Parameters"
APSFrameGrid .grid -parent .userFrame.par.frame -xList {x1 x2}
set w .userFrame.par.frame
set w1 $w.grid.x1
set w2 $w.grid.x2

set aveType msAve
set outputDir [APSGoToDailyDirectory -subdirectory  adcScan]
set outputDir .
set rootname fpgaAdcScan
set adcSteps 11
set sleepTime 5
set plotOnly 0
set fitPoints 5
set width 20
APSRadioButtonFrame .type -parent $w1 -variable aveType -buttonList {msAve mswAve} -valueList {msAve mswAve} -orientation horizontal \
  -label "BPM average type:" -commandList {ChangeSleepTime ChangeSleepTime}
APSRadioButtonFrame .plot -parent $w2 -variable plotOnly -buttonList {Yes No} -valueList {1 0} -orientation hoizontal \
    -contextHelp "if plot only is yes, then scan without changing the adc delays." -label "Plot only?" 
APSLabeledEntry .steps -parent $w1 -textVariable adcSteps -width $width -label "Scan steps:"
APSLabeledEntry .sleep -parent $w2 -textVariable sleepTime -width $width -label "Post change time(s):"
APSLabeledEntry .root -parent $w1 -textVariable rootname -width $width -label "Output rootname:"
APSLabeledEntry .fit -parent $w2 -textVariable fitPoints -width $width -label "Slope fit points (including delta step=0 point):" 

APSLabeledEntry .dir -parent .userFrame -textVariable outputDir -width 80 -label "Output directory:"
APSButton .daily -parent .userFrame.dir -packOption "-side right" -text "daily" -size small \
  -command "set outputDir [APSGoToDailyDirectory -subdirectory  adcScan]"


APSButton .scan -parent .userFrame -text "Start Scan" -command "StartScan"
APSButton .plot -parent .userFrame -text "Plot Data" -command "PlotFiles" 
APSButton .proc -parent .userFrame -text "Reprocess Data" -command "ReprocessFile"
