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

set CVSRevisionAuthor "\$Revision: 1.26 $ \$Author: emery $"

APSApplication . -name setpoints -version $CVSRevisionAuthor \
  -overview "Application setpoints generates a standardization file and setpoints file for a beamline or ring. An adjustment model is available for the quadrupoles. One can select between \"difference in K1\" (prefered choice), \"difference in I\" or \"ratio in I\"."

proc addBasicSCRcolumnsParameters {args} {
    global basicSCRcolumns basicSCRparameters
    set file ""
    set referenceSCRFile ""
    APSStrictParseArguments {file referenceSCRFile}
    if ![file exists $file] {
        return -code error "addBasicSCRcolumnsParameters: Can't find file $file"
    }
    if ![file exists $referenceSCRFile] {
        return -code error "addBasicSCRcolumnsParameters: Can't find file $referenceSCRFile"
    }

    if [catch {exec sddsxref $file $referenceSCRFile -noWarning \
                 -match=ControlName \
                 -take=[join $basicSCRcolumns ,] \
                 -transfer=para,[join $basicSCRparameters ,] \
             } result ] {
        return -code error "addBasicSCRcolumnsParameters: $result"
    }
    if [catch {exec sddsprocess $file -noWarning \
                 -reprint=col,BackupMsg,-  \
                 -reprint=col,RestoreMsg,-  \
             } result ] {
        return -code error "addBasicSCRcolumnsParameters: $result"
    }
    file delete ${file}~
    return
}

