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

# simpler version of SRSextoples for change SR chromaticity, H. Shang 10/22/2012

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

APSApplication . -name ChangeSRChromaticity -version 1 \
  -overview {This application is for changing SR chromaticity.}

#-----------------------------------------------------------------------------------------------------------------------

proc MakeMainFrame { args } {

    global applyButton restoreButton zeroButton estimatedChrom beamEnergy
    APSParseArguments {parent}

    #--- Chromaticity estimate part 
    set estimatedChrom ""
    APSLabeledOutput .estimatedChrom -parent $parent \
      -label "Estimated chromaticity for current sextupoles:" -textVariable estimatedChrom -width 35
    APSButton .refresh -parent $parent.estimatedChrom \
      -text "Refresh" -size small \
      -command { 
          if [catch { EstimateCurrentChromaticity -beamEnergy $beamEnergy } estimatedChrom] {
              APSSetVarAndUpdate status "EstimateCurrentChromaticity: $estimatedChrom"
          } else {
              APSSetVarAndUpdate status "Estimated chromaticity refreshed."
          }
      } -contextHelp "Recalculates the estimated chromaticity for current sextupoles using lattice from \
                      oagData/calibratedModels/default"
    APSLabeledEntry .xChromaticity -parent $parent -label "X chromaticity change:" -textVariable Chromaticity(x) -width 30
    APSButton .x1 -parent $parent.xChromaticity -packOption "-side right" -text "+1" -command "incr Chromaticity(x)"
    APSButton .x2 -parent $parent.xChromaticity -packOption "-side right" -text "-1" -command "incr Chromaticity(x) -1"
    APSLabeledEntry .yChromaticity -parent $parent -label "Y chromaticity change:" -textVariable Chromaticity(y) -width 30
    APSButton .y1 -parent $parent.yChromaticity -packOption "-side right" -text "+1" -command "incr Chromaticity(y)"
    APSButton .y2 -parent $parent.yChromaticity -packOption "-side right" -text "-1" -command "incr Chromaticity(y) -1"
    
    
    APSFrame .sext -parent $parent -label "Combined Intended Changes"
    APSButton .estimate -parent $parent.sext.frame -text "Estimate chromaticity changes" -command "EstimateChanges_ChromTab" \
        -packOption "-side top"
    APSFrameGrid .grid1 -parent $parent.sext.frame -xList {x1 x2 x3}
    set w $parent.sext.frame.grid1
    APSLabeledOutput .xChromaticity -parent $w.x1 -label "X chromaticity change:" -textVariable ChromaticityTotal(x) -width 10
    APSLabeledOutput .yChromaticity -parent $w.x1 -label "Y chromaticity change:" -textVariable ChromaticityTotal(y) -width 10
    APSLabeledOutput .deltaS3total -parent $w.x2 -label "S3 change (A):" -textVariable deltaItotal(S3) -width 12
    APSLabeledOutput .deltaS4total -parent $w.x2 -label "S4 change (A):" -textVariable deltaItotal(S4) -width 12
    APSLabeledOutput .s3I -parent $w.x3 -label "S3 (A):" -textVariable I(S3) -width 10
    APSLabeledOutput .s4I -parent $w.x3 -label "S4 (A):" -textVariable I(S4) -width 10
    APSFrame .chrom -parent $parent -label "Accumulated Applied Changes"
    APSFrameGrid .grid -parent $parent.chrom.frame -xList {x1 x2}
     set w $parent.chrom.frame.grid.x1
    APSLabeledOutput .xChromaticity -parent $w -label "X chromaticity change:     " \
	-textVariable ChromaticityAccum(x) -width 10
    set w $parent.chrom.frame.grid.x2
    APSLabeledOutput .yChromaticity -parent $w -label "   Y chromaticity change:     " \
	-textVariable ChromaticityAccum(y) -width 10

    APSButton .changeSextupoles -parent $parent -text "Apply combined sextupole changes" -command "ApplyDeltaCurrents" \
       -contextHelp "Applies combined intended sextupole changes to the machine."
    #APSButton .restoreSextupoles -parent $parent -text "Restore sextupoles" -command "RestoreSextupoles" \
    #  -contextHelp "Return all sextupoles to the very beginning."
    
    APSButton .zeroAll -parent $parent -text "Zero all intended changes" -command ZeroIntendedChanges
    
}

