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

# $Log: CPUorbitCollection,v $
# Revision 1.20  2011/10/02 21:17:40  xiaoam
# Fix a bug
#
# Revision 1.19  2011/10/02 20:59:57  xiaoam
# Add more auto setting stuff.
#
# Revision 1.18  2011/05/30 16:38:29  lemery
# Added emacs tcl-mode local variables at end of file.
#
# Revision 1.17  2010/09/17 20:09:56  soliday
# No changes.
#
# Revision 1.16  2010/09/17 17:02:14  xiaoam
# Change the write permission.
#
# Revision 1.15  2010/05/26 23:20:41  xiaoam
# Change access priviladge
#
# Revision 1.14  2010/05/26 23:16:22  xiaoam
# *** empty log message ***
#
# Revision 1.13  2010/05/11 23:37:00  xiaoam
# Add coupling plot command. Make the script run more automatically.
#
# Revision 1.12  2009/10/02 18:07:01  xiaoam
# *** empty log message ***
#
# Revision 1.11  2009/10/02 18:00:19  xiaoam
# Fix an error in comment.
#
# Revision 1.9  2009/10/02 17:53:58  xiaoam
# Fix an error in comment.
#
# Revision 1.8  2009/05/23 05:40:00  xiaoam
# Change average frame value to 30
#
# Revision 1.7  2009/01/28 04:57:07  emery
# Fixed the problem with the check buttons for emittance plot.
#
# Revision 1.6  2008/01/23 01:46:08  emery
# Sorted file list for display.
#
# Revision 1.5  2007/09/25 21:52:34  emery
# Added processing of individual bpm rms variation.
# This data can be used for selecting bad bpms.
#
# Revision 1.4  2007/03/15 20:48:56  emery
# Removed debugging tee commands.
# Added emittance vs time and coil plots.
#
# Revision 1.3  2006/05/29 19:11:40  emery
# Added plot options. Reordered buttons.
#
# Revision 1.2  2006/05/29 17:19:47  emery
# Added if statement to avoid adding a blank space to badBPMs
# variable when no additional bad bpms are entered in the GUI.
#
# Revision 1.1  2004/05/23 15:26:24  emery
# First installation of renamed application. The old name was SRCollectBPMwCPU.
#

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)]

APSStandardSetup

set CVSRevisionAuthor "\$Revision: 1.20 $ \$Author: xiaoam $"

APSApplication . -name "CPUorbitCollection" -version \
  $CVSRevisionAuthor -overview "Collects orbit readbacks while the ID4 CPU is ramping in DC mode. The rms of the global orbit error can be plotted against the setpoint of the CPU."

proc MakeInputFrame {widget args} {
    set parent ""

    APSStrictParseArguments {parent}

    set outputDir .
    APSFrame $widget -parent $parent -label "Input parameters"
    set w $parent$widget.frame
    APSLabeledEntry .outputDir -parent $w \
      -label "Output directory:" -textVariable outputDir \
      -contextHelp "Enter a name for the output file directory." -width 50
    APSButton .daily -parent $w.outputDir -packOption "-anchor e" \
      -text "daily" -size small \
      -command {set outputDir [APSGoToDailyDirectory -subdirectory CPU]}
    APSLabeledEntry .comment -parent $w -label "Comment: " -textVariable comment \
      -width 55 \
      -contextHelp "Enter a comment to be written as a parameter to the output file."

    APSLabeledEntry .interval -parent $w -label "Interval (s): " -textVariable interval \
      -contextHelp "Interval of SDDSmonitor."
    APSLabeledEntry .bad -parent $w -label "Bad bpms: " \
      -textVariable additionalBad \
      -width 55 \
      -contextHelp "Bad bpm list separated by blanks."
    APSLabeledEntry .rate -parent $w -label "Ramp Step: " \
      -textVariable rate \
      -width 55 \
      -contextHelp "Ramp step for main coils s/step."
    APSCheckButtonFrame .dp -parent $w \
      -label "DP/RTFB On/Off: " \
      -variableList {DPOn RTFBOn} \
      -buttonList {"DP On" "RTFB On" } \
      -orientation horizontal
}

