#!/bin/sh
# \
exec oagtclsh  "$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

APSStandardSetup

# Input files: /home/helios/oagData/sr/BPMStatus/config.sdds
#              /home/helios/oagData/sr/lattices/templates/aps.lte
#              /home/helios/oagData/sr/lattices/default/aps.lte
#              /home/helios/oagData/sr/lattices/scripts/twiss.ele
#              /home/helios/oagData/sr/lattices/scripts/twiss-with-load-parameter-files.ele
#              /home/helios/oagData/sr/lattices/scripts/chromMatrix.ele
#              /home/helios/oagData/sr/lattices/scripts/sector01.ele
#              /home/helios/oagData/sr/lattices/scripts/correctorResponse.ele
#              /home/helios/oagData/sr/lattices/scripts/quadrupoleHResponse.ele
#              /home/helios/oagData/sr/lattices/scripts/quadrupoleVResponse.ele
#
# Output files: /home/helios/oagData/sr/lattices/default/aps.param
#               /home/helios/oagData/sr/lattices/default/aps.template.lte
#               /home/helios/oagData/sr/lattices/default/correctorResponse.ele
#               /home/helios/oagData/sr/lattices/default/quadrupoleHResponse.ele
#               /home/helios/oagData/sr/lattices/default/quadrupoleVResponse.ele
#               /home/helios/oagData/sr/lattices/default/aps.mag
#               /home/helios/oagData/sr/lattices/default/aps.twi.0
#               /home/helios/oagData/sr/lattices/default/apsNatChrom.mag
#               /home/helios/oagData/sr/lattices/default/apsNatChrom.param
#               /home/helios/oagData/sr/lattices/default/twiss.log
#               /home/helios/oagData/sr/lattices/default/apsNatChrom.twi
#               /home/helios/oagData/sr/lattices/default/sector01.mag
#               /home/helios/oagData/sr/lattices/default/sector01.twi
#               /home/helios/oagData/sr/lattices/default/sector01.param
#               /home/helios/oagData/sr/lattices/default/sector01.log
#               /home/helios/oagData/sr/lattices/default/sector01.png
#               /home/helios/oagData/sr/lattices/default/aps.twiAve
#               /home/helios/oagData/sr/lattices/scripts/SRBPMPosition.xref
#               /home/helios/oagData/sr/lattices/scripts/SRCorrPosition.xref
#               /home/helios/oagData/sr/lattices/scripts/SRBPMCorrPosition.xref
#               /home/helios/oagData/sr/lattices/scripts/SRBPMPosition.startS1.xref
#               /home/helios/oagData/sr/lattices/scripts/SRCorrPosition.startS1.xref
#               /home/helios/oagData/sr/lattices/scripts/SRBPMCorrPosition.startS1.xref
#               /home/helios/oagData/sr/sddsmonitorFiles/SROrbit-Rootnames.vmon
#               /home/helios/oagData/sr/lattices/default/aps.twi
#               /home/helios/oagData/sr/lattices/default/correctorResponse.log
#               /home/helios/oagData/sr/lattices/default/aps.flqhrm.0
#               /home/helios/oagData/sr/lattices/default/aps.flqhrm
#               /home/helios/oagData/sr/lattices/default/quadrupoleHResponse.log
#               /home/helios/oagData/sr/lattices/default/aps.flqvrm.0
#               /home/helios/oagData/sr/lattices/default/aps.flqvrm
#               /home/helios/oagData/sr/lattices/default/quadrupoleVResponse.log
#               /home/helios/oagData/sr/rtfeedback/lattices/default/refMatrices/h.default
#               /home/helios/oagData/sr/rtfeedback/lattices/default/refMatrices/v.default
#               /home/helios/oagData/sr/rtfeedback/lattices/default/refMatrices/h.free.default
#               /home/helios/oagData/sr/rtfeedback/lattices/default/refMatrices/v.free.default
#               /home/helios/oagData/sr/orbitControllaw/lattices/default/refMatrices/h.default
#               /home/helios/oagData/sr/orbitControllaw/lattices/default/refMatrices/v.default
#               /home/helios/oagData/sr/orbitControllaw/lattices/default/refMatrices/h.free.default
#               /home/helios/oagData/sr/orbitControllaw/lattices/default/refMatrices/v.free.default
#               /home/helios/oagData/sr/fastOrbitControllaw/lattices/default/refMatrices/h.default
#               /home/helios/oagData/sr/fastOrbitControllaw/lattices/default/refMatrices/v.default
#               /home/helios/oagData/sr/fastOrbitControllaw/lattices/default/refMatrices/h.free.default
#               /home/helios/oagData/sr/fastOrbitControllaw/lattices/default/refMatrices/v.free.default
#               /home/helios/oagData/sr/lattices/default/aps.flhrm
#               /home/helios/oagData/sr/lattices/default/aps.free.hrm
#               /home/helios/oagData/sr/lattices/default/aps.flvrm
#               /home/helios/oagData/sr/lattices/default/nonExistentBPMs
#               /home/helios/oagData/sr/lattices/default/aps.free.vrm
#               /home/helios/oagData/sr/lattices/default/aps.hrm
#               /home/helios/oagData/sr/lattices/default/aps.free.hrm.I
#               /home/helios/oagData/sr/lattices/default/aps.vrm
#               /home/helios/oagData/sr/lattices/default/aps.free.vrm.I
#               /home/helios/oagData/sr/rfOrbitControllaw/lattices/default/refMatrices/nonExistentBPMs
#               /home/helios/oagData/sr/rfOrbitControllaw/lattices/default/refMatrices/h.default
#
# scripts:      plotTwiss
#               averageOverElements
#               convertAPSUResponseMatrix
#               createDefinitionsFileForSRbpmAndCorrectors (only on the weed cluster)
#