proc RestoreSextupoles {} {
    global restoreSextupolesString
     APSSetVarAndUpdate status "Ramping back..."
    if [catch {exec cavput -list=$restoreSextupolesString -pend=10 -ramp=step=30,pause=5} result] {
        APSSetVarAndUpdate status "Error in restoring sextupoles: $result"
    } else {
        APSSetVarAndUpdate status "Sextupoles have been restored."
    }
}

set lteFileDir $OAGGlobal(SRLatticesDirectory)

proc findFiles {args} {
    set fileVar ""
    APSParseArguments {dir pattern fileVar}
    global $fileVar
    set file [set $fileVar] 
    if [string length $file] {
        set dir [file dir $file]
    }
    set choosedfile [APSFileSelectDialog .chooseInputFile -listDir $dir -pattern $pattern]
    if [string length $choosedfile] {
        set $fileVar $choosedfile
    }
} 


#-----------------------------------------------------------------------------------------------------------------------
#--- This procedure transforms currents to K2s or K2s to currents

proc sexSetpoints { args } {

    global excitationFile beamEnergy
    set sexName ""
    set I ""
    set K2 ""

    APSParseArguments {sexName I K2}
    if {![string length $sexName] || ![expr [string length $I] + [string length $K2]]} {
        puts stderr $argv
        puts stderr $usage

    }

    set sexLength 0.2527
    set Hr [expr $beamEnergy / 0.299792]
 
    switch -exact -- $sexName {
	S1 { set sign 1 }
	S2 { set sign -1 }
	S3 { set sign -1 }
	S4 { set sign 1 }
	default { return -code error "Wrong sextupole name!" }
    }
    set BnLcolumn $sexName-BnL

    if {[string length $I] != 0 } {
	#--- Transforming currents to K2s...
        set B2L [exec sddsinterp $excitationFile -pipe=out -col=I,$BnLcolumn -atValues=$I \
                   -aboveRange=extrapolate -belowRange=extrapolate \
                   | sdds2stream -pipe=in -col=$BnLcolumn]
        set K2 [expr $B2L / $Hr / $sexLength * $sign]
        set output $K2
    } else {
        set B2L [expr $K2 * $Hr * $sexLength * $sign]
        set I [exec sddsinterp $excitationFile -pipe=out -col=$BnLcolumn,I -atValues=$B2L \
                 -aboveRange=extrapolate -belowRange=extrapolate \
                 | sdds2stream -pipe=in -col=I]
        set output $I
    }
    return $output
}

#-----------------------------------------------------------------------------------------------------------------------

proc EstimateChanges_ChromTab { args } {

    APSStrictParseArguments { family }

    global Ainv I Chromaticity deltaItotal ChromaticityTotal deltaI

    foreach sext {S1 S2 S3 S4} {
        set deltaI($sext) 0
        set Iold($sext) [expr $I($sext) + $deltaItotal($sext)]
    }

    set sexList {S3 S4}
    
    foreach sext $sexList {
        set deltaK2($sext) [exec rpnl "$Ainv(${sext}-1) $Chromaticity(x) * $Ainv(${sext}-2) $Chromaticity(y) * + "]
        set K2old($sext)   [sexSetpoints -sexName $sext -I $Iold($sext)]
        set K2new($sext)   [expr $K2old($sext) + $deltaK2($sext)]
        set Inew($sext)    [sexSetpoints -sexName $sext -K2 $K2new($sext)]
        set deltaI($sext)  [expr $Inew($sext) - $Iold($sext)]
    }

    foreach sext {S1 S2 S3 S4} {
        set deltaItotal($sext) [format "%12.6f" [expr $deltaItotal($sext) + $deltaI($sext)]]
        set deltaI($sext) 0
    }
    array set Chromaticity "x 0 y 0"
    CalculateTotalChromaticity
}

#-----------------------------------------------------------------------------------------------------------------------

