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

# $Log: not supported by cvs2svn $
# Revision 1.10  2010/03/09 17:41:29  shang
# modified to use different tests files depending on topup is running or not to avoid reading data during topup injection.
#
# Revision 1.9  2009/11/03 16:38:25  shang
# changed the output directory so that it uses current date.
#
# Revision 1.8  2009/10/30 21:17:45  shang
# added corrector delta limit, and output file for logging the PVs to controllaw, and included the correctors in the controllaw tests file.
#
# Revision 1.7  2009/01/19 18:46:31  soliday
# Updated to not look for the nonexistent /home/helios/OAG/oagData/ADTFiles/par/adtrc
#
# Revision 1.6  2007/03/01 23:33:51  shang
# added runcontrol pv to sddscontrollaw and test button.
#
# Revision 1.5  2006/06/02 16:45:00  soliday
# Added additional buttons for more ADT screens.
#
# Revision 1.4  2006/03/02 22:34:54  soliday
# Added button to start related ADT screen.
#
# Revision 1.3  2003/11/17 03:15:02  borland
# No longer tries to add an email button to the exec log dialog, since their
# is one added by default now.
#
# Revision 1.2  2001/11/06 20:32:47  borland
# Reduced the number of iterations from 100 to 10.
#
# Revision 1.1  1998/06/16 16:57:43  borland
# First version per R. Soliday.
#
#

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.11 $ \$Author: shang $"

APSApplication . -name "PAR Orbit Correction" -version $CVSRevisionAuthor \
	-overview " PAR Orbit Correction\n\n\
	Graphic interface to\n\
	sddscontrollaw which\n\
	replaces the\n\
	correct-x-orbit,\n\
	correct-y-orbit,\n\
	and trimcor-x-orbit\n\
	csh scripts."

set directory /home/helios/oagData/par/orbitCorrection

APSFrame .horizontal -parent .userFrame -label Horizontal 

APSFrame .vertical -parent .userFrame -label Vertical

set horMagnets Cor

#APSRadioButtonFrame .horizontalRadioFrame -parent .userFrame.horizontal.frame \
	-buttonList {"corrector magnets" "trim windings"} -label "" \
	-valueList "Cor Trim" -variable horMagnets \
	-contextHelp "Choose which magnets to use"

set horGain 0.5

APSLabeledEntry .horizontalGain -parent .userFrame.horizontal.frame \
	-label "Gain:" -textVariable horGain \
	-contextHelp "<real-value> - Quantity multiplying\n\
	the inputfile matrix.  If the gain\n\
	matrix is exactly equal to the\n\
	inverse response matrix between\n\
	the control and measurement\n\
	process variables, then this\n\
	value should be less than one.\n\
	If instablility occurs in the\n\
	feedback, then the program\n\
	should be re-run with a reduced\n\
	value for gain."

set horInterval 2.0
set horDelta 0.5
APSLabeledEntry .horizontalInterval -parent .userFrame.horizontal.frame \
	-label "Iteration interval:" -textVariable horInterval \
	-contextHelp "<real-value> - Specifies the\n\
	interval between readings.\n\
	The time interval is implemented\n\
	with a call to usleep between\n\
	calls to the control system.\n\
	Because the calls to the control\n\
	system may take up a significant\n\
	amount of time, the average\n\
	effective time interval may be\n\
	longer than specified."
APSLabeledEntry .hlimit -parent .userFrame.horizontal.frame \
	-label "corrector delta limit (A):" -textVariable horDelta \
	-contextHelp "<real-value> - Enter the upper limit for corrector change. \n\
         The corrector with the maximum change will be compared to this value. \n\
         If necessary, all correctors will be scaled sown so that the corrector with\n\
         the largest change will not exceed the limit."
	
set horIterations 10
if {0} {
APSLabeledEntry .horizontalIterations -parent .userFrame.horizontal.frame \
	-label "Number of Iterations:" -textVariable horIterations \
	-contextHelp "<integer-value> -\n\
	Number of\n\
	iterations\n\
	for the feedback\n\
	before normal\n\
	exiting."
}
set horizID ""
APSButton .horizontalStart -parent .userFrame.horizontal.frame \
    -text "Start" -command \
    {
        if [catch {exec cavput -list=PAR:OrbitControlLawXSDDS.ABRT=1 -pend=30} result] {
            return -code error $result
        }
        APSsddscontrollaw -Gain $horGain -Interval \
            $horInterval -Iterations $horIterations -Magnets $horMagnets -Plane H \
            -Directory $directory -Accelerator PAR -deltaLimit $horDelta
    } \
    -contextHelp "Start Horizontal Orbit Correction"

APSButton .horizontalAbort -parent .userFrame.horizontal.frame \
  -text Abort \
  -command "Abort -plane h" \
  -contextHelp "Abort Horizontal Orbit Correction"

APSButton .info -parent .userFrame.horizontal.frame \
    -text Info \
    -command { 
        exec medm -x -attach -macro RCPV=PAR:OrbitControlLawXSDDS \
            ./sr/psApp/APSRunControlSingle.adl &
    }
set vertMagnets Cor

#APSRadioButtonFrame .verticalRadioFrame -parent .userFrame.vertical.frame \
	-buttonList {"corrector magnets"} -label "" \
	-valueList "Cor" -variable vertMagnets \
	-contextHelp "Choose which magnets to use"

set vertGain 0.5

APSLabeledEntry .verticalGain -parent .userFrame.vertical.frame \
	-label "Gain:" -textVariable vertGain \
	-contextHelp "<real-value> - Quantity multiplying\n\
	the inputfile matrix.  If the gain\n\
	matrix is exactly equal to the\n\
	inverse response matrix between\n\
	the control and measurement\n\
	process variables, then this\n\
	value should be less than one.\n\
	If instablility occurs in the\n\
	feedback, then the program\n\
	should be re-run with a reduced\n\
	value for gain."

set vertInterval 2.0
set vertDelta 0.5
APSLabeledEntry .verticalInterval -parent .userFrame.vertical.frame \
	-label "Iteration interval:" -textVariable vertInterval \
	-contextHelp "<real-value> - Specifies the\n\
	interval between readings.\n\
	The time interval is implemented\n\
	with a call to usleep between\n\
	calls to the control system.\n\
	Because the calls to the control\n\
	system may take up a significant\n\
	amount of time, the average\n\
	effective time interval may be\n\
	longer than specified."
APSLabeledEntry .vlimit -parent .userFrame.vertical.frame \
	-label "corrector delta limit (A):" -textVariable vertDelta \
	-contextHelp "<real-value> - Enter the upper limit for corrector change. \n\
         The corrector with the maximum change will be compared to this value. \n\
         If necessary, all correctors will be scaled sown so that the corrector with\n\
         the largest change will not exceed the limit."
set vertIterations 10
if {0} {
APSLabeledEntry .verticalIterations -parent .userFrame.vertical.frame \
	-label "Number of Iterations:" -textVariable vertIterations \
	-contextHelp "<integer-value> -\n\
	Number of\n\
	iterations\n\
	for the feedback\n\
	before normal\n\
	exiting."
}
set vertID ""
APSButton .verticalStart -parent .userFrame.vertical.frame \
    -text "Start" -command \
    {
        if [catch {exec cavput -list=PAR:OrbitControlLawYSDDS.ABRT=1 -pend=30} result] {
            return -code error $result
        }
        set vertID [APSsddscontrollaw -Gain $vertGain -Interval \
                        $vertInterval -Iterations $vertIterations -Magnets $vertMagnets -Plane V \
                        -Directory $directory -Accelerator PAR -deltaLimit $vertDelta]} \
    -contextHelp "Start Vertical Orbit Correction"

APSButton .verticalAbort -parent .userFrame.vertical.frame \
    -text "Abort" \
    -command  "Abort -plane v"  -contextHelp "Abort Vertical Orbit Correction"

APSButton .info  -parent .userFrame.vertical.frame \
    -text Info \
    -command { 
        exec medm -x -attach -macro RCPV=PAR:OrbitControlLawYSDDS \
            ./sr/psApp/APSRunControlSingle.adl &
    }

APSButton .test -parent .userFrame -text "Test" -command "Test"
APSButton .adt1 -parent .userFrame \
    -text "BPM ADT" \
    -command "exec adt -f /home/helios/OAG/oagData/ADTFiles/par/par.bpm.pv &"

APSButton .adt2 -parent .userFrame \
    -text "BPM Errors ADT" \
    -command "exec adt -f /home/helios/OAG/oagData/ADTFiles/par/par.bpm.error.pv &"

APSButton .adt3 -parent .userFrame \
    -text "BPM and BPM Errors ADT" \
    -command "exec adt -f /home/helios/OAG/oagData/ADTFiles/par/par.bpm.with.error.pv &"

#
# Orbit Correction
#
proc Test {} {
    if [catch {exec cavget -list=Mt:TopUpAutoEnableC.VAL -pend=10 -printErrors -numerical} topup] {
        return -code error "Unable to read topup state: $topup"
    }
    if $topup {
        set testfile /home/helios/oagData/par/orbitCorrection/PAR-topup.tests
    } else {
        set testfile /home/helios/oagData/par/orbitCorrection/PAR-nontopup.tests
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddscombine $testfile /home/helios/oagData/par/orbitCorrection/PAR.tests -merge $tmpRoot.tests} result] {
        return -code error $result
    }
    APSAddToTempFileList $tmpRoot.tests
    if [catch {exec sddscasr $tmpRoot.tests -save -pipe=out -pend=10 -numerical \
		   | sddsprocess -pipe -match=col,CAError=n \
		   | sddsprocess -pipe -scan=col,Value,ValueString,%lf \
		   | sddsprocess -pipe \
		   "-define=col,OutOfRange,Value MinimumValue < Value MaximumValue > || ? 1 : 0 $ ,type=long" \
		   | sddsprintout -pipe=in $tmpRoot.print \
		   -col=ControlName,format=%45s -col=MinimumValue,format=%10.2f \
		   -col=MaximumValue,format=%10.2f  \
		   -col=Value,format=%10.2f -col=OutOfRange,format=%10ld } result] {
	return -code error $result
    }
    APSAddToTempFileList  $tmpRoot.print
    APSFileDisplayWindow [APSUniqueName .] -height 20  \
	-fileName $tmpRoot.print  -width 100  -deleteOnClose 1 

}
proc APSsddscontrollaw {args} {
    set Gain ""
    set Interval ""
    set Iterations ""
    set Plane ""
    set Magnets ""
    set Directory ""
    set Accelerator ""
    set deltaLimit ""
    APSStrictParseArguments {Gain Interval Iterations Plane Magnets Directory Accelerator deltaLimit}

    global outputDir
    set outputDir [APSGoToDailyDirectory -subdirectory PARorbit]
    switch $Plane {
        H {
            set runControlPV PAR:OrbitControlLawXSDDS
            set runControlDesc "Horizontal PAR orbit correction"
        }
        V {
            set runControlPV PAR:OrbitControlLawYSDDS
            set runControlDesc "Vertical PAR orbit correction" 
        }
    }
    # Check for valid input values
    APSValidity -Type %f -inputValue $Gain -outputValue Gain
    APSValidity -Type %f -inputValue $Interval -outputValue Interval
    APSValidity -Type %d -inputValue $Iterations -outputValue Iterations
    APSValidity -Values "H V" -Type %s -inputValue $Plane -outputValue Plane
    APSValidity -Values "Cor Trim" -Type %s -inputValue $Magnets -outputValue Magnets
    APSValidity -Values "Linac PAR Booster SR" -Type %s -inputValue $Accelerator -outputValue Accelerator

    # Set pass variable
    if {$Accelerator=="PAR"} {
        if [catch {exec cavget -list=Mt:TopUpAutoEnableC.VAL -pend=10 -printErrors -numerical} topup] {
            return -code error "Unable to read topup state: $topup"
        }
        if $topup {
            set testfile $Directory/${Accelerator}-topup.tests
        } else {
            set testfile $Directory/${Accelerator}-nontopup.tests
        }
	set tmpRoot /tmp/[APSTmpString]
	if [catch {exec sddscombine $testfile $Directory/$Accelerator.$Plane.tests -merge $tmpRoot.$Plane.tests } result] {
	    return -code error $result
	}
	set testfile $tmpRoot.$Plane.tests
    } else {
        set testfile $Directory/$Accelerator.tests
    }
    set pass "$Directory/$Accelerator.$Plane.Inv.$Magnets $outputDir/$Plane.$Magnets.log -dailyFiles -gain=$Gain -deltaLimit=value=$deltaLimit \
	 -infiniteLoop -controlQuan=$Directory/$Accelerator.$Plane.Def.$Magnets  \
	-testvalues=$testfile -integral -deltaLimit=value=0.5 \
	-interval=$Interval -verbose -runControlPV=string=$runControlPV,pingTimeout=30 \"-runcontrolDescription=string=$runControlDesc\""

    # Execute sddscontrollaw
    set ID [APSExecLog [APSUniqueName .] -unixCommand "sddscontrollaw $pass" \
	    -width 100]
    return $ID
}


#
# Abort sddscontrollaw 
#
proc Abort {args} {
    set plane ""
    APSStrictParseArguments {plane}
    switch $plane {
	h {
	    set runControlPV PAR:OrbitControlLawXSDDS
	}
	v {
	    set runControlPV PAR:OrbitControlLawYSDDS
	}
    }
    if [catch {exec cavput -list=${runControlPV}.ABRT=1 -pend=10} result] {
	return -code error $result
    }
}

#
# Check for valid format of variables then pass the correct format 
# back to previous procedure
#
proc APSValidity {args} {
    set Type %s 
    set Values ""
    set inputValue ""
    APSStrictParseArguments {Type Values inputValue outputValue}
    if {[string compare $Values ""] != 0} {
	set passed 0
	foreach value $Values {
	    if {[string compare $value $inputValue] == 0} {
		set passed 1
	    }
	}
	if {$passed == 0} {
	    return -code error "APSValidity: $inputValue does not match any of the following: $Values"
	}
    }
    if {[scan $inputValue $Type output] != 1} {
	return -code error "APSValidity: $inputValue is not $Type format"
    }
    uplevel "set $outputValue $output"
}