# Creates orbit controllaw reference matrices.
# Usually run by user oag from any directory. There is an internal cd command.

set usage "usage: makeOCRefMatrices \[-latticeDir <lattice-dir-name>\] \{-latticeLteFile <lte-file> \| -parameterFileList <list-of-files>\}"
set latticeDir "default"
set latticeLteFile ""
set parameterFileList ""
set verbose 0
set args $argv
APSParseArguments {latticeDir latticeLteFile parameterFileList verbose}

if {[string length $latticeLteFile] &&  [string length $parameterFileList]} {
    puts stderr "Can't have both latticeLteFile and parameterFileList:\n$usage"
    exit 1
}
if {![string length $latticeLteFile] &&  ![string length $parameterFileList]} {
    puts stderr "One of latticeLteFile and parameterFileList must be provided:\n$usage"
    exit 1
}
if [string length $latticeLteFile] {
    set sourceMode latticeLteFile
} else {
    set sourceMode parameterFiles
}

# The choice is to use
# 1) an in-directory elegant lattice file or
# 2) the elegant template lattice file PLUS one or more in-directory *.param file to change the K1 and K2.
# The template file is always
# /home/helios/oagData/sr/lattices/templates/aps.lte
# under revision control.
# If an elegant lattice file is to be used, then it must be named differently from aps.lte
# because that name is reserved for the "save" file output.
# The reason for in-directory requirement of files is for checking the consistency of results at a later date.
# It would be simpler to have only one mode of source input for this script, but we have traditionally had
# the option, and I can see how it can be useful later

cd /home/helios/oagData/sr/lattices/${latticeDir}

set dataDir /home/helios/oagData/sr/BPMStatus
# scripts should be in revision control, BTW
set scriptDir /home/helios/oagData/sr/lattices/scripts

# If there is any versioning of files in this directory. It would be a manual
# versioning of the sources, and not the local output

if {$sourceMode == "parameterFiles"} {
    # check if files exists
    foreach file $parameterFileList {
        if {![file exists $file]} {
            puts stderr "Error for $argv0: Can't find file $file in $parameterFileList in [pwd]"
            exit 1
        }
    }
}

# elegant output aps.param file versioning
set rootname aps
if [catch {set latestParaFile [lindex [lsort [glob $rootname.param-????]] end]} result] {
    # a dummy file just to have start the chain of versions
    exec touch $rootname.param-0000
    set latestParaFile $rootname.param-0000
}
set outputParaFile [APSNextGenerationedName -name $latestParaFile -newFile 1]
if [file exists ${rootname}.param] {
    if [catch {file delete ${rootname}.param} result] {
        puts stderr "Error for $argv0 in [pwd]: $result"
        exit 1  
    }
}
if [catch {exec ln -s $outputParaFile ${rootname}.param} result] {
    puts stderr "Error for $argv0 in [pwd]: $result"
    exit 1
}