proc CalculateTotalChromaticity { } {
    global I A deltaItotal ChromaticityTotal 
    foreach sext {S1 S2 S3 S4} {
        set Inew($sext)    [expr $I($sext) + $deltaItotal($sext)]
        set K2old($sext)   [sexSetpoints -sexName $sext -I $I($sext)]
        set K2new($sext)   [sexSetpoints -sexName $sext -I $Inew($sext)]
        set deltaK2($sext) [expr $K2new($sext) - $K2old($sext)]
        
    }
    set ChromaticityTotal(x) \
      [format "%12.6f" \
         [exec rpnl "$A(11) $deltaK2(S1) * $A(12) $deltaK2(S2) * + $A(13) $deltaK2(S3) * + $A(14) $deltaK2(S4) * +"]]
    set ChromaticityTotal(y) \
      [format "%12.6f" \
         [exec rpnl "$A(21) $deltaK2(S1) * $A(22) $deltaK2(S2) * + $A(23) $deltaK2(S3) * + $A(24) $deltaK2(S4) * +"]]
}

#-----------------------------------------------------------------------------------------------------------------------

proc EstimateChanges_SexTab { } {

    global I A deltaItotal ChromaticityTotal deltaI

    foreach sext {S1 S2 S3 S4} {
        set deltaItotal($sext) [format "%12.6f" [expr $deltaItotal($sext) + $deltaI($sext)]]
        set deltaI($sext) 0
        APSSetVarAndUpdate status "$sext [set deltaItotal($sext)]"
    }
    CalculateTotalChromaticity

}

#-----------------------------------------------------------------------------------------------------------------------

proc EstimateCurrentChromaticity { args } {

    global tmpDir xrefFile

    APSParseArguments { beamEnergy }

    #--- Making scr-like file with sextupoles...
    set tmpRoot $tmpDir/[APSTmpString]-estChrom
    if [catch {exec cavget -list=S -range=beg=1,end=40 -list=A:S1,A:S2,A:S3,A:S4,B:S3,B:S2,B:S1 \
		   -list=:CurrentAO -label} currentList] {
	return -code error "Error doing cavget: $currentList"
    }
    set N [llength $currentList]
    if {$N != 560} { return -code error "cavget: Less than 280 sextupoles returned." }
    for {set I 0} {$I <$N} {incr I 2} {
	lappend controlNameList [lindex $currentList $I]
	lappend valueStringList [lindex $currentList [expr $I + 1]]
    }
    exec sddsmakedataset -pipe=out -col=ControlName,type=string -data=[join $controlNameList ,] \
	-col=ValueString,type=string -data=[join $valueStringList ,] \
	-col=ParameterValue,type=double -data=[join $valueStringList ,] \
	| sddsprocess -pipe=in $tmpRoot.sext -print=para,SnapshotDescription,Dummy
    lappend tmpFileList $tmpRoot.sext


    #--- Running CalculateOfflineChromaticity with scr file created above...
    set measDirectory /home/helios/oagData/sr/calibratedModels/default
    set lteFile $measDirectory/aps.lte
    set beamline RING
    if [catch {exec sdds2stream $measDirectory/requiredParamFiles.sdds -col=filename} fileList] {
	return -code error "Error reading requiredParamFiles.sdds file: $fileList"
    }
    set paramFileList ""
    foreach filename $fileList { lappend parameterFileList $measDirectory/$filename }
    if [catch {CalculateOfflineChromaticity -scrFile $tmpRoot.sext -lteFile $lteFile -xrefFile $xrefFile \
		   -paramFileList $paramFileList -beamEnergy $beamEnergy -beamline $beamline} outputString] {
	return -code error "CalculateOfflineChromaticity: $outputString"
    }

    eval file delete $tmpFileList
    return $outputString
}

#-----------------------------------------------------------------------------------------------------------------------