proc MakePlotOptionFrame {widget args} {
    set parent ""

    APSStrictParseArguments {parent}

    APSFrame $widget -parent $parent -label "Plot Options" 
    set w $parent$widget.frame
    APSCheckButtonFrame .options -parent $w \
      -label "Data to plot:    " \
      -packOption "-side top" \
      -variableList {doOrbitVsTimePlots doOrbitVsCoilPlots doCorrectorVsTimePlots doCorrectorVsCoilPlots doEmittanceVsTimePlots doEmittanceVsCoilPlots doCouplingVsTimePlots doCouplingVsCoilPlots} \
      -buttonList {"Orbit rms vs Time" "Orbit rms vs Coil" "Correctors rms vs Time" "Correctors vs Coil" "Emittance vs Time" "Emittance vs Coil" "Coupling vs Time" "Coupling vs Coil"} \
      -orientation vertical 
    APSRadioButtonFrame .coilChoice -parent $w -label "Coil to plot against:" \
      -packOption "-side top" \
      -variable coil \
      -buttonList {"V coil" "H coil"} \
      -valueList {Vcoil Hcoil} \
      -orientation vertical \
      -contextHelp "Choose the coil against which to plot the data."
}

proc CollectData {args} {
    APSParseArguments {outputDir interval comment abortVar}
    global $abortVar mode rate DPOn RTFBOn

    #0) Suspend DP and open RTFB loops.
    if {!$DPOn} {
        if [catch {exec cavput -list=S: \
                     -list=OrbitControlLawX,OrbitControlLawY,rfFreqControlLaw \
                     -list=RC.SUSP=1 \
                 } result ] {
            return -code error "$result"
        }
        if [catch {exec cavput -list=DP:S: \
                     -list=OrbitControlLawX,OrbitControlLawY \
                     -list=SDDS.SUSP=1 \
                 } result ] {
            return -code error "$result"
        }
    }
    global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz apshpFilterRampPoints apshpFilterRampInterval
    APSMpSetRTFBGlobalParameters -readonly 1
    if {!$RTFBOn} {
        if [catch {APSMpRTFBResetOpenLoops -hpFilterInitialVert $apshpFilterInitialVert \
                     -hpFilterInitialHoriz $apshpFilterInitialHoriz \
                     -runHloop 1 -runVloop 1 } result] {
            return -code error "$result"
        }
    }
    #1) Set up measurement
    exec cavput -list=S:VID1:numToAvgC=30
    exec cavput -list=ID04b:rate_=$rate -list=up,down
    set maxIList [exec sddsprocess /home/helios/oagData/sr/IDs/CPU/DCmodes/default -pipe=out \
        "-redef=col,I,I abs" -proc=I,maximum,Imax \
        | sdds2stream -para=Imax -pipe=in]
    switch $mode {
        2 {
            set mainPV  "ID04b:set_H_coil.VAL"
            set Imax [lindex $maxIList 2]
        }
        3 {
            set mainPV  "ID04b:set_V_coil.VAL"
            set Imax [lindex $maxIList 3]
        }
        default {
            set mainPV  "ID04b:set_H_coil.VAL"
            set Imax [lindex $maxIList 0]
        }
    }   
    exec cavput -list=ID04b:DesiredMode=$mode
    exec cavput -list=$mainPV=0
    exec cawait -interval=0.5 -waitFor=ID04b:feedback.VAL,sameAs=Ready

    #2) start measurement
    if [string match $comment ""] {set comment [lindex [exec caget ID04b:DesiredMode.VAL] 1]}
    if {![string length $outputDir] } {
        APSSetVarAndUpdate status "Output directory or root not given."
        return
    }
    
    set dir [pwd]
    cd $outputDir
    set monFile /home/helios/oagData/sr/IDs/CPU/DCmodes/CPU+orbit.mon
    APSSetVarAndUpdate status "Launching sddsmonitor..."
    if [catch {set pid [exec sddsmonitor $monFile CPU+orbit -daily \
                          -step=1200 -interval=$interval \
                          "-comment=Comment,[APSMakeSafeQualifierString $comment]" &] \
             } result ] {
        APSSetVarAndUpdate status $result
        return
    }
    APSSetVarAndUpdate status "sddsmonitor launched..."
    update
    cd $dir

    if (![set $abortVar]) {after 10000}
    exec cavput -list=$mainPV=$Imax
    while (1) {
       after 1000
       if ([string match "*Ready*" [exec cavget -list=ID04b:feedback.VAL]]) break
       if ([set $abortVar]) break
    }
    if (![set $abortVar]) {after 10000}
    exec cavput -list=$mainPV=0
    while (1) {
       after 1000
       if ([string match "*Ready*" [exec cavget -list=ID04b:feedback.VAL]]) break
       if ([set $abortVar]) break
    }
    if (![set $abortVar]) {after 10000}
    APSSetVarAndUpdate status "Killing sddsmonitor..."
    if [catch {exec kill -KILL $pid} result] {
        APSSetVarAndUpdate status $result
    }
    if ([set $abortVar]) {
       exec cavput -list=$mainPV=0
       exec cawait -interval=0.5 -waitFor=ID04b:feedback.VAL,sameAs=Ready 
       set $abortVar 0
    }
    #) Resume DP and RTFB
    if [catch {exec cavput -list=DP:S: \
                 -list=OrbitControlLawX,OrbitControlLawY \
                 -list=SDDS.SUSP=0 \
             } result ] {
        return -code error "$result"
    }
    if [catch {APSMpRTFBCloseLoops -hpFilterCutoffVert $apshpFilterCutoffVert \
                 -hpFilterCutoffHoriz $apshpFilterCutoffHoriz \
                 -hpFilterInitialVert $apshpFilterInitialVert \
                 -hpFilterInitialHoriz $apshpFilterInitialHoriz \
                 -hpFilterRampPoints $apshpFilterRampPoints \
                 -hpFilterRampInterval $apshpFilterRampInterval } result] {
        return -code error "$result"
    }
    #) set rate back to default value 0.5s/step
    exec cavput -list=ID04b:rate_=0.5 -list=up,down
}

proc PlotData {args} {
    global outputDir
    set coil Hcoil
    set doOrbitVsTimePlots 0
    set doOrbitVsCoilPlots 1
    set doCorrectorVsTimePlots 0
    set doCorrectorVsCoilPlots 0
    set doEmittanceVsTimePlots 0
    set doEmittanceVsCoilPlots 0
    set doCouplingVsTimePlots 0
    set doCouplingVsCoilPlots 1
    APSParseArguments {coil doOrbitVsTimePlots doOrbitVsCoilPlots doCorrectorVsTimePlots doCorrectorVsCoilPlots doEmittanceVsTimePlots doEmittanceVsCoilPlots \
	 doCouplingVsTimePlots doCouplingVsCoilPlots}
    set dir [pwd]
    cd $outputDir
    set root CPU+orbit
    set fileList [lsort [glob -nocomplain $root-????-???-????.????.rowstats]]
    if ![llength $fileList] {
        APSSetVarAndUpdate status "No files match $root-????-???-????.????.rowstats"
        return -code error "No files match $root-????-???-????.????.rowstats"
    }
    set dataList [APSChooseItemFromList \
                     -name "Data Set Selection" \
                     -itemList $fileList \
                     -returnList $fileList \
                     -returnIndices 0 \
                     -multiItem 1 \
                     -contextHelp "Select one or more files for plotting."]

    set options "-layout=1,2 -axes=x"
    if {[llength $dataList] > 1} {
        lappend options -layout=1,2
    }
    foreach file $dataList {
        APSSetVarAndUpdate status "Plotting $file..."
        # overlay orbit with Coil readback
        set root [file root $file]
        if $doOrbitVsTimePlots {
            lappend options -col=Time,?OrbitRMS $file -topline=@Comment -file \
              -tick=xtime -factor=ymult=1e3 \
              {-ylabel=RMS Orbit (um)} -grap=line,vary -leg
            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $file -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
            lappend options -col=Time,*30HzBW $root -topline=@Comment -file \
              -tick=xtime \
              {-ylabel=30 Hz (um)} -grap=line,vary -leg
            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $root -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
            lappend options -col=Time,*VarBW $root -topline=@Comment -file \
              -tick=xtime \
              {-ylabel=100 Hz (um)} -grap=line,vary -leg
            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $root -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
            lappend options -col=Time,*FullBW $root -topline=@Comment -file \
              -tick=xtime \
              {-ylabel=Full BW (um)} -grap=line,vary -leg
            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $root -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
        }
        if $doOrbitVsCoilPlots {
            lappend options -col=${coil}Readback,?OrbitRMS $file -topline=@Comment -file \
              -factor=ymult=1e3 \
              {-ylabel=RMS Orbit (um)} -grap=line,vary -leg -end
            lappend options -col=${coil}Readback,*30HzBW $root -topline=@Comment -file \
              {-ylabel=30 Hz (um)} -grap=line,vary -leg -end
            lappend options -col=${coil}Readback,*VarBW $root -topline=@Comment -file \
              {-ylabel=100 Hz (um)} -grap=line,vary -leg -end
            lappend options -col=${coil}Readback,*FullBW $root -topline=@Comment -file \
              {-ylabel=Full BW (um)} -grap=line,vary -leg -end
       }
        if $doCorrectorVsTimePlots {
            # vertical plane
            lappend options -col=Time,(*S4A:H2*,*S4A:H3:DacAI,*S4B:H2*,*S5A:H2*,*S5A:H3:DacAI,*S5B:H2*) \
              {-ylabel=Horizontal Correctors (A)} \
              $file -topline=@Comment -file -tick=xtime -grap=line,vary \
              -leg -mode=y=offset -axes=x

            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $file -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end

            #horizontal plane
            lappend options -col=Time,(*S4A:V2*,*S4A:V3:DacAI,*S4B:V4*,*S5A:V2*,*S5A:V3:DacAI,*S5B:V4*) \
               {-ylabel=Vertical Correctors (A)} \
              $file -topline=@Comment -file -tick=xtime -grap=line,vary \
              -leg -mode=y=offset -axes=x

            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $file -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
        }
        if $doCorrectorVsCoilPlots {
             lappend options -col=${coil}Readback,(*S4A:H2*,*S4A:H3:DacAI,*S4B:H2*,*S5A:H2*,*S5A:H3:DacAI,*S5B:H2*) \
               {-ylabel=Horizontal Correctors (A)} \
              $file -topline=@Comment -file -grap=line,vary \
              -leg -mode=y=offset -axes=x  -end

             lappend options -col=${coil}Readback,(*S4A:V2*,*S4A:V3:DacAI,*S4B:V4*,*S5A:V2*,*S5A:V3:DacAI,*S5B:V4*) \
               {-ylabel=Vertical Correctors (A)} \
              $file -topline=@Comment -file -grap=line,vary \
              -leg -mode=y=offset -axes=x -end
        }
        if $doEmittanceVsTimePlots {
            lappend options -col=Time,xEmittance $file -topline=@Comment -file \
              -tick=xtime  \
              -grap=line,vary -leg -yscale=id=xemit
            lappend options -col=Time,yEmittance $file -topline=@Comment -file \
              -tick=xtime  \
              -grap=line,vary -leg -yscale=id=yemit
            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $file -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
        }
        if $doEmittanceVsCoilPlots {
            lappend options -col=${coil}Readback,xEmittance $file -topline=@Comment -file \
              -grap=line,vary -leg -yscale=id=xemit 
            lappend options -col=${coil}Readback,yEmittance $file -topline=@Comment -file \
               -grap=line,vary -leg -yscale=id=yemit -end
        }
        if $doCouplingVsTimePlots {
            lappend options -col=Time,coupling $file -topline=@Comment -file \
              -tick=xtime  \
              -grap=line,vary -leg -yscale=id=coup
            lappend options -col=Time,${coil}Readback -tick=xtime -factor=ymult=-1 \
              $file -topline=@Comment -file -ylabel=edit=ei/(A)/ \
              -grap=line,type=2 -yscale=id=${coil} -end
        }
        if $doCouplingVsCoilPlots {
            lappend options -col=${coil}Readback,coupling $file -topline=@Comment -file \
              -grap=line,vary -leg -yscale=id=coupling
        }
     }
    if [catch {eval exec sddsplot \
                 $options & \
             } result] {
        APSSetVarAndUpdate status "PlotData: $result"
        return
    }
    if [catch {eval exec sddsplot $options & \
             } result] {
        APSSetVarAndUpdate status "PlotData: $result"
        return
    }
    APSSetVarAndUpdate status "Done."
    cd $dir
    return
}