# remove rows for bpms that are non-existent in the input file, which could
# be a full or comprehensive file, say, a twi file
proc removeNonexistentBpms {args} {
    global dataDir
    global argv0

    set input ""
    set column ""
    set output ""
    # default keep the P0s that are used to make ID bpm responses.
    set keepP0s 1
    APSParseArguments {input column output keepP0s}
    if ![string length $input] {
        return -code error "removeNonexistentBpms: No input specified."
    }
    if ![string length $column] {
        return -code error "removeNonexistentBpms: No column specified."
    }
    if ![string length $output] {
        set output $input
    }
    
    set tmpFile /tmp/[APSTmpString]
    if $keepP0s {
        if [catch {exec sddsprocess $dataDir/config.sdds nonExistentBPMs \
                       -filter=col,NonexistentH,1,1,NonexistentV,1,1,& \
                       -match=col,DeviceName=S*P0,! 
            exec sddsselect $input nonExistentBPMs $output \
                       -match=$column=DeviceName -invert \
                   } result ] {
            puts stderr "removeNonexistentBpms: $result"
            exit 1
        }
    } else {
        if [catch {exec sddsprocess $dataDir/config.sdds nonExistentBPMs \
                       -filter=col,NonexistentH,1,1,NonexistentV,1,1,& 
            exec sddsselect $input nonExistentBPMs $output \
                       -match=$column=DeviceName -invert \
                   } result ] {
            puts stderr "removeNonexistentBpms: $result"
            exit 1
        }
    }
    return
}

#puts stderr "Processing may take about 75 seconds."
set StartTime [clock seconds]

# Always use the newest version of the elegant template lattice file 
# as a starting point
set templateFile /home/helios/oagData/sr/lattices/templates/aps.lte
if [catch {exec cp $templateFile aps.template.lte} result] {
    puts stderr "$argv0 in [pwd]: problem copying file $templateFile to aps.template.lte"
    exit 1
}

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

proc AddElements {args} {

    APSParseArguments {kickFile addRF addMalin addW1 finalBeamline}

    if [catch {exec grep RFCA $kickFile | grep RF:} result] {set rfElementExists 0} else {set rfElementExists 1}
    if [catch {exec grep MALIN: $kickFile} result] {set malinExists 0} else {set malinExists 1}
    if [catch {exec grep W1: $kickFile} result] {set w1Exists 0} else {set w1Exists 1}
    if {[string length $finalBeamline] && ($addRF || $addMalin || $addW1)} {
        set addBeamline 1
        if [catch {exec grep ${finalBeamline}: $kickFile} result] {set beamlineExists 0} else {
            puts stderr "Error: $finalBeamline already exists in $kickFile."
            exit
        }
    }

    set doneElements 0
    set doneBeamline 0
    if [catch {open $kickFile r} fid1] {return -code error "Error opening $kickFile: $fid1"}
    if [catch {open $kickFile.tmp w} fid2] {return -code error "Error opening $kickFile.tmp: $fid2"}
    while {[gets $fid1 line] >= 0} {
        #--- Add elements:
        if {[string first RING: $line] != -1} {
            if !$doneElements {
                if {$addRF && !$rfElementExists} {puts $fid2 "RF: RFCA"}
                if {$addMalin && !$malinExists} {puts $fid2 "MALIN: MALIGN"}
                if {$addW1 && !$w1Exists} {puts $fid2 "W1: WATCH, FILENAME=\"%s.w1\", mode=parameter"}
            }
            set doneElements 1
        }
        #--- Add finalBeamline:
        if {[string first USE, $line] != -1} {
            if $addBeamline {
                set elementSeq RING
		if $addRF {append elementSeq ",RF"}
		if $addW1 {set elementSeq "W1,$elementSeq"}
		if $addMalin {set elementSeq "MALIN,$elementSeq"}
		if !$doneBeamline {puts $fid2 "$finalBeamline: LINE=($elementSeq)"}
                set doneBeamline 1
            }
        }
        puts $fid2 $line
    }
    if {$addBeamline && !$doneBeamline} {
        set elementsSeq RING
        if $addRF {append elementSeq ",RF"}
        if $addW1 {set elementSeq "W1,$elementSeq"}
        if $addMalin {set elementSeq "MALIN,$elementSeq"}
        puts $fid2 "$finalBeamline: LINE=($elementSeq)"
    }
    close $fid1; close $fid2
    file copy -force $kickFile.tmp $kickFile
    catch {file delete $kickFile.tmp}
}

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