proc MakeInputFrame {widget args} {
    set parent ""
    global beamline paramFile xrefFile templateFile energy
    global outputFileDir outputFileRoot beamline
    global referenceParamFile referenceSnapFile adjustmentModel
    global SensitiveWidgetList OAGGlobal
    APSStrictParseArguments {parent}

    set w $parent$widget.frame
    APSFrame $widget -parent $parent -label "Input parameters"

    set widgetList [APSTabFrame .beamlines -parent $w -label "" \
                      -labelList "SR BTS" -width 900 -height 150 \
                      -commandList {{defaultFiles -beamline SR} {defaultFiles -beamline BTS}} ]
    $w.beamlines.frame configure -relief flat
    pack $w.beamlines -side top
    $w.beamlines.frame.tn select 0
    lappend SensitiveWidgetList $w.beamlines.frame.tn
    set windex 0

    # SR frame
    set tabwidget [lindex $widgetList $windex]
    incr windex
    APSFrame .sr -parent $tabwidget \
      -label ""  -contextHelp "Frame which specifies data for SR beamline"
    set w $tabwidget.sr.frame

    APSLabeledEntry .parametersFile -parent $w -label "SR parameters file: " \
      -textVariable paramFile(SR) -width 65 \
      -contextHelp "Enter the name of the elegant parameters file. Program madto is used to create the KnL columns"
    APSButton .findParametersFile -parent $w.parametersFile \
      -text F -size small -packOption "-side right" \
      -command {set paramFile(SR) [APSFileSelectDialog .openDialog -pattern {*.param} \
                                   -listDir $OAGGlobal(SRLatticesDirectory) \
                                   -contextHelp "Select a parameters file which will be converted to a standardization file, snapshot file." \
                                   -title "Select Parameters File:"]
          update idletasks}
    
    APSLabeledEntry .referenceParametersfile -parent $w -label "SR reference parameters file: " \
      -textVariable referenceParamFile(SR) -width 65 \
      -contextHelp "Enter the name of a reference SR parameters file. The KnL values of this file and the current setpoints of the reference SR snapshot will be used to adjust the current setpoints calculated from the magnet measurement data. This adjustment help in obtaining a closer tune value."
    APSButton .findRefParametersFile -parent $w.referenceParametersfile \
      -text F -size small -packOption "-side right" \
      -command {set referenceParamFile(SR) [APSFileSelectDialog .openDialog -pattern {*.param} \
                                            -listDir $OAGGlobal(SRLatticesDirectory) \
                                            -contextHelp "Select a reference elegant parameters file."\
                                            -title "Select Parameters File:"]
          update idletasks}
    
    APSLabeledEntry .referenceSnapFile -parent $w -label "SR reference snapshot file: " \
      -textVariable referenceSnapFile(SR) -width 65 \
      -contextHelp "Enter the name of a reference SR snapshot (from SaveCompareRestore). The current setpoints (CurrentAO) of this fileand the KnL values of the reference SR lattice file will be used to adjust the current setpoints calculated from the magnet measurement data. This adjustment help in obtaining a closer tune value."
    APSButton .findRefSnapFile -parent $w.referenceSnapFile \
      -text F -size small -packOption "-side right" \
      -command {set referenceSnapFile(SR) [APSFileSelectDialog .openDialog -pattern {SR*gz} \
                                         -listDir /home/helios/oagData/SCR/snapshots/SR \
                                         -contextHelp "Select a snapshot file which will be used in calculating adjusted current setpoints." \
                                         -title "Select Snapshot File:"]
          update idletasks}
    
    set help0 "Select the model of the adjustment of the magnet setpoints relative to the magnet measurement data. Applicable only for quadrupole setpoints. The possible adjustment models are"

    set help1 "None:\nSet current value according to magnet measurement data (i.e. no adjustment): I_new = I_magMeas(K1_new)."

    set help2 "Difference in K1:\nThe difference in K1 between the magnet measurement data and the actual operation is due to some fixed and local focusing error, say an orbit offset through a nearby sextupole. This difference is denoted deltaK = K1(I_ref) - K1_ref. The new current setpoint is determined from\nI_new = I_magMeas(K1) where K1 = K1_new + deltaK = K1_new + (K1(I_ref) - K1_ref). Experience shows that this model is prefered over the others."

    set help3 "Difference in I:\nThe current difference between the magnet measurement data and the actual operation is a constant independent of strength, which could vary from magnet to magnet.  The origin could be power supply offset. To make the correction we add the differences in current between magnet measurement and snapshot file values for a reference lattice. i.e. I_new = I_ref + (I_magMeas(K1_new) - I_magMeas(K1_ref))."

    set help4 "Ratio in I:\nThe current ratio between the magnet measurement data and the actual operation is a constant independent of strength, which could vary from magnet to magnet. The origin could be power supply miscalibration. To make the correction we keep the ratio between the current in the two model constant when setting the I in the ring. i.e. I_new = I_ref (I_magMeas(K1_new)/I_magMeas(K1_ref))"

    set help5 "Correspondence between data and input files:\nK1_new: SR parameters file\nK1_old: SR reference parameters file\nI_ref: SR reference snapshot file"

    APSRadioButtonFrame .model -parent $w -orientation horizontal \
      -variable adjustmentModel(SR) \
      -label "Adjustment model for quadrupoles:" \
      -buttonList {none "difference in K1" "difference in I" "ratio in I"} -valueList {none differenceInK1 differenceInI ratioInI} \
      -contextHelp "$help0\n\n$help1\n\n$help2\n\n$help3\n\n$help4\n\n$help5"


# BTS frame
    set tabwidget [lindex $widgetList $windex]
    incr windex
    set w $tabwidget.bts.frame
    APSFrame .bts -parent $tabwidget \
      -label ""  -contextHelp "Frame which specifies data for BTS beamline"
    APSLabeledEntry .latticeFile -parent $w -label "BTS Parameters file: " \
      -textVariable paramFile(BTS) -width 65 \
      -contextHelp "Enter the name of the elegant parameters file. Program madto is used to create the KnL columns"
    APSButton .findfile -parent $w.latticeFile \
      -text F -size small -packOption "-side right" \
      -command {set paramFile(BTS) [APSFileSelectDialog .openDialog -pattern {*.param} \
                                   -listDir $OAGGlobal(BTSLatticesDirectory)/Booster2SR/standard \
                                   -contextHelp "Select a lattice file which will be converted to a standardization file, snapshot file." \
                                   -title "Select Lattice File:"]
          update idletasks}

# continue with main frame
    set w $parent$widget.frame
# removed B and doBends since we no longer think we'll need that option.
    APSCheckButtonFrame .magnetType -parent $w -orientation horizontal \
      -label "magnet type: " -variableList {doQuads doSexts} \
      -buttonList {Q S} -allNone 1 \
      -contextHelp \
      "Choose the magnet type."
    APSLabeledEntry .energy1 -parent $w -label "Reference energy (GeV): " \
      -textVariable energyRef \
      -contextHelp "Energy corresponding to reference SCR file. Enter the energy in GeV."
    APSLabeledEntry .energy2 -parent $w -label "Energy (GeV): " \
      -textVariable energy \
      -contextHelp "Energy for newSolution file. Enter the energy in GeV."
    APSFrame .saveData -parent $w -label "Save data" \
      -contextHelp "Output standardization file."
    APSLabeledEntry .outputFileDir -parent $w.saveData.frame -label "directory: " \
      -textVariable outputFileDir -width 50 \
      -contextHelp "Directory for standardization file."
    APSButton .daily -parent $w.saveData.frame.outputFileDir \
      -text "Daily" -size small \
      -packOption {-side top} \
      -command {set outputFileDir [APSGoToDailyDirectory]}
    APSLabeledEntry .outputFileRoot -parent $w.saveData.frame -label "root: " \
      -textVariable outputFileRoot -width 50 \
      -contextHelp "Root name for standardization file."
    return
}

# determines file lists for variables xrefFile and templateFile when
# the tab is selected.  Lists are required because of the different
# types of magnets.
proc defaultFiles {args} {
    global beamline xrefFile templateFile  magnetType BRhoPVName
    global doQuads doSexts doBends 
    APSStrictParseArguments {beamline}
    set xrefFile($beamline) ""
    set templateFile($beamline) ""
    switch $beamline {
        SR {
            set BRhoPVName S:BRhoCALC
            set directory /home/helios/oagData/controlFiles/SR
            set templateDir /home/helios/oagData/sr/magnetConditioning/templates
            if $doQuads {
                lappend xrefFile($beamline) $directory/SQ_xref.sdds
                lappend templateFile($beamline) $templateDir/SQ_stand.sdds
            }
            if $doSexts {
                lappend xrefFile($beamline) $directory/SS_xref.sdds
                lappend templateFile($beamline) $templateDir/SS_stand.sdds
            }
            if $doBends {
                lappend xrefFile($beamline) $directory/SB_xref.sdds
                lappend templateFile($beamline) $templateDir/SB_stand.sdds
            }
        }
        BTS {
            set BRhoPVName S:BRhoCALC
            set directory /home/helios/oagData/controlFiles/BTS/magnetData
            set templateDir /home/helios/oagData/BTS/magnetConditioning/templates
            if $doQuads {
                lappend xrefFile($beamline) $directory/BTSQ_xref.sdds
                lappend templateFile($beamline) $templateDir/BTSQ_standardize.sdds
            }
            if $doBends {
                lappend xrefFile($beamline) $directory/BTSB_xref.sdds
                lappend templateFile($beamline) $templateDir/BTSB_standardize.sdds
            }
        }
    }
    set status "Beamline switched to $beamline."
    return
}

set status "Working."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 90
set doQuads 1
set doSexts 1
# doBends doesn't work yet because there is one power supply 
# but 80 different dipole elements.
set doBends 0
set latticeFile ""
set energy 7 
set energyRef 7 
set outputFileDir .
set outputFileRoot NewSolution
set latticeFile ""

set paramFile(SR) $OAGGlobal(SRLatticesDirectory)/default/aps.param
set referenceParamFile(SR) $OAGGlobal(SRLatticesDirectory)/default/aps.param
set referenceSnapFile(SR) /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz
set adjustmentModel(SR) none

set paramFile(BTS) $OAGGlobal(BTSLatticesDirectory)/Booster2SR/default/bts.param
set referenceParamFile(BTS) $OAGGlobal(BTSLatticesDirectory)/Booster2SR/default/bts.param
set referenceSnapFile(BTS) /home/helios/oagData/SCR/snapshots/Booster/Booster-LowE1Reference325.gz
set adjustmentModel(BTS) none

set statusCallback ""
set abortVariable ""

MakeInputFrame .input -parent .userFrame
set status "Ready."
set abortRun 0
update

set basicSCRcolumns "ControlName ControlType Lineage \
     ControlMode Count ValueString Category IsNumerical Tolerance Beamline \
     OpsIntervention IsReadOnly IsProtected Description"
set basicSCRparameters "TimeStamp LoginID EffectiveUID GroupID BurtKeywords \
     BurtComments SnapType Time SnapshotDescription RequestFile SnapshotFilename"