proc ProcessData {} {
    global outputDir additionalBad

    set dir [pwd]
    cd $outputDir
    set root CPU+orbit
    set fileList [lsort [glob -nocomplain $root-????-???-????.????]]
    if ![llength $fileList] {
        APSSetVarAndUpdate status "No files match $root-????-???-????.????"
        return -code error "No files match $root-$year-$julian-$month$day.????"
    }
    set dataList [APSChooseItemFromList \
                     -name "Data Set Selection" \
                     -itemList $fileList \
                     -returnList $fileList \
                     -returnIndices 0 \
                     -multiItem 1 \
                     -contextHelp "Select a file for plotting."]
    set badBPMs [exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds \
                   -pipe=out \
                   -filter=col,OkForDCOrbitCorrectionH,0,0,OkForDCOrbitCorrectionH,0,0,| \
                   | sdds2stream -pipe -col=DeviceName ]
    if {$additionalBad != "" } {
        append badBPMs " $additionalBad"
    }
    set badBPMs [split $badBPMs]
    foreach file $dataList {
        APSSetVarAndUpdate status "Processing $file..."
        exec sddsconvert $file -pipe=out \
          -dele=col,[join $badBPMs ,] \
          | sddsprocess -pipe \
          -process=S*:msAve:?:ErrorCC,first,%sFirst \
          -process=S*:msAve:?:ErrorCC,standarddeviation,%sStdDev \
          "-redef=col,%s,%s %sFirst -,sel=S*:msAve:?:ErrorCC" \
          | sddsrowstats -pipe=in \
          $file.rowstats \
          -standardDeviation=XOrbitRMS,S*:msAve:x:ErrorCC \
          -standardDeviation=YOrbitRMS,S*:msAve:y:ErrorCC 
    }
    APSSetVarAndUpdate status "Done."
    cd $dir
    return
}

set args $argv
set root ""
set interval 1
set outputDir .
set mode 0
set abortRun 0
set rate 2
set DPOn 0
set RTFBOn 0
#set additionalBad "S4?:P* S5?:P* S29A:P4* S13A:P0*  S23A:P* S32A:P4"
set additionalBad ""
set comment ""
APSParseArguments {outputDir interval comment}


set status "Working..."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 50
MakeInputFrame .input -parent .userFrame

APSRadioButtonFrame .mode -parent .userFrame -orientation horizontal \
      -label "CPU mode for measuring: " -variable mode \
      -limitPerRow 5 \
      -buttonList {CW CCW V H CW/CCW} \
      -valueList {0 1 2 3 4} \
      -commandList {"set coil Vcoil" "set coil Vcoil" \
                    "set coil Hcoil" "set coil Vcoil" "set coil Hcoil"} \
      -contextHelp \
      "Choose CPU mode for measurement."

APSButton .run -parent .userFrame -text Collect -command \
  { \
      APSDisableButton .userFrame.run.button 
      APSEnableButton .userFrame.stop.button
      catch {CollectData -outputDir $outputDir -comment $comment \
               -interval $interval -abortVar abortRun} status
      update idletasks
      APSDisableButton .userFrame.stop.button
      APSEnableButton .userFrame.run.button
      } \
          -contextHelp "Collects CPU DC main coils and BPM averaged data. Uses monitor file /home/helios/oagData/sr/IDs/CPU/DCmodes/CPU+orbit.mon"

APSButton .stop -parent .userFrame -text Abort -command \
  { \
      set abortRun 1
      APSDisableButton .userFrame.stop.button
      APSEnableButton .userFrame.run.button } \
  -contextHelp "Aborts run."

APSButton .process -parent .userFrame -text PROCESS... -command \
  ProcessData \
  -contextHelp "Selects and processes the data collected today."

APSButton .plot -parent .userFrame -text "PLOT..." -command \
  {PlotData -coil $coil -doOrbitVsTimePlots $doOrbitVsTimePlots \
     -doOrbitVsCoilPlots $doOrbitVsCoilPlots \
     -doCorrectorVsTimePlots $doCorrectorVsTimePlots \
     -doCorrectorVsCoilPlots $doCorrectorVsCoilPlots \
     -doEmittanceVsTimePlots $doEmittanceVsTimePlots \
     -doEmittanceVsCoilPlots $doEmittanceVsCoilPlots \
     -doCouplingVsTimePlots  $doCouplingVsTimePlots \
     -doCouplingVsCoilPlots  $doCouplingVsCoilPlots}\
  -contextHelp "Selects and plots the data collected today."


MakePlotOptionFrame .plotOptions -parent .userFrame
set coil Vcoil
set doOrbitVsTimePlots 0
set doOrbitVsCoilPlots 1
set doCorrectorVsTimePlots 0
set doCorrectorVsCoilPlots 0
set doEmittanceVsTimePlots 0
set doEmittanceVsCoilPlots 0
set doCouplingVsTimePlots 0
set doCouplingVsCoilPlots 1
set status Ready.
update


# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