proc MakeKickFile {args} {
    APSParseArguments {lteFile kickFile}
    catch {file delete $kickFile}
    exec cat $lteFile \
      | replaceText -stdio -original=QUAD -replacement=KQUAD\\,N_KICKS=30 -filter=K1 \
      | replaceText -stdio -original=QUAD -replacement=KQUAD\\,N_KICKS=5 -filter=TILT \
      | replaceText -stdio -original=SEXT -replacement=KSEXT\\,N_KICKS=3 \
      | replaceText -stdio -original=\\,ORDER=2 -replacement= -filter=SEX \
      | replaceText -stdio -original=SBEN -replacement=CSBEN\\,N_KICKS=100 -filter=A:M \
      | replaceText -stdio -original=SBEN -replacement=CSBEN\\,N_KICKS=100 -filter=B:M \
      | replaceText -stdio -original=SBEN -replacement=CSBEN\\,N_KICKS=5 -filter=:H1M > $kickFile   
    if [catch {AddElements -kickFile $kickFile -addRF 1 -addMalin 1 -addW1 1 -finalBeamline RINGRF} result] {
        return -code error "AddElements: $result"
    }
}

# Refresh elegant command files in case new ones were generated since last time
# can't use tcl command "file copy" since that retains the softlink.
exec cp -f $scriptDir/twiss.ele .
exec cp -f $scriptDir/chromMatrix.ele .
# this file helps create plots of the twiss functions in a sector.
exec cp -f $scriptDir/sector01.ele .
exec cp -f $scriptDir/correctorResponse.ele .
exec cp -f $scriptDir/quadrupoleHResponse.ele .
exec cp -f $scriptDir/quadrupoleVResponse.ele .

proc AddEffectiveEmittance {args} {
    APSParseArguments {file}
    set tmpFile [APSTmpString].twi
    set coupling 0.01

    #check if radiation integrals are present
    set integralsPresent 0
    if {-1 < [lsearch [exec sddsquery -para $file] ex0]} {
        set integralsPresent 1
    }

    if $integralsPresent {
        if [catch {exec sddsprocess $file $tmpFile -nowarning \
                     "-def=para,emitx,ex0,units=\$gp\$rm" \
                     "-def=para,emity,ex0 $coupling *,units=\$gp\$rm" \
                     "-def=col,gammax,alphax sqr 1 + betax /,units=1/m" \
                     "-def=col,gammay,alphay sqr 1 + betay /,units=1/m" \
                     "-def=col,Sigmax,emitx betax * etax Sdelta0 * sqr + sqrt 1e6 *,units=um" \
                     "-def=col,Sigmaxp,emitx gammax * etaxp Sdelta0 * sqr + sqrt 1e6 *,units=urad" \
                     "-def=col,Sxxp,Sdelta0 sqr etax * etaxp * alphax emitx * - 1e12 *,units=um-urad" \
                     "-def=col,Sigmay,emity betay * etay Sdelta0 * sqr + sqrt 1e6 *,units=um" \
                     "-def=col,Sigmayp,emity gammay * etayp Sdelta0 * sqr + sqrt 1e6 *,units=urad" \
                     "-def=col,EffectiveEmittance,Sigmax Sigmaxp * sqr Sxxp sqr - sqrt 1e3 /,units=nm-rad" \
                     -process=EffectiveEmittance,first,%s \
                     "-print=para,tuneString,nux: %7.4g  nuy: %7.4g,nux,nuy" \
                     -def=para,EffectiveEmittancePresent,1,type=long \
                 } result ] {
            puts stderr "AddEffectiveEmittance: $result"
        }
        catch {exec mv -f $tmpFile $file}
    } else {
        return -code error "AddEffectiveEmittance: integrals not present"
    }
    return
}