APSButton .run -parent .userFrame -text Calculate -command \
  { \
      APSDisableButton .userFrame.run.button 
      APSEnableButton .userFrame.stop.button 
      defaultFiles -beamline $beamline
      catch { \
          switch $adjustmentModel($beamline) {
              none {
                  # after procedure setpoint is run, there should be an unperturbed
                  # magnet settings files *.std, *results, *.snp in the
                  # $outputFileDir directory.
                  APSMpMagnetSetpoints -paramFile $paramFile($beamline) \
                      -xrefFileList $xrefFile($beamline) \
                      -templateFileList $templateFile($beamline) \
                      -energy $energy -BRhoPVName $BRhoPVName \
                      -outputFileDir $outputFileDir -outputFileRoot $outputFileRoot \
                      -statusCallback SetStatus \
                      -abortVariable abortRun
                  addBasicSCRcolumnsParameters -file $outputFileDir/$outputFileRoot.snp \
                         -referenceSCRFile $referenceSnapFile($beamline)
              }
              differenceInK1 {
                  set tmproot /tmp/[APSTmpString]
                  set newParamFile ${tmproot}.newParam
                  # For I = I(K1(I_ref) + (K1 - K1_ref))
                  # need the following files: SCR, xref, parameters of original lattice, 
                  # and parameters of new optics.
                  # this call should leave the sextupole unchanged.
                  APSMpAdjustParameterFile \
                    -referenceSCRFile $referenceSnapFile($beamline) \
                    -xrefFileList $xrefFile($beamline) \
                    -energy $energyRef -BRhoPVName $BRhoPVName \
                    -refParamFile $referenceParamFile($beamline) \
                    -paramFile $paramFile($beamline) \
                    -outputParamFile $newParamFile  \
                    -statusCallback SetStatus
                  APSMpMagnetSetpoints -paramFile $newParamFile \
                      -xrefFileList $xrefFile($beamline) \
                      -templateFileList $templateFile($beamline) \
                      -energy $energy -BRhoPVName $BRhoPVName \
                      -outputFileDir $outputFileDir -outputFileRoot $outputFileRoot \
                      -statusCallback SetStatus \
                      -abortVariable abortRun
                  addBasicSCRcolumnsParameters -file $outputFileDir/$outputFileRoot.snp \
                         -referenceSCRFile $referenceSnapFile($beamline)
              }
              differenceInI -
              ratioInI -
              default {
                  set tmproot [APSTmpString]
                  # The difference model sets
                  # I = I(K1) + I_ref - I(K1_ref)
                  # procedure setpoints calculates I(K1)
                  # the adjustment procudure adds the correction term
                  # (I_ref - I(K1_ref))
                  # after this setpoint procedure is run, there should be
                  # magnet settings files *.std, *results, *.snp in the
                  # /tmp directory for the reference lattice.
                  APSMpMagnetSetpoints -paramFile $paramFile($beamline) \
                         -xrefFileList $xrefFile($beamline) \
                         -templateFileList $templateFile($beamline) \
                         -energy $energy -BRhoPVName $BRhoPVName \
                         -outputFileDir /tmp -outputFileRoot $tmproot.new0 \
                         -statusCallback SetStatus \
                         -abortVariable abortRun
                  APSMpMagnetSetpoints -paramFile $referenceParamFile($beamline) \
                         -xrefFileList $xrefFile($beamline) \
                         -templateFileList $templateFile($beamline) \
                         -energy $energyRef -BRhoPVName $BRhoPVName \
                         -outputFileDir /tmp -outputFileRoot $tmproot.ref0 \
                         -statusCallback SetStatus \
                         -abortVariable abortRun
                  APSMpAdjustMagnetSetpoints -newSnapFile /tmp/$tmproot.new0.snp \
                         -referenceSnapFile /tmp/$tmproot.ref0.snp \
                         -referenceSCRFile $referenceSnapFile($beamline) \
                         -adjustmentModel $adjustmentModel($beamline) \
                         -outputFileDir $outputFileDir \
                         -outputFileRoot $outputFileRoot \
                         -statusCallback SetStatus \
                         -abortVariable abortRun
                  addBasicSCRcolumnsParameters -file $outputFileDir/$outputFileRoot.snp \
                         -referenceSCRFile $referenceSnapFile($beamline)
              }
          }
      } status
      update idletasks
      APSDisableButton .userFrame.stop.button 
      APSEnableButton .userFrame.run.button }

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

proc SetStatus {text} {
    global status
    set status $text
    update
}