proc CalculateOfflineChromaticity { args } {

    global tmpDir BRhoPVName

    APSParseArguments { scrFile lteFile paramFileList beamEnergy beamline xrefFile }

    set tmpRoot $tmpDir/[APSTmpString]-offlineChrom

    #--- Making KnL file from scr file...
    set outputFileDir [file dirname $tmpRoot]
    set outputFileRoot [file tail $tmpRoot]
    if [catch {APSMpMagnetKnLValues -SCRFile $scrFile -xrefFileList $xrefFile \
		   -energy $beamEnergy -BRhoPVName $BRhoPVName \
		   -outputFileDir $outputFileDir \
		   -outputFileRoot $outputFileRoot \
		   -statusCallback "APSSetVarAndUpdate status" \
		   -abortVariable abortRun} result] {
	return -code error "APSMpMagnetKnLValues: $result"
    }
    lappend tmpFileList $tmpRoot.KnL

    #--- Averaging Kn over sextupole families (for output only):
    foreach sextupole [list S1 S2 S3 S4] sexK2 [list K2S1Av K2S2Av K2S3Av K2S4Av] {
	if [catch {exec sddsprocess $tmpRoot.KnL -pipe=out -match=col,ElementName=*:$sextupole -process=Kn,average,KnAv \
		       | sdds2stream -pipe=in -para=KnAv} $sexK2] {
	    return -code error "Error averaging Kn: [set $sexK2]"
	}
    }
    APSSetVarAndUpdate status "Average sextupole strengths: S1 [format "%7.3f" $K2S1Av], S2 [format "%7.3f" $K2S2Av], \
        S3 [format "%7.3f" $K2S3Av], S4 [format "%7.3f" $K2S4Av]"

    #--- Making elegant file for chromaticity run...
    set eleFile $tmpRoot.ele
    set twiFile $tmpRoot.twi
    set sexFile $tmpRoot.KnL
    if [catch {GenerateElegantFileFromLTE -eleOutputFile $eleFile \
		   -run_setup [list "lattice $lteFile use_beamline $beamline default_order 2"] \
		   -load_parameters [list "filename_list \"$paramFileList\"" \
					 "filename $sexFile change_defined_values 1"] \
		   -twiss_output [list "filename $twiFile"] \
		   -run_control [list "n_steps 1"] \
		   -bunched_beam [list "n_particles_per_bunch 1"] \
	       } result] {
	return -code error "Fit_GenerateElegantFileFromLTE: $result"
    }
    lappend tmpFileList $eleFile $twiFile $sexFile

    #--- Running elegant...
    set eleOutFile $tmpRoot.out
    file delete $eleOutFile
    APSSetVarAndUpdate status "running elegant..."
    if [catch {exec elegant $eleFile > $eleOutFile} result] {
        return -code error "elegant error (see file $eleOutFile): $result"
    }
    lappend tmpFileList $eleOutFile
    set chromX [exec sdds2stream $twiFile -para=dnux/dp]
    set chromY [exec sdds2stream $twiFile -para=dnuy/dp]
    set outputString "CHROMX [format "%8.2f" $chromX],  CHROMY [format "%8.2f" $chromY]"
    APSSetVarAndUpdate status "CHROMX = [format "%8.2f" $chromX],  CHROMY = [format "%8.2f" $chromY]"

    eval file delete $tmpFileList
    return $outputString
}

#-----------------------------------------------------------------------------------------------------------------------

proc ApplyDeltaCurrents { } {

    global deltaItotal ChromaticityTotal ExcludeSectors ChromaticityAccum

    EstimateChanges_ChromTab
    
    set    cavputString "A:S3:CurrentAO=$deltaItotal(S3),"
    append cavputString "B:S3:CurrentAO=$deltaItotal(S3),"
    append cavputString "A:S4:CurrentAO=$deltaItotal(S4)"
    if {$deltaItotal(S3)==0 && $deltaItotal(S4)} {
        APSSetVarAndUpdate status "No changes needed."
        return
    }
    if ![APSYesNoPopUp "Are you sure to change S3 sextupoles by $deltaItotal(S3), and S4 sextupoles by $deltaItotal(S4)?"] {
        APSSetVarAndUpdate status "Change S3 and S4 sextupoles was cancelled."
        return
    }
    set ExcludeSectors [string trim $ExcludeSectors]
    set excludeList 0
    if [string length $ExcludeSectors] {
        foreach item [split $ExcludeSectors " ,"] {
            lappend excludeList $item
        }
    }
    set sectorList ""
    for {set sector 1} {$sector<41} {incr sector} {
        if [lsearch -exact $excludeList $sector]==-1 {
            lappend sectorList $sector
        }
    }
    #check if orbit correction is running
    APSSetVarAndUpdate status "check if orbit correction is running..."
    set first 1
    while {1} {
        if [catch {exec cavget -list=DP:S:OrbitControlLaw -list=X,Y -list=SDDS.RUN -pend=10 -printErrors } runningList] {
            return -code error "Error in reading controllaw status: $runningList"
        }
        set xRun [lindex $runningList 0]
        set yRun [lindex $runningList 1]
        set running 1
        if {!$xRun || !$yRun} {
            if $first {
                if !$xRun {
                    APSSetVarAndUpdate status "horizontal orbit correction is not running, please start horizontal orbit correction."
                }
                if !$yRun {
                     APSSetVarAndUpdate status "vertical orbit correction is not running, please start vertical orbit correction."
                }
                set first 0
                 APSSetVarAndUpdate status "Wait for orbit correction..."
            }
            after 1000
            continue
        } else {
            break
        }
    }
    APSSetVarAndUpdate status "check topup status"
    if [catch {exec cavget -list=Mt:TopUpAutoEnableC.VAL -num -pend=10 -printErrors} topupRunning] {
        return -code error "Error in reading topup state: $topupRunning"
    }
    if $topupRunning {
        APSSetVarAndUpdate status "suspend topup..."
        if [catch {exec cavput -list=Mt:TopUpAutoEnableC.VAL=0 -pend=10 } result] {
            return -code error "Error in suspending topup state: $result"
        }
    }
    
    APSSetVarAndUpdate status "[exec date +%H:%M:%S] ramping S3/S4 sextupoles..."
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=$cavputString \
                 -delta -pend=10 -ramp=step=30,pause=5} result] {
        return -code error "cavput: $result"
    } else {
        APSSetVarAndUpdate status "[clock format [clock seconds] -format %T]"
        APSSetVarAndUpdate status \
          "The following changes have been applied:\
             \nS3=$deltaItotal(S3)  S4=$deltaItotal(S4) \
             \nCHROMX= $ChromaticityTotal(x)  CHROMY= $ChromaticityTotal(y)"
	set ChromaticityAccum(x) [format %6.3f [expr $ChromaticityAccum(x) + $ChromaticityTotal(x)]]
	set ChromaticityAccum(y) [format %6.3f [expr $ChromaticityAccum(y) + $ChromaticityTotal(y)]]
    }
    if $topupRunning {
        APSSetVarAndUpdate status "resuming topup..."
        if [catch {exec cavput -list=Mt:TopUpAutoEnableC.VAL=1 -pend=10 } result] {
            return -code error "Error in resuming topup state: $result"
        }
    }
     APSSetVarAndUpdate status "done."
}

#-----------------------------------------------------------------------------------------------------------------------

proc CalculateCoefficients { args } {

    APSStrictParseArguments { lteFile paramFile paramFile1 beamlineName }

    global tmpDir A Ainv beamEnergy

    set scanParamFile $tmpDir/[APSTmpString]-chromCoeff.param
    set eleFile $tmpDir/[APSTmpString]-chromCoeff.ele
    set twiFile $tmpDir/[APSTmpString]-chromCoeff.twi
    if [catch {CreateParamFile -paramFile $scanParamFile} result] {
        return -code error "CalculateCoefficients: $result"
    }
    set paramFileList ""
    if [string length $paramFile] {set paramFileList $paramFile}
    if [string length $paramFile1] {set paramFileList [concat $paramFile $paramFile1]}
    if [catch {GenerateElegantFileFromLTE -eleOutputFile $eleFile \
			   -run_setup [list "lattice $lteFile use_beamline $beamlineName default_order 2"] \
			   -load_parameters [list "filename_list \"$paramFileList\"" \
						"filename $scanParamFile change_defined_values 0"] \
			   -twiss_output [list "filename $twiFile"] \
			   -run_control [list "n_steps 5"] \
			   -bunched_beam [list "n_particles_per_bunch 1"] \
		       } result] {
                return -code error "Fit_GenerateElegantFileFromLTE: $result"
	    }

    lappend tmpFileList $scanParamFile $eleFile $twiFile

    APSSetVarAndUpdate status "Running elegant..."
    file delete elegant.out
    if [catch {exec elegant $eleFile > elegant.out} result] {
        return -code error "elegant: $result"
    }
    lappend tmpFileList elegant.out
    set xChromList [exec sdds2stream $twiFile -para=dnux/dp]
    set yChromList [exec sdds2stream $twiFile -para=dnuy/dp]

    set A(11) [expr [lindex $xChromList 1] - [lindex $xChromList 0]]
    set A(12) [expr [lindex $xChromList 2] - [lindex $xChromList 0]]
    set A(13) [expr [lindex $xChromList 3] - [lindex $xChromList 0]]
    set A(14) [expr [lindex $xChromList 4] - [lindex $xChromList 0]]
    set A(21) [expr [lindex $yChromList 1] - [lindex $yChromList 0]]
    set A(22) [expr [lindex $yChromList 2] - [lindex $yChromList 0]]
    set A(23) [expr [lindex $yChromList 3] - [lindex $yChromList 0]]
    set A(24) [expr [lindex $yChromList 4] - [lindex $yChromList 0]]

    set deter34 [exec rpnl "$A(13) $A(24) * $A(14) $A(23) * -"]
    set deter12 [exec rpnl "$A(11) $A(22) * $A(12) $A(21) * -"]
    set Ainv(S1-1) [expr $A(22) / $deter12]
    set Ainv(S1-2) [expr $A(12) / $deter12 * -1]
    set Ainv(S2-1) [expr $A(21) / $deter12 * -1]
    set Ainv(S2-2) [expr $A(11) / $deter12]
    set Ainv(S3-1) [expr $A(24) / $deter34]
    set Ainv(S3-2) [expr $A(14) / $deter34 * -1]
    set Ainv(S4-1) [expr $A(23) / $deter34 * -1]
    set Ainv(S4-2) [expr $A(13) / $deter34]

    APSSetVarAndUpdate status "Direct:"
    APSSetVarAndUpdate status \
      "[format "%8.4f" $A(11)] [format "%8.4f" $A(12)] [format "%8.4f" $A(13)] [format "%8.4f" $A(14)]" 
    APSSetVarAndUpdate status \
      "[format "%8.4f" $A(21)] [format "%8.4f" $A(22)] [format "%8.4f" $A(23)] [format "%8.4f" $A(24)]" 
    APSSetVarAndUpdate status "Inverse:"
    APSSetVarAndUpdate status \
      "[format "%8.4f" $Ainv(S1-1)] [format "%8.4f" $Ainv(S1-2)] [format "%8.4f" $Ainv(S2-1)] [format "%8.4f" $Ainv(S2-2)]" 
    APSSetVarAndUpdate status \
      "[format "%8.4f" $Ainv(S3-1)] [format "%8.4f" $Ainv(S3-2)] [format "%8.4f" $Ainv(S4-1)] [format "%8.4f" $Ainv(S4-2)]" 

    eval file delete $tmpFileList
    APSSetVarAndUpdate status "Coefficients are done."
}

#-----------------------------------------------------------------------------------------------------------------------

proc CreateParamFile {args} {

    APSParseArguments { paramFile }

    if [catch {open $paramFile w} fid] {
        return -code error "$fid"
    }
    puts $fid "SDDS1"
    puts $fid "&column name=ElementName, type=string,  &end"
    puts $fid "&column name=ElementParameter, type=string,  &end"
    puts $fid "&column name=ParameterValue, type=double,  &end"
    puts $fid "&column name=ParameterMode, type=string,  &end"
    puts $fid "&data mode=ascii, no_row_counts=1, &end"
    for {set sector 1} {$sector < 41} {incr sector} {
        puts $fid " S${sector}A:S1  K2  0.0  differential "
        puts $fid " S${sector}B:S1  K2  0.0  differential "
    }
    puts $fid "  "
    for {set sector 1} {$sector < 41} {incr sector} {
        puts $fid " S${sector}A:S1  K2  1.0  differential "
        puts $fid " S${sector}B:S1  K2  1.0  differential "
    }
    puts $fid "  "
    for {set sector 1} {$sector < 41} {incr sector} {
        puts $fid " S${sector}A:S2  K2  1.0  differential "
        puts $fid " S${sector}B:S2  K2  1.0  differential "
    }
    puts $fid "  "
    for {set sector 1} {$sector < 41} {incr sector} {
        puts $fid " S${sector}A:S3  K2  1.0  differential "
        puts $fid " S${sector}B:S3  K2  1.0  differential "
    }
    puts $fid "  "
    for {set sector 1} {$sector < 41} {incr sector} {
        puts $fid " S${sector}A:S4  K2  1.0  differential "
    }
    puts $fid "  "
    close $fid
}

#-----------------------------------------------------------------------------------------------------------------------

proc GenerateElegantFileFromLTE { args } {
    set argList [list run_setup load_parameters alter_elements load_parameters2 run_control correct closed_orbit \
		     correction_matrix_output twiss_output bunched_beam]
    foreach arg $argList {set $arg ""}
    set eleOutputFile ""
    APSParseArguments [concat $argList eleOutputFile]

    array set run_setup_Array [list lattice "" use_beamline "" p_central_mev 7e3 default_order 1 concat_order 1 rootname "" \
				   parameters "" centroid ""]
    array set load_parameters_Array [list filename "" filename_list "" allow_missing_elements 1 allow_missing_parameters 1 \
					 change_defined_values 1]
    array set alter_elements_Array [list name "" type "" item "" value "" allow_missing_elements 1]
    array set run_control_Array [list n_steps 1]
    array set correct_Array [list mode orbit method global verbose 0 n_iterations 0 n_xy_cycles 1 \
				 correction_fraction [list 1.0 1.0] corrector_tweek [list 1e-5 1e-5] fixed_length 0 \
				 fixed_length_matrix 0]
    array set closed_orbit_Array [list output "" output_monitors_only 1 fixed_length 0]
    array set correction_matrix_output_Array [list response "" output_at_each_step 1 fixed_length 0]
    array set twiss_output_Array [list filename "" radiation_integrals 0 output_at_each_step 1 matched 1 reference_file "" \
				      reference_element ""]
    array set bunched_beam_Array [list n_particles_per_bunch 1]

    if [catch {open $eleOutputFile w} fileId] {
        return -code error "Cannot open the file $eleOutputFile for writing: $fileId"
    }
    foreach command $argList {
	if [string length [set $command]] {
	    #------ command is a list of lists of options to allows for multiple same-name commands (like load_parameters)
	    set commandList [set $command]
	    if {[string compare $command load_parameters2] == 0} {set command load_parameters}
	    foreach singleCommand $commandList {
		array set optionsArray $singleCommand
		array set defaultOptionsArray [array get ${command}_Array]
		foreach option [array names optionsArray] {set defaultOptionsArray($option) $optionsArray($option)}
		#------ Cannot have load_parameters with empty filename and filename_list - elegant gives error.
		if {[string compare $command load_parameters] == 0} {
		    foreach option [array names optionsArray] {set defaultOptionsArray($option) $optionsArray($option)}
		    if {![string length $defaultOptionsArray(filename)] \
			    && ![string length $defaultOptionsArray(filename_list)]} {
			unset optionsArray
			unset defaultOptionsArray
			continue
		    }
		}
		puts $fileId "&$command"
		foreach option [array names defaultOptionsArray] {
		    if [string length $defaultOptionsArray($option)] {
			if {[llength $defaultOptionsArray($option)] == 1} {
			    puts $fileId "   $option = $defaultOptionsArray($option),"
			} else {
			    if {[string compare $option filename_list] == 0} {
				puts $fileId "   $option = \"$defaultOptionsArray($option),\""
			    } else {
				puts $fileId "   ${option}\[0\] = [join $defaultOptionsArray($option) ,],"
			    }
			}
		    }
		}
		puts $fileId "&end"
		puts $fileId " "
		unset optionsArray
		unset defaultOptionsArray
	    }
	}
    }

    puts $fileId "&track &end"
    puts $fileId " "
    puts $fileId "&stop &end"
    
    close $fileId
}

#-----------------------------------------------------------------------------------------------------------------------

proc GetAverageSextupoleCurrents { args } {

    APSParseArguments {restoreString}
    set tol 1.0
    APSSetVarAndUpdate status "Getting sextupole settings..."
    if $restoreString {
        if [catch {exec cavget -list=S -range=beg=1,end=40 -list=A:S3,A:S4,B:S3 -list=:CurrentAO \
                     -cavputForm -pend=10} restoreSextupolesString] {
            return -code error "$restoreSextupolesString"
        }
    }

    if [catch {exec cavget -list=S -range=beg=1,end=40 -list=A:S1,A:S2,A:S3,A:S4,B:S3,B:S2,B:S1 \
		   -list=:CurrentAO -label} currentList] {
	return -code error "Error doing cavget: $currentList"
    }
    set N [llength $currentList]
    if {$N != 560} { return -code error "cavget: Less than 280 sextupoles returned." }
    for {set I 0} {$I <$N} {incr I 2} {
	lappend controlNameList [lindex $currentList $I]
	lappend valueStringList [lindex $currentList [expr $I + 1]]
    }
    if [catch {exec sddsmakedataset -pipe=out -col=ControlName,type=string -data=[join $controlNameList ,] \
		   -col=Value,type=double -data=[join $valueStringList ,] \
		   | sddsprocess -pipe \
		   -process=Value,average,S1Av,match=ControlName,value=*:S1:* \
		   -process=Value,average,S2Av,match=ControlName,value=*:S2:* \
		   -process=Value,average,S3Av,match=ControlName,value=*:S3:* \
		   -process=Value,average,S4Av,match=ControlName,value=*:S4:* \
		   -process=Value,standarddeviation,S1Stdev,match=ControlName,value=*:S1:* \
		   -process=Value,standarddeviation,S2Stdev,match=ControlName,value=*:S2:* \
		   -process=Value,standarddeviation,S3Stdev,match=ControlName,value=*:S3:* \
		   -process=Value,standarddeviation,S4Stdev,match=ControlName,value=*:S4:* \
		   | sdds2stream -pipe=in -param=S1Av,S1Stdev,S2Av,S2Stdev,S3Av,S3Stdev,S4Av,S4Stdev} valueList] {
	return -code error "Error processing cavget: $valueList"
    }

    if {([lindex $valueList 1] > $tol) || ([lindex $valueList 3] > $tol) \
	    || ([lindex $valueList 5] > $tol) || ([lindex $valueList 7] > $tol)} {
        APSInfoWindow .bigSigma -width 20 -infoMessage "Warning...\nSextupoles vary too much within families.\
            The corrections may not be correct. The program calculates dK2 values, then uses averaged over families currents \
            to calculate dI."
    }
    if $restoreString {
        return [list $restoreSextupolesString [format %8.3f [lindex $valueList 0]] [format %8.3f [lindex $valueList 2]] \
		    [format %8.3f [lindex $valueList 4]] [format %8.3f [lindex $valueList 6]]]
    } else {
        return [list [format %8.3f [lindex $valueList 0]] [format %8.3f [lindex $valueList 2]] \
		    [format %8.3f [lindex $valueList 4]] [format %8.3f [lindex $valueList 6]]]
    }
	
}

#-----------------------------------------------------------------------------------------------------------------------

proc ZeroIntendedChanges { } {

    global Chromaticity ChromaticityTotal deltaI deltaItotal
    foreach plane {x y} {
        set Chromaticity($plane) 0
        set ChromaticityTotal($plane) 0
    }
    foreach sext {S1 S2 S3 S4} {
        set deltaI($sext) 0
        set deltaItotal($sext) 0
    }
}

#-----------------------------------------------------------------------------------------------------------------------

set beamEnergy 7.0
array set Chromaticity "x 3.5 y 2.0"
array set ChromaticityTotal "x 0 y 0"
array set ChromaticityAccum "x 0 y 0"
set ExcludeSectors ""
set family S34
array set deltaI "S1 0 S2 0 S3 0 S4 0"
array set deltaItotal "S1 0 S2 0 S3 0 S4 0"

#Coefficients for the ideal lower-emittance lattice
set A(11)  4.991
set A(12)  0.586
set A(13)  0.541
set A(14)  4.017
set A(21) -3.693
set A(22) -2.799
set A(23) -3.743
set A(24) -2.489

set Ainv(S1-1)  0.2371
set Ainv(S1-2)  0.0496
set Ainv(S2-1) -0.3128
set Ainv(S2-2) -0.4228
set Ainv(S3-1) -0.1818
set Ainv(S3-2) -0.2935
set Ainv(S4-1)  0.2734
set Ainv(S4-2)  0.0395

set status ""
APSScrolledStatus .status -parent .userFrame -textVariable status -width 80 -height 7

if [catch {GetAverageSextupoleCurrents -restoreString 1} result] {
    APSSetVarAndUpdate status "GetSextupoleSettings: $result"
} else {
    set restoreSextupolesString [lindex $result 0]
    set I(S1) [lindex $result 1]
    set I(S2) [lindex $result 2]
    set I(S3) [lindex $result 3]
    set I(S4) [lindex $result 4]
}

MakeMainFrame -parent .userFrame

set excitationFile /home/helios/oagData/sr/magnets/sext/averageExcitCurves.sdds
set scrFile /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamReference.gz
set lteFile $OAGGlobal(SRLatticesDirectory)/default/aps.lte
set beamline RING
set tmpDir /tmp
set BRhoPVName S:BRhoCALC
set xrefFile /home/helios/oagData/sr/magnets/sext/SSP_xref.sdds