if $verbose {
    puts stderr "calculating twiss data..."
}
# elegant command file twiss.ele writes files aps.lte and aps.param, which can
# be reused by other elegant commands
switch $sourceMode {
    latticeLteFile {
        if [catch {file delete -force twiss.log 
            exec elegant twiss.ele -macro=input=$latticeLteFile >& twiss.log \
                   } result ] {
            puts stderr "$argv0 in [pwd]: problem with elegant twiss run(1): $result"
            exit 1
        }
    }
    parameterFiles {
        if [catch {file delete -force twiss.log 
            exec elegant twiss-with-load-parameter-files.ele -macro=input=$templateFile,parameterFileList=$parameterFileList >& twiss.log \
                   } result ] {
            puts stderr "$argv0 in [pwd]: problem with elegant twiss run(2): $result"
            exit 1
        }
    }
}

#if [catch {MakeKickFile -lteFile aps.lte -kickFile apsKick.lte} result] {
#    puts stderr "MakeKickFile: $result"
#    exit 1
#}

if $verbose {
    puts stderr "calculating effective emittance data..."
}
if [catch {AddEffectiveEmittance -file apsNatChrom.twi \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit 1
}


if $verbose {
    puts stderr "Creating twiss plots..."
}
# create files for use by the general public.
if [catch {file delete -force sector01.log} result ] {
    puts stderr "$argv0 in [pwd]: There was the following error while creating file sector01.png (0): $result. Continue execution."
}
if [catch {exec elegant sector01.ele >& sector01.log} result ] {
    puts stderr "$argv0 in [pwd]: There was the following error while creating file sector01.png (1): $result. Continue execution."
}
if [catch {exec plotTwiss -fileRoot sector01 -largePng 1 -pngFile sector01.png -thick 1 -noDisplay 1} result ] {
    puts stderr "$argv0 in [pwd]: There was the following error while creating file sector01.png (2): $result. Continue execution."
}

# make sure that averageOverElements is put in an official place
if $verbose {
    puts stderr "Calculating average twiss quantities over elements..."
}
if [catch {exec averageOverElements -input aps.twi -output aps.twiAve \
             -itemList "betax betay  psix psiy" \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}

if [catch {file copy -force aps.twi aps.twi.0
    # this is to keep only bpms that exist
    removeNonexistentBpms -input aps.twi.0 -column ElementName -keepP0s 0 \
             -output aps.twi \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}

# make bpm position reference file
# this file is used by physics-related application
# such as beta function measurement. This file
# could be moved somewhere else.
if $verbose {
    puts stderr "Making bpm and corrector xref files..."
}
if [catch {exec sddsprocess aps.twi -pipe=out \
               -proc=s,last,Circumference \
               -match=col,ElementType=MONI \
               | sddsconvert -pipe \
               -retain=col,s,ElementName \
               | sddsprocess -pipe \
               -reprint=column,BPMName,%s,ElementName \
               "-def=col,Sector,s Circumference 40 / / " \
               "-def=col,SectorNumber,Sector int 0 > ? pop : 40 \$ ,type=long" \
               | sddssort -pipe=in ${scriptDir}/SRBPMPosition.xref \
               -col=s -col=ElementName -num} result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
# for traditional ordering, need to offset the "s" coordinate
if [catch {exec sddsprocess aps.twi -pipe=out \
               -proc=s,last,Circumference \
               -match=col,ElementType=MONI \
               | sddsconvert -pipe \
               -retain=col,s,ElementName \
               | sddsprocess -pipe \
               -reprint=column,BPMName,%s,ElementName \
               "-redef=col,s,s Circumference 40.0 / - Circumference mod" \
               "-def=col,Sector,s Circumference 40 / / 1 +" \
               "-def=col,SectorNumber,Sector int,type=long" \
               | sddssort -pipe=in ${scriptDir}/SRBPMPosition.startS1.xref \
               -col=s -col=ElementName -num} result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}

# make corrector position reference file
#S1->H1 KSEXT
#S1->V1 KSEXT
#Q7->H7 KQUAD
#Q7->V7 KQUAD
#Q8->V8 CSBEND
#Q4->Q4T CCBEND
#Q5->Q5T CCBEND
#Q8->Q8T CSBEND
#M3->M3T CSBEND
#M4->M4T CSBEND
#C:M2->C:H2 CSBEND ??
#C:M2->C:V2 CSBEND ??
if [catch {exec sddsprocess aps.twi -pipe=out \
               -proc=s,last,Circumference \
               -match=col,ElementType=HKICK,ElementType=VKICK,|,ElementType=HVKICK,|,ElementType=EHKICK,|,ElementType=EVKICK,| \
               | sddsconvert -pipe \
               -retain=col,s,ElementName \
               | sddsprocess -noWarn -pipe=in ${scriptDir}/SRCorrPosition.xref.HV \
               -reprint=column,CorrName,%s,ElementName \
               "-def=col,Sector,s Circumference 40 / / " \
               "-def=col,SectorNumber,Sector int 0 > ? pop : 40 \$ ,type=long"} result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
# twi file actually has sector 40 as first sector.
# for traditional ordering, sector 1 starting, which is
# needed for some applications, we need to offset the "s" coordinate
if [catch {exec sddsprocess aps.twi -pipe=out \
               -proc=s,last,Circumference \
               -match=col,ElementType=HKICK,ElementType=VKICK,|,ElementType=HVKICK,|,ElementType=EHKICK,|,ElementType=EVKICK,| \
               | sddsconvert -pipe \
               -retain=col,s,ElementName \
               | sddsprocess -noWarn -pipe=in ${scriptDir}/SRCorrPosition.startS1.xref.HV \
               -reprint=column,CorrName,%s,ElementName \
               "-redef=col,s,s Circumference 40.0 / - Circumference mod" \
               "-def=col,Sector,s Circumference 40 / / 1 +" \
               "-def=col,SectorNumber,Sector int,type=long"} result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
set fList ${scriptDir}/SRCorrPosition.xref.HV
set fListStartS1 ${scriptDir}/SRCorrPosition.startS1.xref.HV
foreach new ":H1 :V1 C:H2 C:V2 :H7 :V7 :V8 :Q4T :Q5T :Q8T :M3T :M4T" \
    old ":S1 :S1 C:M2 C:M2 :Q7 :Q7 :Q8 :Q4 :Q5 :Q8 :M3 :M4" \
    type "KSEXT KSEXT CSBEND CSBEND KQUAD KQUAD CSBEND CCBEND CCBEND CSBEND CSBEND CSBEND" {
        if [catch {exec sddsprocess aps.twi -nowarn -pipe=out \
                       -proc=s,last,Circumference \
                       "-match=col,ElementType=${type},ElementName=*${old},&" \
                       | sddsconvert -pipe \
                       -retain=col,s,ElementName \
                       | sddsprocess -nowarn -pipe -reedit=column,ElementName,%/${old}/${new}/ \
                       | sddsprocess -nowarn -pipe=in ${scriptDir}/SRCorrPosition.xref.${new} \
                       -reprint=column,CorrName,%s,ElementName \
                       "-def=col,Sector,s Circumference 40 / / " \
                       "-def=col,SectorNumber,Sector int 0 > ? pop : 40 \$ ,type=long"} result ] {
            puts stderr "$argv0 in [pwd]: $result"
            exit
        }
        # for traditional ordering, need to offset the "s" coordinate
        if [catch {exec sddsprocess aps.twi -nowarn -pipe=out \
                       -proc=s,last,Circumference \
                       "-match=col,ElementType=${type},ElementName=*${old},&" \
                       | sddsconvert -pipe \
                       -retain=col,s,ElementName \
                       | sddsprocess -nowarn -pipe -reedit=column,ElementName,%/${old}/${new}/ \
                       | sddsprocess -nowarn -pipe=in ${scriptDir}/SRCorrPosition.startS1.xref.${new} \
                       -reprint=column,CorrName,%s,ElementName \
                       "-redef=col,s,s Circumference 40.0 / - Circumference mod" \
                       "-def=col,Sector,s Circumference 40 / / 1 +" \
                       "-def=col,SectorNumber,Sector int,type=long"} result ] {
            puts stderr "$argv0 in [pwd]: $result"
            exit
        }
        lappend fList ${scriptDir}/SRCorrPosition.xref.${new}
        lappend fListStartS1 ${scriptDir}/SRCorrPosition.startS1.xref.${new}
    }
if {[catch {eval exec sddscombine $fList -pipe=out -merge | sddssort -pipe=in ${scriptDir}/SRCorrPosition.xref -col=s -col=ElementName -num} results]} {
    puts stderr "$argv0 in [pwd]: $results"
    exit
}
if {[catch {eval exec sddscombine $fListStartS1 -pipe=out -merge | sddssort -pipe=in ${scriptDir}/SRCorrPosition.startS1.xref -col=s -col=ElementName -num} results]} {
    puts stderr "$argv0 in [pwd]: $results"
    exit
}
eval file delete $fList
eval file delete $fListStartS1

# make corrector/monitor position reference file
if [catch {exec sddscombine ${scriptDir}/SRBPMPosition.xref \
             ${scriptDir}/SRCorrPosition.xref -pipe=out -merge | \
             sddssort -pipe=in ${scriptDir}/SRBPMCorrPosition.xref -col=s -col=ElementName -num} result] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {exec sddsconvert ${scriptDir}/SRBPMPosition.xref \
             /home/helios/oagData/sr/sddsmonitorFiles/SROrbit-Rootnames.vmon \
             -retain=col,s,ElementName \
             -rename=col,ElementName=Rootname \
         } result] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {exec sddscombine ${scriptDir}/SRBPMPosition.startS1.xref \
             ${scriptDir}/SRCorrPosition.startS1.xref -pipe=out -merge | \
             sddssort -pipe=in ${scriptDir}/SRBPMCorrPosition.startS1.xref -col=s -col=ElementName -num} result] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {exec sddsconvert ${scriptDir}/SRBPMPosition.startS1.xref \
             /home/helios/oagData/sr/sddsmonitorFiles/SROrbit-Rootnames.startS1.vmon \
             -retain=col,s,ElementName \
             -rename=col,ElementName=Rootname \
         } result] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}


# Need to keep all the P0s up to this point
# because they are used for ID xray bpm response.
# Source of bpm is the local aps.lte
if $verbose {
    puts stderr "Making response matrices..."
}
if [catch {file delete -force correctorResponse.log 
    exec elegant correctorResponse.ele  >& correctorResponse.log 
    file copy -force aps.flhrm aps.flhrm.0
    file copy -force aps.flvrm aps.flvrm.0 
    file copy -force aps.free.hrm aps.free.hrm.0
    file copy -force aps.free.vrm aps.free.vrm.0 \
          } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
# for quadrupole glitches, which could affect either plane
if [catch {file delete -force quadrupoleHResponse.log 
    exec elegant quadrupoleHResponse.ele  >& quadrupoleHResponse.log 
    file copy -force aps.flqhrm aps.flqhrm.0
          } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {file delete -force quadrupoleVResponse.log 
    exec elegant quadrupoleVResponse.ele  >& quadrupoleVResponse.log 
    file copy -force aps.flqvrm aps.flqvrm.0
          } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}

if [catch {removeNonexistentBpms -input aps.flhrm.0 -column BPMName -keepP0s 1 \
             -output aps.flhrm \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {removeNonexistentBpms -input aps.free.hrm.0 -column BPMName -keepP0s 1 \
             -output aps.free.hrm \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {removeNonexistentBpms -input aps.flvrm.0 -column BPMName -keepP0s 1 \
             -output aps.flvrm \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {removeNonexistentBpms -input aps.free.vrm.0 -column BPMName -keepP0s 1 \
             -output aps.free.vrm \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
catch {file delete aps.flhrm.0 aps.flvrm.0 aps.free.hrm.0 aps.free.vrm.0}

# the output files are in units of m/A, which is changed from APS with mm/A.
# presently convertAPSUResponseMatrix handles only the correctors in the limits list.
# we may need to include trims later.
if $verbose {
    puts stderr "Converting units in matrices..."
}
catch {exec rm aps.hrm aps.free.hrm.I aps.vrm aps.free.vrm.I}
if [catch {exec convertAPSUResponseMatrix -plane h -input aps.flhrm -output aps.hrm \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
# String I in the file name refers to power supply current, and not "inverse"
if [catch {exec convertAPSUResponseMatrix -plane h -input aps.free.hrm -output aps.free.hrm.I \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {exec convertAPSUResponseMatrix -plane v -input aps.flvrm -output aps.vrm \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}
if [catch {exec convertAPSUResponseMatrix  -plane v -input aps.free.vrm -output aps.free.vrm.I \
         } result ] {
    puts stderr "$argv0 in [pwd]: $result"
    exit
}

# make some definition files used by sddscontrollaw and matrices.
# Used by weed orbit simulator. 
# These are not the same definition files created by SRConfig.tcl as those are 
# created to go along the orbit correction configurations
if {$apsScriptHost == "head3.cluster"} {
    if [catch {exec createDefinitionsFileForSRbpmAndCorrectors -response aps.hrm} result ] {
        puts stderr "$argv0 in [pwd]: $result"
        exit
    }
    if [catch {exec createDefinitionsFileForSRbpmAndCorrectors -response aps.vrm} result ] {
        puts stderr "$argv0 in [pwd]: $result"
        exit
    }
}

if $verbose {
    puts stderr "Installing matrices..."
}
set oldDir [pwd]
set applicationList [list rfOrbitControllaw orbitControllaw fastOrbitFeedback]
foreach application $applicationList {
    set orbitCLDir /home/helios/oagData/sr/${application}/lattices/${latticeDir}/refMatrices
    if ![file exists $orbitCLDir] {
        file mkdir $orbitCLDir
    }
    cd $orbitCLDir
    set dateStamp [clock format [clock seconds] -format %Y-%m%d]
    set hname [APSNextGenerationedName -name h.$dateStamp.00 -separator . \
                   -newFile 1]
    set vname [APSNextGenerationedName -name v.$dateStamp.00 -separator . \
                   -newFile 1]
    
    switch $application {
        orbitControllaw -
        rtfeedback -
        fastOrbitControllaw {
            if [catch {file copy $oldDir/aps.hrm $hname
                file copy $oldDir/aps.vrm $vname
                file delete h.default v.default
                exec ln -s $hname h.default
                exec ln -s $vname v.default \
                     } result] {
                puts stderr "$result"
                exit 1
            }
# These have to be repeated following the creation of the above
# files. Otherwise you don't get a new number suffix.
            set hname [APSNextGenerationedName -name h.$dateStamp.00 -separator . \
                           -newFile 1]
            set vname [APSNextGenerationedName -name v.$dateStamp.00 -separator . \
                           -newFile 1]
            if [catch {file copy $oldDir/aps.free.hrm.I $hname
                file copy $oldDir/aps.free.vrm.I $vname
                file delete h.free.default v.free.default
                exec ln -s $hname h.free.default
                exec ln -s $vname v.free.default \
                     } result] {
                puts stderr "$result"
                exit 1
            }
        }
        rfOrbitControllaw {
            # The matrix elements should be in units of um/Hz
            set rfFrequency 352055036.6050960
            if [catch {exec sddsconvert $oldDir/aps.twi -pipe=out \
                         -retain=col,ElementName,etax \
                         -rename=col,ElementName=BPMName \
                         | sddsprocess -pipe=in /tmp/$hname \
                         -match=col,BPMName=S*:P? \
                         "-def=col,BRF:S:Hp8657RefFreqAO,etax $rfFrequency / alphac / 1e6 * chs" \
                     } result] {
                puts stderr "$result"
                exit 1
            }
            if [catch {removeNonexistentBpms -input /tmp/$hname -column BPMName -keepP0s 1 \
                           -output  $hname \
                       } result ] {
                puts stderr "$argv0 in [pwd]: $result"
                exit
            } 
            file delete h.default
            exec ln -s  $hname h.default
        }
    }
}

set Time [clock seconds]
set deltaTime [expr $Time - $StartTime]
if $verbose {
    puts stderr "Elapsed time for $argv0: $deltaTime"
}
exit

# this doesn't work from weed
if [string match $latticeDir default] {
    cd /home/helios/oagData/sr/lattices/${latticeDir}
    # copy files to the SR parameter web page
    set targetDir /net/epics-ops/web_roots/ops/SRparameters/otherFiles
    exec scp aps.lte $targetDir/aps.lte
    # make simple sector file
    exec scp /home/helios/oagData/sr/lattices/templates/sector01.lte $targetDir
}
set Time [clock seconds]
set deltaTime [expr $Time - $StartTime]
#puts stderr "Elapsed time for $argv0: $deltaTime"
exit 0

# Local Variables:
# mode: tcl
# End:
