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

global hpvsaSelection

set hpvsaSelection hpvecsr
set hpSID ""
set outputRoot ""
set tunePlane y
set pauseRequested 0
set abortRequested 0
set resumeRequested 0
set setStatus ""

APSApplication . -name SRCheckChromSextupoles -version 1 \
  -overview {This application checks the chromaticity \
               contribution of S3 and S4 sextupoles.}

APSScrolledStatus .status -parent .userFrame -textVariable setStatus  \
  -width 100
set sextList {A:S1 A:S2 A:S3 A:S4 B:S3 B:S2 B:S1}
APSSRSectorButtons .sextButtons -parent .userFrame \
  -rootname sext \
  -orientation horizontal \
  -label "Sextupole selections" \
  -description "Sextupole selections" \
  -itemList $sextList -packOption "-side top" \
  -itemLabelList $sextList

APSFrame .controls -parent .userFrame -label "Experiment controls" \
  -packOption "-side top"
set w .userFrame.controls.frame
set outputDir [pwd]

APSRadioButtonFrame .tunePlane -parent .userFrame \
  -label "Tune measurement plane: " \
  -orientation horizontal \
  -variable tunePlane -buttonList {x/H y/V} \
  -valueList {x y} \
  -contextHelp "Choose the plane for tune \
                measurements. You must indicate to this script which tune \
                you've set up to measure.  Use x (y) tune when the beta \
                function is expected to be larger in the x (y) plane."

APSFrameGrid .output -parent $w -xList {x1 x2} -yList {y1 y2}

set w1 $w.output

APSLabeledEntry .dirname -parent $w1.x1.y1 \
  -label "Output directory: " \
  -textVariable outputDir -width 60 \
  -contextHelp "Enter the name of the directory \
                                       in which to put files."

APSButton .daily -parent $w1.x2.y1 -packOption "-side top -anchor e" \
  -text "Go to daily directory" \
  -command {set outputDir \
              [APSGoToDailyDirectory -subdirectory CheckChromSext]} \
  -contextHelp "Setting daily directory \
                                                 in which to put data files."

APSLabeledEntry .rootname -parent $w1.x1.y2 \
  -label "Output rootname: " \
  -textVariable outputRoot -width 60 \
  -contextHelp "Enter the rootname for the output \
                 files.  The sextupole name will be appended to the rootname \
                 to make filenames."

APSButton .run -parent $w -text Run \
  -contextHelp "Runs the measurements starting at the lowest \
                             numbered sectors and proceeding to higher \
                             numbered sectors." \
  -command "RunMeasurements $w"

APSButton .pause -parent $w -text Pause \
  -contextHelp "Pauses the present measurement." \
  -command "PauseMeasurement $w"

APSButton .resume -parent $w -text Resume \
  -contextHelp "Resumes measurements following a pause." \
  -command "ResumeMeasurement $w"

APSButton .abort -parent $w -text Abort \
  -contextHelp "Aborts the present measurement and all \
                               subsequent measurements." \
  -command "AbortMeasurement $w"

APSButton .parameters -parent $w -text "Parameters set" \
  -packOption "-side right" \
  -contextHelp "Choice of parameters." \
  -command choiceParameters

APSDisableButton $w.abort.button
APSDisableButton $w.pause.button
APSDisableButton $w.resume.button
update


#======================================================================= 
# Process doChoice: check parameters
#======================================================================= 
proc  doChoice {} {

    global orbitWaitTime   # wait for orbit correction 
    global VSAwaitTime     # wait for VSA averaging during tune measurement
    global freqWait        # wait for RF frequency establishment
    global freqShift       # frequency shift for tune measurement
    global orbitWaitTimeOld   # wait for orbit correction 
    global VSAwaitTimeOld     # wait for VSA averaging during tune measurement
    global freqWaitOld        # wait for RF frequency establishment
    global freqShiftOld       # frequency shift for tune measurement
    
    if {$orbitWaitTime <=0} {
        APSSetVarAndUpdate setStatus "Choose orbitWaitTime > 0, please"
        set orbitWaitTime $orbitWaitTimeOld
        return
    } else {
        set orbitWaitTimeOld $orbitWaitTime
    }
    if {$VSAwaitTime <=0} {
        APSSetVarAndUpdate setStatus "Choose  VSAwaitTime > 0, please"
        set VSAwaitTime $VSAwaitTimeOld
        return
    } else {
        set VSAwaitTimeOld $VSAwaitTime 
    }
    if {$freqWait <=0} {
        APSSetVarAndUpdate setStatus "Choose  freqWait > 0, please"
        set freqWait $freqWaitOld
        return
    } else {
        set freqWaitOld $freqWait 
    }
    if {$freqShift <=0} {
        APSSetVarAndUpdate setStatus "Choose freqShift > 0, please"
        set freqShift $freqShiftOld
        return
    } else {
        set freqShiftOld $freqShift
    }
}

#======================================================================= 
# Process choiceParameters
#======================================================================= 
set orbitWaitTime 10000
set VSAwaitTime 5000
set freqWait 1000
set freqShift 100
set orbitWaitTimeOld 10000
set VSAwaitTimeOld 5000
set freqWaitOld 1000
set freqShiftOld 100

proc  choiceParameters {} {

    global orbitWaitTime   # wait for orbit correction 
    global VSAwaitTime     # wait for VSA averaging during tune measurement
    global freqWait        # wait for RF frequency establishment
    global freqShift       # frequency shift for tune measurement

    set choice [APSUniqueName .]
    
    APSDialogBox $choice -name "Parameters choice" -okCommand doChoice
    
    APSLabeledEntry .orbit -parent $choice.userFrame \
      -label "    Orbit wait time: " \
      -textVariable orbitWaitTime -width 6 \
      -type integer \
      -gridPack "-column 0 -row 0 -sticky w" \
      -contextHelp ""
    
    APSLabeledEntry .vsa -parent $choice.userFrame \
      -label "   Time for VSA: " \
      -textVariable VSAwaitTime -width 6 -type integer \
      -gridPack "-column 1 -row 0 -sticky w" \
      -contextHelp ""

    APSLabeledEntry .freqW -parent $choice.userFrame \
      -label "Frequency wait time: " \
      -textVariable freqWait -width 6 -type real \
      -gridPack "-column 0 -row 1 -sticky w" \
      -contextHelp ""

    APSLabeledEntry .freqS -parent $choice.userFrame \
      -label "Frequency shift: " \
      -textVariable freqShift -width 6 -type real \
      -gridPack "-column 1 -row 1 -sticky w" \
      -contextHelp ""

}    

proc PauseMeasurement {widget} {
    global pauseRequested resumeRequested
    set pauseRequested 1
    set resumeRequested 0
    APSEnableButton $widget.resume.button
    APSDisableButton $widget.pause.button
}

proc ResumeMeasurement {widget} {
    global pauseRequested resumeRequested
    set pauseRequested 0
    set resumeRequested 1
    APSEnableButton $widget.pause.button
    APSDisableButton $widget.resume.button
}

proc AbortMeasurement {widget} {
    global abortRequested
    set abortRequested 1
    APSSetVarAndUpdate setStatus "Abort requested..."
    APSDisableButton $widget.abort.button
    APSDisableButton $widget.pause.button
    APSDisableButton $widget.resume.button
    APSEnableButton $widget.run.button
}

#======================================================================= 
# Process RunMeasurements
#======================================================================= 

proc RunMeasurements {widget} {
    global abortRequested pauseRequested resumeRequested sextList
    global hpSID outputDir outputRoot
    global orbitWaitTime   # wait for orbit correction 
    global VSAwaitTime     # wait for VSA averaging during tune measurement
    global freqWait        # wait for RF frequency establishment
    global freqShift       # frequency shift for tune measurement

    if ![string length $outputRoot] {
        APSSetVarAndUpdate setStatus "Output root not given."
        return
    }

    set pauseRequested 0
    set abortRequested 0
    set resumeRequested 0
    APSEnableButton $widget.abort.button
    APSEnableButton $widget.pause.button
    APSDisableButton $widget.resume.button
    APSDisableButton $widget.run.button

    cd [pwd]
    #-----------------------------------------------------------------------
    # Skipped sextupoles which are existed --> skippedSextupole:
    #
    set skippedSextupole ""
    for {set sector 1} {$sector<=40} {incr sector} {
        foreach sext $sextList {
            set alreadyThere ""
            set flagName sextS${sector}$sext
            global $flagName
            if ![set $flagName] continue
            set sName S${sector}$sext
            set fileRoot $outputDir/$outputRoot-$sName
            set filesFound [glob -nocomplain $fileRoot*.sdds]
            set filesNumber [llength $filesFound]                      
            APSSetVarAndUpdate setStatus "sName = $sName, fileRoot = $fileRoot, \
                                  filesFound = $filesFound, \
                                  filesNumber = $filesNumber"
            if $filesNumber {
                lappend alreadyThere $filesFound
                APSSetVarAndUpdate setStatus "alreadyThere = $alreadyThere"
                switch [ APSMultipleChoice [APSUniqueName .] \
                           -question "For sextupole $sName \
                                            $filesNumber old datafiles exist" \
                           -labelList {"Remove these files" \
                                         "Skip this sextupole" \
                                         "Abort the measurements"} \
                           -returnList {remove skip abort}] {
                               remove {
                                   if [catch {eval file delete -force -- $alreadyThere} result] {
                                       APSSetVarAndUpdate setStatus "Problems with removing of the old files due to $result"
                                       continue
                                   }
                                   APSSetVarAndUpdate setStatus "OK: old files are removed"
                               }
                               abort {
                                   APSSetVarAndUpdate setStatus "Measurements aborted."
                                   set abortRequested 1
                                   return
                               }
                               skip {
                                   APSSetVarAndUpdate setStatus "Measurements for sextupole \
                                                   $sName will be skipped."
                                   lappend skippedSextupole $sName                            
                                   continue
                               }
                           }
            }
        }
    }
    #    APSSetVarAndUpdate setStatus "skippedSextupole = $skippedSextupole"

    #-----------------------------------------------------------------------
    # Checking the connection with VSA:
    #
    if ![string length $hpSID] {
        if [catch {APSOpenTelnetStream -IPaddress hpvecsr \
                     -GreetingLines 0} hpSID] {
            APSSetVarAndUpdate setStatus "Connection problems with HPVSA \
                                         due to $hpSID"
            return      
        } 
    }

    # Ensure that averaging is normal, i.e. not repeating.
    # Leave steam open for loop over sextupoles.
    if [catch {APSWriteToTelnetStream -command "AVER:TCON NORM" -streamID $hpSID \
             } result ] {
        return -code error "RunMeasurements: $result"
    }

    #-----------------------------------------------------------------------
    # Origin frequency measurement:
    #
    if [catch {exec cavget -list=A014-IETS:BTC:SRSetFreqM -float=%21.15f} freq0] {
        APSSetVarAndUpdate setStatus "Problems to measure origin frequency \
                                     due to $freq0"
        return
    }
    set freq1 [expr $freq0+$freqShift]
    APSSetVarAndUpdate setStatus "Origin frequency = $freq0"
    APSSetVarAndUpdate setStatus "Shifted frequency = $freq1"
    
    #-----------------------------------------------------------------------
    # RESUME mode for orbit control:
    #
    if [catch {exec cavput -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC, -list=.SUSP=Resume} result] {
        APSSetVarAndUpdate setStatus "Problems with orbit control law \
                                      due to $result"
    }

    # return to default.
    if [catch {exec cavput -list=SR:TUNE:stripSELmbbo=X/Y \
             } result ] {
        puts stderr $result
        exit 1
    }


    #-----------------------------------------------------------------------
    # Main loop of sextupole checking:
    #
    for {set sector 1} {$sector<=40} {incr sector} {
        foreach sext $sextList {
            #--------------------------------------------------------------------
            # Skipping sextupoles which are in skippedSextupole list:
            #
            set flagName sextS${sector}$sext
            if ![set $flagName] continue
            set sName S${sector}$sext
            set ind [lsearch -exact $skippedSextupole $sName]
            if {[lsearch -exact $skippedSextupole $sName] >= 0} {
                APSSetVarAndUpdate setStatus "Skipping $sName"
                continue
            } 
            #--------------------------------------------------------------------
            # Step 1 - origin current measurement:
            #
            APSSetVarAndUpdate setStatus "Doing $sName..."
            APSSetVarAndUpdate setStatus "Origin current measurement..."
            if [catch {exec cavget -list=$sName -list=:CurrentAO} origValue] {
                APSSetVarAndUpdate setStatus "Skipping $sName due to $origValue"
                continue
            }
            if [string compare $origValue ?]==0 {
                APSSetVarAndUpdate setStatus "Skipping $sName: no connection."
                continue
            }
            APSSetVarAndUpdate setStatus "Origin current = $origValue"
            #--------------------------------------------------------------------
            # Should actually do the measurement here:
            #
            if $pauseRequested {
                APSDisableButton $widget.pause.button
                APSEnableButton $widget.resume.button
                set resumeRequested 0
                set pauseRequested 0
                APSSetVarAndUpdate setStatus "Measurement paused. [exec date]"
                break
            }
            if $abortRequested {
                APSSetVarAndUpdate setStatus "Measurement aborted. [exec date]"
                break
            }
            #--------------------------------------------------------------------
            # Step 2 - tune measurement for origin sextupole current 
            #                               and origin RF frequency:
            #
            APSSetVarAndUpdate setStatus "Wait [expr $VSAwaitTime/1000] s, \
	                                please: tune measurements \
	                                (results into file  \
                                        $outputRoot-$sName-df0-On.sdds)"
            if [catch {eval measureTune \
                         -filename $outputRoot-$sName-df0-On.sdds \
                         -waitTime $VSAwaitTime} result] {
                APSSetVarAndUpdate setStatus "Problems to measure frequency \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }                
            #--------------------------------------------------------------------
            # Step 3 - stop orbit correction when RF frequency is changed:
            #
            APSSetVarAndUpdate setStatus "Stop orbit correction..."
            if [catch {exec cavput -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC -list=.SUSP=Suspend} result] {
                APSSetVarAndUpdate setStatus "Problems with orbit control law \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                              
            }        
            #--------------------------------------------------------------------
            #  Step 4 - changing of the RF frequency:
            #
            APSSetVarAndUpdate setStatus "Changing of the RF frequency..."
            if [catch {exec cavput -list=A014-IETS:BTC:SRSetFreqM=$freq1 \
                         -ramp=step=10,pause=0.2} result] {
                APSSetVarAndUpdate setStatus "Problems with frequency changing \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                              
            }
            #--------------------------------------------------------------------
            #  Step 5 - pause for changing of the RF frequency:
            # 
            # (not needed anymore)

            #--------------------------------------------------------------------
            # Step 6 - tune measurement for origin sextupole current 
            #                               and shifted RF frequency:
            #
            APSSetVarAndUpdate setStatus "Wait [expr $VSAwaitTime/1000] s, \
	                                please: tune measurements (results into \
                               file $outputRoot-$sName-df$freqShift-On.sdds)"
            if [catch {eval measureTune \
                         -filename $outputRoot-$sName-df$freqShift-On.sdds \
                         -waitTime $VSAwaitTime} result] {
                APSSetVarAndUpdate setStatus "Problems to measure frequency \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }                
            #--------------------------------------------------------------------
            # Step 7 - set up origin RF frequency 
            #                 and switch off the sextupole current:
            #
            APSSetVarAndUpdate setStatus "Set up origin RF frequency, \
	                                switch off the sextupole current..."
            if [catch {exec cavput \
                         -list=A014-IETS:BTC:SRSetFreqM=$freq0,$sName:CurrentAO=0} \
                  result] {
                APSSetVarAndUpdate setStatus "Problems to change current \
                                           and frequency due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }           
            #--------------------------------------------------------------------
            # Step 8 - pause for changing of the current:
            #
            APSSetVarAndUpdate setStatus "Wait, please..."
            if [catch {exec cawait -waitfor=$sName:CurrentAI,below=1} \
                  result] {
                APSSetVarAndUpdate setStatus "Problems with pause after \
                                           change current due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }
            #--------------------------------------------------------------------
            # Step 9 - RESUME mode for orbit control:
            #
            APSSetVarAndUpdate setStatus "Resume of orbit control..."
            if [catch {exec cavput -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC -list=.SUSP=Resume} result] {
                APSSetVarAndUpdate setStatus "Problems with orbit control law \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }
            #--------------------------------------------------------------------
            # Step 10 - pause for orbit restoring:
            #
            APSSetVarAndUpdate setStatus "Wait [expr $orbitWaitTime/1000] s, \
	                                please: orbit restoring..."
            after $orbitWaitTime
            #--------------------------------------------------------------------
            # Step 11 - tune measurement for zero sextupole current 
            #                                and origin RF frequency:
            #
            APSSetVarAndUpdate setStatus "Wait [expr $VSAwaitTime/1000] s, \
	                                please: tune measurements (results into \
	                                file $outputRoot-$sName-df0-Off.sdds)"
            if [catch {eval measureTune \
                         -filename $outputRoot-$sName-df0-Off.sdds \
                         -waitTime $VSAwaitTime} result] {
                APSSetVarAndUpdate setStatus "Problems to measure frequency \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }                
            #--------------------------------------------------------------------
            # Step 12 - stop orbit correction when RF frequency is changed:
            #
            APSSetVarAndUpdate setStatus "Stop orbit correction..."
            if [catch {exec cavput -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC -list=.SUSP=Suspend} result] {
                APSSetVarAndUpdate setStatus "Problems with orbit control law \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }        
            #--------------------------------------------------------------------
            # Step 13 - changing of the RF frequency:
            #
            APSSetVarAndUpdate setStatus "Changing the RF frequency..."
            if [catch {exec cavput -list=A014-IETS:BTC:SRSetFreqM=$freq1 \
                         -ramp=step=10,pause=0.2} result] {
                APSSetVarAndUpdate setStatus "Problems with frequency changing \
                                          due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }
            #--------------------------------------------------------------------
            # Step 14 - pause for changing of the RF frequency:
            #
            # (not needed anymore)

            #--------------------------------------------------------------------
            # Step 15 - tune measurement for origin sextupole current 
            #                               and shifted RF frequency:
            #
            APSSetVarAndUpdate setStatus "Wait [expr $VSAwaitTime/1000] s, \
	                                please: tune measurements (results \
	                  into file $outputRoot-$sName-df$freqShift-Off.sdds)"
            if [catch {eval measureTune \
                         -filename $outputRoot-$sName-df$freqShift-Off.sdds \
                         -waitTime $VSAwaitTime} result] {
                APSSetVarAndUpdate setStatus "Problems to measure frequency \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }                
            #--------------------------------------------------------------------
            # Step 16 - set up origin RF frequency 
            #                 and origin sextupole current:
            #
            APSSetVarAndUpdate setStatus "Set up the origin RF frequency \
	                                and sextupole current..."
            if [catch {exec cavput \
                         -list=A014-IETS:BTC:SRSetFreqM=$freq0,$sName:CurrentAO=$origValue} \
                  result] {
                APSSetVarAndUpdate setStatus "Problems to change current \
                                           and frequency due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }           
            #--------------------------------------------------------------------
            # Step 17 - pause for changing of the current:
            #
            APSSetVarAndUpdate setStatus "Wait, please..."
            if [catch {exec cawait \
                         -waitfor=$sName:CurrentAI,above=[expr $origValue-10]} \
                  result] {
                APSSetVarAndUpdate setStatus "Problems with pause after \
                                           change current due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }
            #--------------------------------------------------------------------
            # Step 18 - RESUME mode for orbit control:
            #
            APSSetVarAndUpdate setStatus "Resume of orbit control..."
            if [catch {exec cavput -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC -list=.SUSP=Resume} result] {
                APSSetVarAndUpdate setStatus "Problems with orbit control law \
                                           due to $result; \
					   \nMeasurements aborted."
                set abortRequested 1
                break                        
            }
            #--------------------------------------------------------------------
            #  Step 19 - pause for orbit restoring:
            #
            APSSetVarAndUpdate setStatus "Wait [expr $orbitWaitTime/1000] s, \
	                                please: orbit restoring..."
            after $orbitWaitTime
            if $abortRequested {
                set sector 41
                break
            }
            APSSetVarAndUpdate setStatus "Done with $sName"
        }
        if $abortRequested {
            break
        }
    }
    if $abortRequested {
        APSSetVarAndUpdate setStatus "Measurements aborted."
    }
    APSSetVarAndUpdate setStatus "Done with series."

    APSDisableButton $widget.abort.button
    APSDisableButton $widget.pause.button
    APSDisableButton $widget.resume.button
    APSEnableButton $widget.run.button
}

#======================================================================= 
# Process measureTune
#======================================================================= 

proc measureTune {args} {

    global hpvsaSelection hpSID

    set filename ""
    set waitTime 10000

    APSStrictParseArguments {filename waitTime}

    #-----------------------------------------------------------------------
    #  first work method:
    #

    # Ensure that averaging is normal, i.e. not repeating.
    if [catch {APSWriteToTelnetStream -command "ABOR;*WAI" -streamID $streamID \
             } result ] {
        return -code error "measureTune: $result"
        exit 1
    }

    after 2000
    set operationCondition 256
    while {$operationCondition & 256} {
        after 1000
        set operationCondition [APSWriteToTelnetStream -command "STAT:OPER:COND?" -streamID $streamID]
    }

    # testing for overvoltage on channel 1.
    set voltageRegister [APSWriteToTelnetStream -command "STAT:QUES:VOLT:COND?" -streamID $streamID]
    if [expr $voltageRegister & 128] {
        return -code error "measureTune: Questionable voltage condition present. Check instrument range."
    }

    if [catch {exec hpVecTrace -unit=sr a $filename} result] {
        return -code error "Tune measurement problems (data reading) due to $result"
    }
    return
}

APSSetVarAndUpdate setStatus "Ready."
