#
# $Log: not supported by cvs2svn $
# Revision 1.82  2011/08/18 12:48:54  borland
# Added ability to process momentum apeture runs after running (in case
# script is interrupted while waiting).
#
# Revision 1.81  2011/06/06 14:02:44  borland
# Various updates.
#
# Revision 1.80  2011/06/02 17:32:41  borland
# Added ability to enable/disable orbit correction.
#
# Revision 1.79  2011/06/02 16:21:50  borland
# For FMA, can now specify using a single job (good for parallel mode).
#
# Revision 1.78  2011/06/02 16:16:31  borland
# Added ability to control number of orbit correction SVs.
#
# Revision 1.77  2011/06/02 03:02:28  borland
# Improved tolerance for lags on file server compared to queue.
#
# Revision 1.76  2011/06/01 23:50:45  borland
# Added features to improve portability to other systems.
#
# Revision 1.75  2011/06/01 18:47:18  borland
# IBS is now performed using grid engine if requested.
#
# Revision 1.74  2011/05/31 16:08:55  borland
# Improved file management for Basic and Moments calculations with errors.
#
# Revision 1.73  2011/05/27 07:30:03  borland
# Restored file deletion commands.
#
# Revision 1.72  2011/05/27 06:28:13  borland
# further improvements to beta beat analysis.
#
# Revision 1.71  2011/05/27 06:10:10  borland
# Added parallel computation for moments or twiss parameters with errors.
# Added display of beta and eta beats.
#
# Revision 1.70  2011/05/26 17:17:50  borland
# Fixed some display bugs.
#
# Revision 1.69  2011/05/26 17:05:38  borland
# Added option to use multiple cores for DA with errors jobs.
#
# Revision 1.68  2011/04/06 15:16:49  borland
# Fixed plotting problem for FMA.
#
# Revision 1.67  2011/04/06 13:38:24  borland
# Fixed bug in FMA for x/y and delta.
#
# Revision 1.66  2011/04/06 02:35:38  borland
# Added FMA for x/y vs delta with errors.
#
# Revision 1.65  2011/03/22 16:48:21  borland
# Added ability to make EPS files for FMA.
#
# Revision 1.64  2010/10/19 02:36:17  borland
# Fixed problem in last version.
#
# Revision 1.63  2010/10/19 00:08:12  borland
# Better FMA-with-errors analysis, including use of Pelegant.
#
# Revision 1.62  2010/07/08 21:27:42  borland
# Added "first" qualifier -omnipresent option for resonances on FMA diffusion and
# tune maps.  Also, the order of the resonances is set by the parameter in the
# dialog box.
#
# Revision 1.61  2010/04/08 22:28:23  borland
# Added ability to run kick aperture with multiple processors per job.
# Fixed problems with postprocessing.
#
# Revision 1.60  2010/04/04 02:47:05  borland
# Fixed bug in last chagne.
#
# Revision 1.59  2010/04/04 02:44:22  borland
# Fixed problem with multpage param file in kick aperture setup.
#
# Revision 1.58  2010/04/04 02:43:46  borland
# Fixed problem with multipage twiss files in kick aperture setup.
#
# Revision 1.57  2010/04/04 02:35:56  borland
# Fixed a incorrect variable name.
#
# Revision 1.56  2010/04/04 00:11:58  borland
# Added KickAperture computation.
#
# Revision 1.55  2010/01/06 18:29:04  borland
# Postprocessing added for additional files for momentum aperture.
#
# Revision 1.54  2009/10/09 15:25:56  borland
# Added aperture file for DA w/errors.
#
# Revision 1.53  2009/03/10 19:52:13  borland
# Added optional driving term computation.
#
# Revision 1.52  2009/03/06 22:45:19  borland
# Added option for input of errors from a parameter file.
#
# Revision 1.51  2009/03/05 23:24:13  borland
# Fixed some problems with display of moments data.
#
# Revision 1.50  2009/03/04 03:19:30  borland
# Added option for parameter file with errors.
#
# Revision 1.49  2009/03/03 18:52:26  borland
# Added moments computation for elegantRingAnalysis.
#
# Revision 1.48  2009/03/03 14:52:21  borland
# Added -integer option to several lsort commands to get correct processing
# of multi-step runs with Step>9.
#
# Revision 1.47  2009/02/27 19:37:43  borland
# Added plotting of the diffusion.
#
# Revision 1.46  2009/01/30 17:36:25  borland
# Fixed typo.
#
# Revision 1.45  2009/01/30 00:16:57  borland
# Changes for elegantRingAnalysis:
# 1. Use DynamicApertureErrorsTemplate.ele if no template is named.
# 2. Check for existence of parameter files.
#
# Revision 1.44  2008/09/16 13:15:29  borland
# Added filter on tune range for FMA plots.
#
# Revision 1.43  2008/08/26 18:26:09  borland
# Added element type pattern for momentum aperture determination.
#
# Revision 1.42  2008/08/21 22:02:07  borland
# Fixed numerical values on horizontal axis for tune vs amplitude plots
# in phase space tab.
#
# Revision 1.41  2008/07/17 21:56:54  borland
# Now makes log files when not using queue.
#
# Revision 1.40  2008/06/10 20:00:34  borland
# Shows all normal resonances for resonance finding.
#
# Revision 1.39  2007/12/21 16:48:57  borland
# Fixed a minor typo.
#
# Revision 1.38  2007/12/21 16:46:53  borland
# Added tracking and display of number of processing warnings.
#
# Fixed/enhanced plotting of DA with errors results.
#
# Revision 1.37  2007/11/16 19:12:03  borland
# For DynamicAperture with errors, added process-only feature.  Should be
# easy to add for others now, also.
#
# Revision 1.36  2007/11/16 13:52:25  borland
# Added template filename to entry array for dynamic aperture calculations,
# so the user can change it if desired.
#
# Revision 1.35  2007/10/18 17:45:37  borland
# Fixed further problems with DA when there are no errors.
#
# Revision 1.34  2007/10/18 17:29:05  borland
# Does single DA run if errors are turned off.
# Added some -nowarning statements for FineDA processing.
#
# Revision 1.33  2007/03/29 21:15:17  borland
# Added -nowarning to instance of sddsprocess.
#
# Revision 1.32  2007/03/05 15:26:03  borland
# Full filename is now on all plots.
#
# Revision 1.31  2007/03/03 23:01:16  borland
# Fixed some postprocessing problems with last change.
#
# Revision 1.30  2007/03/03 03:03:53  borland
# Added check during merging that all expected files exist.
# Added check to processing script for OffMomentumTuneTracking to ensure valid
# data for each value of delta; deleted duplicate processing script.
#
# Revision 1.29  2007/01/24 19:07:00  emery
# Indented code.
#
# Revision 1.28  2006/11/16 00:35:15  borland
# Fixed random number seed substitution problem for DA+Errors runs.
#
# Revision 1.27  2006/09/08 14:13:15  shang
# fixed the bug that *.done file was deleted after APSExecLog, moved the delete statement to before submitting or run elegant jobs.
#
# Revision 1.26  2006/08/22 20:03:48  borland
# Changed numberOfseeds to numberOfSeeds.
#
# Revision 1.25  2006/08/02 22:33:07  shang
# included errors into FMA, FMAdelat, basic computation and momentum aperture.
#
# Revision 1.24  2006/06/15 13:12:56  borland
# Fixed label on FMA delta plots.
#
# Revision 1.23  2006/06/06 02:28:34  borland
# Fixed erroneous variables in dynamic aperture with errors due to change
# to the line-based aperture finding method.
#
# Revision 1.22  2006/06/02 13:25:21  borland
# The dynamic aperture with errors calculation in elegantRingAnalysis now uses
# line search modes.
#
# Revision 1.21  2006/03/24 18:48:30  borland
# Added momentum aperture feature.
#
# Revision 1.20  2005/11/28 16:00:41  borland
# Uses sddsfindresonances instead of SDDS toolkit programs.
#
# Revision 1.19  2005/11/22 14:41:41  borland
# Combine closed orbit files for all runs (.clo extension).
#
# Revision 1.18  2005/10/19 19:39:40  borland
# Fixed bug with png file output for fma delta mode.
#
# Revision 1.17  2005/10/03 19:12:06  borland
# Fixed typo for FMA plotting of PNG files.
#
# Revision 1.16  2005/09/26 22:17:21  borland
# Resonance finding for FMA display now includes regular resonances up to
# sextupoles.
#
# Revision 1.15  2005/08/19 20:47:09  borland
# Fine DA plotting now uses the fill-in mode of symbol plotting.
#
# Revision 1.14  2005/08/19 20:15:11  borland
# Use symbol plotting in fill mode for FineDA and FMA plots.
#
# Revision 1.13  2005/08/12 09:51:10  emery
# Added braces around the statusCallback varirable in the after command of a postprocessing procedure
#
# Revision 1.12  2005/08/10 17:56:12  borland
# Added evaluation of microwave instability as part of Haissinski postprocessing.
#
# Revision 1.11  2005/07/25 21:00:26  borland
# Corrected "space charge tune spread" to "space charge tune shift"
#
# Revision 1.10  2005/07/23 20:39:33  borland
# Fixed bug in PNG plotting of (x, y) FMA data for y tune.
#
# Revision 1.9  2005/07/23 00:52:51  borland
# Further improvements to resonance interpolation.  Now double-interpolation
# works for delta as well.
#
# Revision 1.8  2005/07/23 00:37:19  borland
# Improved resonance plots by doing interpolation in both coordinates.
# VS: ----------------------------------------------------------------------
#
# Revision 1.7  2005/07/21 15:19:42  borland
# Added plotting of FMA with coordinates normalized to sigma.
#
# Revision 1.6  2005/07/15 22:13:19  borland
# Removed start qualifiers from sddsplot -split commands, to make more useful
# colorbars.
#
# Revision 1.5  2005/07/15 12:50:11  borland
# Changes to FMA postprocessing and plotting to handle sddsplot color bar bug.
#
# Revision 1.4  2005/07/14 17:57:25  borland
# Optionally show integer and half-integer resonances on FMA plots.
#
# Revision 1.3  2005/07/08 20:33:51  borland
# Removed some references to close orbit files, which are no longer being made.
#
# Revision 1.2  2005/07/08 20:25:25  borland
# Fixed a problem with FMA delta map.
#
# Revision 1.1  2005/07/06 13:03:06  borland
# Removed from elegantRingAnalysis; names changed to make them longer and
# more specific; by Shang.
#
# Hairong Shang, move the procedures in elegantRingAnalysis to libary

proc submitGridEngineJob {args} {
    set processorsPerJob 1
    set gridEngine no
    set inputFile ""
    APSStrictParseArguments {processorsPerJob gridEngine inputFile}
    
    if $processorsPerJob==1 {
	switch $gridEngine {
	    beamphysics-test {
		if [catch {exec ssub -queue beamphysics-test elegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	    hive {
		if [catch {exec ssub -hive 1 elegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	    default {
		if [catch {exec ssub elegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	}
    } else {
	switch $gridEngine {
	    beamphysics {
		if [catch {exec csub -mvapich2 $processorsPerJob Pelegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	    beamphysics-test {
		if [catch {exec csub -queue beamphysics-test -mvapich2 $processorsPerJob Pelegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	    hive {
		if [catch {exec csub -mvapich2-1.9 $processorsPerJob -hive 1 Pelegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	    default {
		if [catch {exec csub -mvapich2-1.9 $processorsPerJob Pelegant $inputFile} result] {
		    return -code error "$result"
		}
	    }
	}
    }
    return "$result"
}

proc APSTimeSinceLastChange {args} {
    set rootname ""
    APSStrictParseArguments {rootname}

    set mostRecent 0
    foreach filename [lsort [glob -nocomplain $rootname.*]] {
	if [expr [set mtime1 [file mtime $filename]]>$mostRecent] {
	    set mostRecent $mtime1
	}
    }
    return [expr [clock seconds]-$mostRecent]
}

proc APSElegantPerformRun {args} {
    set template ""
    set parameterFileList ""
    set forceOccurence 0
    set order 1
    set momentum 7e3
    set replacementList ""
    set originalList ""
    set tag ""
    set suffix ""
    set postProcessProc ""
    set mainDirectory ""
    set mainPrefix ""
    set matrixLatticeFile ""
    set kickLatticeFile ""
    set sourceDir ""
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine "no"
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    set processorsPerJob 1
    APSStrictParseArguments {template parameterFileList order momentum makePngFiles\
                               replacementList originalList tag suffix postProcessProc \
                               forceOccurence statusCallback\
                               mainDirectory mainPrefix matrixLatticeFile \
                               kickLatticeFile sourceDir \
                               matrixBeamline kickBeamline \
                               matrixOffsetElement kickOffsetElement gridEngine noPlots processorsPerJob}
    
    foreach item [list order momentum mainDirectory mainPrefix matrixLatticeFile kickLatticeFile parameterFileList matrixBeamline kickBeamline matrixOffsetElement kickOffsetElement forceOccurence suffix] {
        lappend originalList <$item>
        lappend replacementList [set $item]
    }
    global errors correction
    if $errors(on) {
        foreach name [array names errors] {
            if {$name=="on"} {
                continue
            }
            lappend originalList <$name>
            lappend replacementList $errors($name)
        }
        set tmpDir [file dir $template]
        if !$errors(maskTable) {
            lappend originalList <ERROR>
            lappend replacementList $tmpDir/ErrorsTemplate.ele
        }
        if [string length $errors(errorInputFile)] {
            lappend originalList <ERRORPARAM>
            lappend replacementList $tmpDir/ErrorParametersTemplate.ele
        }
    } else {
        lappend originalList <numberOfSeeds>
        lappend replacementList 1
        lappend originalList <seed>
        lappend replacementList $errors(seed)
    }
    foreach name [array names correction] {
	lappend originalList <$name>
	lappend replacementList $correction($name)
    }
    set runDone 0
    file delete -force $mainDirectory/${mainPrefix}${tag}${suffix}.done
    exec replaceText $template $mainDirectory/${mainPrefix}${tag}${suffix}.ele \
      -original=[join $originalList ,] -replacement=[join $replacementList ,]
    set rootname $mainDirectory/${mainPrefix}${tag}${suffix}
    set pid unknown
    file delete -force $rootname.done
    if [string compare $gridEngine "no"]!=0 {
	set result [submitGridEngineJob -gridEngine $gridEngine -processorsPerJob $processorsPerJob -inputFile $mainDirectory/${mainPrefix}${tag}${suffix}.ele]
        set jobID [lsearch $result "job"]
        if $jobID>=0 {
            set pid [lindex $result [expr $jobID + 1]]
        } 
        if [string length $statusCallback] {
            eval $statusCallback {"$result (pid=$pid)"}
        }
    } else {
        if [string length $statusCallback] {
            eval $statusCallback {"Running elegant..."}
        }
        APSExecLog [APSUniqueName .] -width 100 \
          -unixCommand "elegant $mainDirectory/${mainPrefix}${tag}${suffix}.ele" \
          -callback "set runDone 1" \
          -cancelCallback "set runDone 2" -abortCallback "set runDone 2"
        tkwait variable runDone
    }
    
    if [string length $postProcessProc] {
        APSElegantAddNewProcess -postProcessProc $postProcessProc -rootname $rootname -pidList $pid
        after 10000 "APSElegantPostProcessRun -rootname $rootname -postProcessProc \"$postProcessProc\" -pid \"$pid\" \
          -statusCallback \"$statusCallback\" -makePngFiles $makePngFiles -noPlots $noPlots"
    } 
}

proc APSElegantPostProcessRun {args} {
    set rootname ""
    set postProcessProc ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    set pid ""
    APSStrictParseArguments {rootname postProcessProc statusCallback makePngFiles noPlots pid}
    
    global apsAbortElegantRun apsElegantRunRootList apsElegantRunPIDList 
    
    if ![string length $postProcessProc] {
        return -code error "postProcessProc is not provided.!"
    }
    
    set timeout [expr [clock seconds] + 10]
    while {[clock seconds]<$timeout} {
        if ![file exists $rootname.done] {
            if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                return
            }
            if {[catch {exec qstat | grep $pid} result]} {
                if [file exist $rootname.done] {
                    break
                }
		set timeSinceChange [APSTimeSinceLastChange -rootname $rootname]
		if [expr $timeSinceChange<60] {
		    break
		}
                if [string length $statusCallback] {
                    eval $statusCallback  {"$rootname probably bombed before complete."}
                }
                if [APSYesNoPopUp "$rootname probably bombed, do you want to abort it?"] {
                    catch {exec qdel $pid}
                    if [string length $statusCallback] {
                        eval $statusCallback  {"$rootname was aborted"}
                    }
                    set apsAbortElegantRun($postProcessProc.$rootname) 1
                    return
                }
            } elseif [set apsAbortElegantRun($postProcessProc)] {
                if [catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} aborted] {
                    if [string length $statusCallback] {
                        eval $statusCallback  {"$aborted"}
                    }
                }
            }
            if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                return
            }
        } else {
            break
        }
        APSWaitWithUpdate -updateInterval 1 -waitSeconds 5
    }
    if ![file exist $rootname.done] {
        if [string length $statusCallback] {
            eval $statusCallback  {"waiting for [file root $rootname.done]"}
        }
        # statusCallback is usually two words (puts stderr). Therefore we
        # need to put braces around status callback because they get stripped off
        # at every "after" call.
        after 10000 "APSElegantPostProcessRun -rootname $rootname -makePngFiles $makePngFiles -pid \"$pid\" \
                       -postProcessProc \"$postProcessProc\" -statusCallback \"$statusCallback\" -noPlots $noPlots"
        return
    }
    
    if [string length $statusCallback] {
        eval $statusCallback {"Run $rootname completed"}
    }
    $postProcessProc -rootname $rootname -statusCallback $statusCallback -makePngFiles $makePngFiles \
      -noPlots $noPlots
}


proc APSElegantPerformRuns {args} {
    set template ""
    set parameterFileList ""
    set forceOccurence 0
    set order 1
    set momentum 7e3
    set replacementList ""
    set originalList ""
    set tag ""
    set variable ""
    set startValue 0
    set endValue 0
    set points 0
    set copyList ""
    set combineList ""
    set mergeList ""
    set firstOnlyList ""
    set suffix ""
    set postProcessProc ""
    set mainDirectory ""
    set mainPrefix ""
    set matrixLatticeFile ""
    set kickLatticeFile ""
    set sourceDir ""
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    set eleFileList ""
    set processOnly 0
    set processorsPerJob 1
    APSStrictParseArguments {template parameterFileList order momentum tag  \
                               variable startValue endValue  points copyList \
                               combineList mergeList firstOnlyList suffix forceOccurence \
                               replacementList originalList postProcessProc \
                               mainDirectory mainPrefix matrixLatticeFile \
                               kickLatticeFile sourceDir \
                               matrixBeamline kickBeamline matrixOffsetElement\
                               kickOffsetElement gridEngine \
                               statusCallback makePngFiles noPlots eleFileList \
                               processOnly processorsPerJob}
    
    foreach item [list order momentum mainDirectory mainPrefix matrixLatticeFile kickLatticeFile parameterFileList matrixBeamline kickBeamline matrixOffsetElement kickOffsetElement forceOccurence] {
        lappend originalList <$item>
        lappend replacementList [set $item]
    }
    global errors apsAbortElegantRun correction
    if $errors(on) {
        foreach name [array names errors] {
            if {$name=="on"} {
                continue
            }
            lappend originalList <$name>
            lappend replacementList $errors($name)
        }
        set tmpDir [file dir $template]
        if !$errors(maskTable) {
            lappend originalList <ERROR>
            lappend replacementList $tmpDir/ErrorsTemplate.ele
        }
    } else {
        lappend originalList <numberOfSeeds>
        lappend replacementList 1
        lappend originalList <seed>
        lappend replacementList $errors(seed)
    }
    foreach name [array names correction] {
	lappend originalList <$name>
	lappend replacementList $correction($name)
    }
    if {$points && [llength $eleFileList]} {
        return -code error "APSElegantPerformRuns: points=$points and eleFileList given"
    }
    if {$points>=1} {
        set varyMode 1
        set delta 0
        if $points>1 {
            set delta [expr ($endValue*1.0-$startValue)/($points-1.0)]
        }
        if [lsearch -exact $mergeList var]==-1 {
            lappend mergeList var
        }
    } else {
        set points [llength $eleFileList]
        set varyMode 0
    }
    set w [APSUniqueName .]
    set rootnameList ""
    set pidList ""
    set rootname0 $mainDirectory/${mainPrefix}${tag}${suffix}

    if !$processOnly {
        file delete -force $rootname0.done
    }

    for {set i 0} {$i<$points} {incr i} {
        set runDone 0
        if $varyMode {
            set value [expr $startValue + $i*$delta]
            set suffix0 ${suffix}-[format %03d $i]
            set rootname $mainDirectory/${mainPrefix}${tag}${suffix0}
            exec sddsmakedataset $rootname.var -column=$variable,type=double -data=$value
            # putting the variable first here is essential in case the variable is also
            # part of a previous substitution.
            if {$errors(on) && [string length $errors(errorInputFile)]} {
                if {[string match *DynamicApertureErrors* $tag] || [string match *KickAperture* $tag] || [string match *FrequencyMap* $tag] || \
			[string match *Moments* $tag] || [string match *Basic* $tag]} {
                    if $i==0 {
                        exec sddssplit $errors(errorInputFile) -rootname=$mainDirectory/${mainPrefix}${tag}${suffix}- -extension=erlIn -digits=3 -offset=1
                    }
                    set tmpDir [file dir $template]
                    exec replaceText $template $rootname.ele -verbose \
                      -original=<ERRORPARAM>,<$variable>,<errorInputFile>,[join $originalList ,],<suffix> \
                      -replacement=$tmpDir/ErrorParametersTemplate.ele,$value,$rootname.erlIn,[join $replacementList ,],$suffix0
                } else {
                    set tmpDir [file dir $template]
                    exec replaceText $template $rootname.ele \
                      -original=<ERRORPARAM>,<$variable>,<errorInputFile>,[join $originalList ,],<suffix> \
                      -replacement=$tmpDir/ErrorParametersTemplate.ele,$value,$errors(errorInputFile),[join $replacementList ,],$suffix0
                }
            } else {
                exec replaceText $template $rootname.ele \
                  -original=<$variable>,[join $originalList ,],<suffix> \
                  -replacement=$value,[join $replacementList ,],$suffix0
            }
        } else {
            set rootname [file rootname [lindex $eleFileList $i]]
        }
        set pid unknown
        if !$processOnly {
            file delete -force $rootname.done
            if [string compare "no" $gridEngine]!=0 {
                APSElegantAddNewProcess -postProcessProc $postProcessProc -rootname $rootname0 -pidList $pidList
                if [set apsAbortElegantRun($postProcessProc)] {
                    catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} result
                }

                if [set apsAbortElegantRun($postProcessProc.$rootname0)] {
                    return
                }
		set result [submitGridEngineJob -gridEngine $gridEngine -inputFile $rootname.ele -processorsPerJob $processorsPerJob]
		set jobID [lsearch $result "job"]
                if $jobID>=0 {
                    set pid [lindex $result [expr $jobID + 1]]
                }
                if [string length $statusCallback] {
                    eval $statusCallback {"$rootname run $i submitted: $result."}
                }
            } else {
                if [string length $statusCallback] {
                    eval $statusCallback {"Running elegant $rootname run $i..."}
                }
                APSExecLog $w -width 100 \
                  -unixCommand "elegant $rootname.ele | tee $rootname.ele.log" \
                  -callback "set runDone 1" \
                  -cancelCallback "set runDone 2" -abortCallback "set runDone 2"
                tkwait variable runDone
                set runDone [file exists $rootname.done]
                if !$runDone {
                    if [string length $statusCallback] {
                        eval $statusCallback {"Run failed: $rootname.done not found."}
                    }
                    return 0
                }
                if [string length $statusCallback] {
                    eval $statusCallback {"$rootname Run $i finished."}
                }
            }
        }
        lappend pidList $pid
        lappend rootnameList $rootname
    }
    set rootname $mainDirectory/${mainPrefix}${tag}${suffix}
    if [string length $postProcessProc] {
        if !$processOnly {
            APSElegantAddNewProcess -postProcessProc $postProcessProc -rootname $rootname -pidList $pidList
	    after 10000 "APSElegantPostProcessRuns -rootname $rootname -postProcessProc \"$postProcessProc\" \
          -runNameList \"$rootnameList\" -statusCallback \"$statusCallback\" -pidList \"$pidList\" \
          -copyList \"$copyList\" -mergeList \"$mergeList\" -firstOnlyList \"$firstOnlyList\" \
          -combineList \"$combineList\" -makePngFiles $makePngFiles -noPlots $noPlots"
	} else {
	    APSElegantPostProcessRuns -rootname $rootname -postProcessProc "$postProcessProc" \
		-runNameList "$rootnameList" -statusCallback "$statusCallback" -pidList "$pidList" \
		-copyList "$copyList" -mergeList "$mergeList" -firstOnlyList "$firstOnlyList" \
		-combineList "$combineList" -makePngFiles $makePngFiles -noPlots $noPlots
	}
    }
    return 1
}

proc APSElegantAffix {args} {
    set prefix ""
    set itemList ""
    set suffix ""
    if [APSStrictParseArguments {prefix itemList suffix}] {
        return -code error "APSElegantAffix: Invalid arguments"
    }
    set returnList ""
    foreach item $itemList {
        lappend returnList ${prefix}${item}${suffix}
    }
    return $returnList
}

proc APSElegantPostProcessRuns {args} {
    set rootname ""
    set runNameList ""
    set pidList ""
    set copyList ""
    set mergeList ""
    set combineList ""
    set firstOnlyList ""
    set postProcessProc ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    set excludeList ""
    APSStrictParseArguments {rootname runNameList copyList mergeList pidList excludeList \
                               combineList postProcessProc makePngFiles firstOnlyList \
                               statusCallback noPlots}
    
    global apsAbortElegantRun apsElegantRunRootList apsElegantRunPIDList
    set warningCount 0

    if ![string length $postProcessProc] {
        return -code error "postProcessProc is not provided."
    }
    catch {
        if [set apsAbortElegantRun($postProcessProc.$rootname)] {
            return
        }
    }
    set doneList [APSElegantAffix -itemList $runNameList -suffix .done]
    set numToDo [llength $doneList]
    set timeout [expr [clock seconds] + 10]
    
    while {[clock seconds]<$timeout} {
        catch {
            if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                return
            }
        }
        set numDone 0
        foreach done $doneList pid $pidList {
            update
            catch {
                # Use catch in case the abort information doesn't exist (post-process only mode)
                if [set apsAbortElegantRun($postProcessProc)] {
                    if [catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} aborted] {
                        if [string length $statusCallback] {
                            eval $statusCallback {"$aborted."}
                        }
                    }
                }
                if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                    return
                }
            }
            if [file exists $done] {
                incr numDone
            } elseif {[string compare $pid unknown]!=0} {
                if [catch {exec qstat | grep $pid} result] {
                    incr numDone
                    if ![file exist $done] {
                        if {[lsearch $excludeList $done]<0} {
			    set timeSinceChange [APSTimeSinceLastChange -rootname [file root $done]]
			    if [expr $timeSinceChange>60] {
				if [string length $statusCallback] {
				    eval $statusCallback  {"[file root $done] (pid=$pid) probably completed with error ($timeSinceChange s)."}
				}
				if [APSYesNoPopUp "[file root $done] (pid: $pid) probably completed with error, do you want to abort $rootname?"] {
				    catch {eval exec cdel $pidList} result
				    if [string length $statusCallback] {
					eval $statusCallback  {"$rootname was aborted: $result"}
				    }
				    set apsAbortElegantRun($postProcessProc.$rootname) 1
				    return
				}
				lappend excludeList $done
			    }
			}
                    }
                }
            }
        }
        if [string length $statusCallback] {
            eval $statusCallback {"$numDone/$numToDo done for $rootname"}
        }
        if {$numDone==$numToDo} {
            break
        } else {
            catch {
                if [set apsAbortElegantRun($postProcessProc)] {
                    if [catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} aborted] {
                        if [string length $statusCallback] {
                            eval $statusCallback {"$aborted."}
                        }
                    }
                }
                if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                    return
                }
            }
        }
        APSWaitWithUpdate -updateInterval 1 -waitSeconds 5
    }
    if {$numDone!=$numToDo} {
        if [string length $statusCallback] {
            eval $statusCallback {"$numDone/$numToDo done for $rootname"}
        }
        after 1000 \
          "APSElegantPostProcessRuns -rootname $rootname -postProcessProc $postProcessProc -pidList \"$pidList\"  -excludeList \"$excludeList\" \
           -runNameList \"$runNameList\" -copyList \"$copyList\" -mergeList \"$mergeList\" -combineList \"$combineList\" -statusCallback \"$statusCallback\" -makePngFiles $makePngFiles -noPlots $noPlots"
        return
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Postprocessing for ${rootname}"}
    }
    set processedList ""
    lappend copyList done
    foreach item $copyList {
        if [lsearch -exact $processedList $item]!=-1 continue
        
        if [string length $statusCallback] {
            eval $statusCallback  {"Copying [lindex $runNameList 0].$item to $rootname.$item"}
        }
        exec cp [lindex $runNameList 0].$item $rootname.$item
        eval file delete -force [APSElegantAffix -itemList $runNameList -suffix .$item]
        lappend processedList $item
    }
    
    foreach item $mergeList {
        if [lsearch -exact $processedList $item]!=-1 continue
        if [catch {exec sddscheck [lindex $runNameList 0].$item} result] {
            if [string compare $item var]==0 continue
            return -code error "$result"
        }
        set fileList [APSElegantAffix -itemList $runNameList -suffix .$item]
        foreach filename $fileList {
            if ![file exists $filename] {
                return -code error "not found: $filename"
            }
        }
        if [string length $statusCallback] {
            eval $statusCallback {"Merging [llength $runNameList] files into $rootname.$item"}
        }
        if [string compare $result ok]==0 {
            if [catch {eval exec sddscombine [APSElegantAffix -itemList $runNameList -suffix .$item] \
                         -merge -overwrite $rootname.$item} result] {
                eval $statusCallback {"Warning: $result"}
                incr warningCount
            }
        } else {
            if [catch {eval exec cat [APSElegantAffix -itemList $runNameList -suffix .$item] \
                         > $rootname.$item} result] {
                if [string compare $item var]==0 continue
                eval $statusCallback {"Warning: $result"}
                incr warningCount
            }
        }
        lappend processedList $item
        eval file delete -force [APSElegantAffix -itemList $runNameList -suffix .$item]
    }

    foreach item $combineList {
        if [lsearch -exact $processedList $item]!=-1 continue
        if [string length $statusCallback] {
            eval $statusCallback {"Combining [llength $runNameList] files into $rootname.$item"}
        }
        if [catch {exec sddscheck [lindex $runNameList 0].$item} result] {
            return -code error "$result"
        }
        if [string compare $result ok]==0 {
            if [catch {eval exec sddscombine [APSElegantAffix -itemList $runNameList -suffix .$item] \
                         -overwrite $rootname.$item} result] {
                eval $statusCallback {"Warning: $result"}
                incr warningCount
            }
        } else {
            if [catch {eval exec cat [APSElegantAffix -itemList $runNameList -suffix .$item] \
                         > $rootname.$item} result] {
                eval $statusCallback {"Warning: $result"}
                incr warningCount
            }
        }
        lappend processedList $item
        eval file delete -force [APSElegantAffix -itemList $runNameList -suffix .$item]
    }

    foreach item $firstOnlyList {
        if [lsearch -exact $processedList $item]!=-1 continue
        if [string length $statusCallback] {
            eval $statusCallback {"Copying first file into $rootname.$item"}
        }
        if [catch {exec sddscheck [lindex $runNameList 0].$item} result] {
            return -code error "$result"
        }
	if [catch {file rename -force [lindex $runNameList 0].$item $rootname.$item} result] {
	    eval $statusCallback {"Warning: $result"}
	    incr warningCount
	}
        lappend processedList $item
        catch {eval file delete -force [APSElegantAffix -itemList $runNameList -suffix .$item]}
    }

    # delete temporary files
    foreach item [list erlIn] {
	eval file delete [APSElegantAffix -itemList $runNameList -suffix .$item]
    }

    $postProcessProc -rootname $rootname -statusCallback $statusCallback \
      -makePngFiles $makePngFiles -noPlots $noPlots
    if [string length $statusCallback] {
        if !$warningCount {
            eval $statusCallback {"Done postprocessing for $rootname"}
        } else {
            eval $statusCallback {"Done postprocessing for $rootname, with $warningCount warnings."}
        }
    }
}

proc APSElegantSaveJobConfiguration {args} {
    set filename ""
    set statusCallback ""
    set momentum ""
    set matrixLatticeFile ""
    set matrixBeamline ""
    set matrixOffsetElement ""
    set kickLatticeFile ""
    set kickBeamline  ""
    set kickOffsetElement ""
    set forceOccurence 0
    set mainDirectory ""
    set mainPrefix ""
    set gridEngine no
    set makePngFiles 0
    APSStrictParseArguments {filename statusCallback momentum matrixLatticeFile matrixBeamline \
                               matrixOffsetElement kickLatticeFile kickBeamline  kickOffsetElement \
                               forceOccurence mainDirectory mainPrefix gridEngine makePngFiles}
    global elegantSaveVarList elegantGlobalArrays
    eval global $elegantGlobalArrays
    set fd [open $filename w]
    
    foreach variable $elegantSaveVarList {
        set names [array names $variable]
        if ![llength $names] {
            set value [set $variable]
            if [string length $value] {
                puts $fd "set $variable $value"
            } else {
                puts $fd "set $variable \"\""
            }
        } else {
            foreach name $names {
                set value [set $variable\($name\)]
                if [string length $value] {
                    puts $fd "set $variable\($name\) \{$value\}"
                } else {
                    puts $fd "set $variable\($name\) \"\""
                }
            }
        }
    }
    close $fd
    if [string length $statusCallback] {
        eval $statusCallback {"Configuration $filename written."}
    }
}

proc APSElegantGetParameterFileList {args} {
    set parameterFileList ""
    global mainParameterFile mainDirectory
    foreach item [lsort [array names mainParameterFile]] {
        if ![file exists $mainParameterFile($item)] {
            if ![file exists $mainDirectory/$mainParameterFile($item)] {
                return -code error "Parameter file not found: $mainParameterFile($item)"
            }
        }
        if [string length $mainParameterFile($item)] {
            append parameterFileList "$mainParameterFile($item) "
        }
    }
    return $parameterFileList
}

proc APSElegantBasicComputations {args} {
    set sourceDir ""
    set momentum 7e3
    set matrixLatticeFile ""
    set matrixBeamline ""
    set matrixOffsetElement ""
    set kickLatticeFile ""
    set kickBeamline  ""
    set kickOffsetElement ""
    set forceOccurence 0
    set mainDirectory ""
    set mainPrefix ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback "" 
    set noPlots 0
    APSStrictParseArguments {sourceDir statusCallback momentum matrixLatticeFile matrixBeamline \
                               matrixOffsetElement kickLatticeFile kickBeamline  kickOffsetElement \
                               forceOccurence mainDirectory mainPrefix gridEngine makePngFiles noPlots}
    # global sourceDir  forceOccurence
    # global basicComputations momentum matrixLatticeFile mainParameterFile mainDirectory mainPrefix matrixBeamline
    global basicComputations errors
    set tag Basic
    set rootname $mainDirectory/${mainPrefix}${tag}$basicComputations(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    foreach name [array names basicComputations] {
        set $name $basicComputations($name)
    }
    set order 1
    if $doChromaticity {
        set order 2
    }
    if {$doHigherOrderChromaticity || $doChromaticTuneSpread || $doDrivingTerms} {
        set order 3
    }
    if {$doChromaticTuneSpread && [expr $chromaticTuneSpreadMomentumSpread<=0]} {
        return -code error "momentum spread must be positive for chromatic tune spread computations"        
    }
    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names basicComputations] {
        lappend origList <$item>
        lappend replList [set $item]
    }
    set variable seed
    set firstSeed $errors(seed)
    set lastSeed [expr $firstSeed+10*($errors(numberOfSeeds)-1)]
    set seeds $errors(numberOfSeeds)
    if !$errors(on) {
        set seeds 1
    }
    if $seeds>1 {
	APSElegantPerformRuns -template $sourceDir/BasicTemplate.ele \
	    -parameterFileList $parameterFileList \
	    -forceOccurence $forceOccurence \
	    -variable $variable \
	    -startValue $firstSeed -endValue $lastSeed -points $seeds \
	    -copyList [list done mag] \
	    -combineList [list erl twi w1 fin clo orb param cor scor flr]  \
	    -mergeList [list ele ele.log] \
	    -tag $tag -order $order -momentum $momentum -suffix $basicComputations(userSuffix) \
	    -originalList $origList -replacementList $replList \
	    -suffix $basicComputations(userSuffix) -postProcessProc APSElegantBasicComputationsPP \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
    } else {
	APSElegantPerformRun -template $sourceDir/BasicTemplate.ele \
	    -parameterFileList $parameterFileList \
	    -forceOccurence $forceOccurence \
	    -tag $tag -order $order -momentum $momentum -suffix $basicComputations(userSuffix) \
	    -originalList $origList -replacementList $replList \
	    -suffix $basicComputations(userSuffix) -postProcessProc APSElegantBasicComputationsPP \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
    }
}

proc APSElegantBasicComputationsPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    
    source $rootname.runCfg
    
    foreach name [array names basicComputations] {
        set $name $basicComputations($name)
    }
    set order 1
    if $doChromaticity {
        set order 2
    }
    if {$doHigherOrderChromaticity || $doChromaticTuneSpread} {
        set order 3
    }
    
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.p1
    if !$errors(on) {
	if [expr $finalSTwiss>0] {
	    exec plotTwiss -fileRoot ${rootname} -filter=column,s,0,$finalSTwiss &
	} else {
	    exec plotTwiss -fileRoot ${rootname} &
	}
    } else {
	exec sddsprocess $rootname.twi -pipe=out \
	    "-test=param,nux isnan nuy isnan || !" \
	    | sddsenvelope -pipe=in $rootname.twi.ave -copy=s -mean=beta?,etax 
	exec sddsprocess $rootname.twi -pipe=out \
	    "-test=param,nux isnan nuy isnan || !" \
	    | sddsxref -pipe $rootname.twi.ave -take=* -reuse=page \
	    | sddsprocess -pipe=in $rootname.beat \
	    "-define=col,dbetaxFrac,betax betaxMean - betaxMean / 100 *,units=%" \
	    "-define=col,dbetayFrac,betay betayMean - betayMean / 100 *,units=%" \
	    -process=etaxMean,largest,%sLargest \
	    "-define=col,detaxFrac,etax etaxMean - etaxMeanLargest abs 1e-16 + / 100 *,units=%" \
	    -process=dbetaxFrac,rms,%sRms \
	    -process=dbetayFrac,rms,%sRms \
	    -process=detaxFrac,rms,%sRms \
	    -process=dbetaxFrac,spread,%sSpread \
	    -process=dbetayFrac,spread,%sSpread \
	    -process=detaxFrac,spread,%sSpread \
	    "-print=parameter,betaxLabel,%.2f%% pk-to-pk    %.2f%% rms,dbetaxFracSpread,dbetaxFracRms" \
	    "-print=parameter,etaxLabel,%.2f%% pk-to-pk    %.2f%% rms,detaxFracSpread,detaxFracRms" \
	    "-print=parameter,betayLabel,%.2f%% pk-to-pk    %.2f%% rms,dbetayFracSpread,dbetayFracRms" 

	exec sddsplot -layout=1,3 -split=page -groupby=page,names -separate=names $rootname.beat \
	    -column=s,dbetaxFrac -title=@betaxLabel \
	    -column=s,dbetayFrac -title=@betayLabel \
	    -column=s,detaxFrac -title=@etaxLabel  &

	exec sddscollapse $rootname.beat -pipe=out \
	    | sddsprocess -pipe \
	    -process=*Rms,ave,%sAve \
	    "-print=parameter,betaxStatsLabel,ave. betax beat: %.2f%%,dbetaxFracRmsAve" \
	    "-print=parameter,etaxStatsLabel,ave. etax beat: %.2f%%,detaxFracRmsAve" \
	    "-print=parameter,betayStatsLabel,ave. betay beat: %.2f%%,dbetayFracRmsAve" \
	    | sddsmultihist -pipe=in $rootname.beatHis -separate -autobins=target=10,min=10,max=50 \
	    -column=dbetaxFracRms,dbetayFracRms,detaxFracRms
	exec sddsplot -sep \
	    -column=dbetaxFracRms,dbetaxFracRmsFrequency $rootname.beatHis -topline=@betaxStatsLabel \
	    -column=dbetayFracRms,dbetayFracRmsFrequency $rootname.beatHis -topline=@betayStatsLabel \
	    -column=detaxFracRms,detaxFracRmsFrequency $rootname.beatHis -topline=@etaxStatsLabel &
    }
    set parameterList -parameter=nu?,end 
    if $doChromaticity {
        lappend parameterList -parameter=dnu?/dp,end 
    }
    if $doHigherOrderChromaticity {
        lappend parameterList -parameter=dnu?/dp2,end -parameter=dnu?/dp3,end 
    }
    if $doChromaticTuneSpread {
        lappend parameterList -parameter=dnu?Chrom,end
    }
    if $doDrivingTerms {
        lappend parameterList -parameter=h?????,end
    }
    if $basicComputations(doRadiationIntegrals) {
        lappend parameterList -parameter=ex0 -parameter=Sdelta0 -parameter=U0,end
        lappend parameterList -parameter=J? -parameter=Jdelta,end
        lappend parameterList -parameter=tau? -parameter=taudelta,end
        lappend parameterList -parameter=I1 -parameter=I2 -parameter=I3,end
        lappend parameterList -parameter=I4 -parameter=I5,end
    }
    eval exec sddsprocess ${rootname}.twi -pipe=out \
      {"-define=parameter,dnuxChrom,nuxChromUpper nuxChromLower -"} \
      {"-define=parameter,dnuyChrom,nuyChromUpper nuyChromLower -"} \
      | sddsprintout -pipe=in $tmpRoot.p1 -title=${rootname}.twi \
      $parameterList -parameter=beta?Max,end -parameter=beta?Min,end \
      -parameter=etaxM*,end 
    
    APSFileDisplayWindow [APSUniqueName .] -fileName $tmpRoot.p1 -deleteOnClose 1 \
      -height [llength $parameterList] -width 120 -height 10
    
}

proc APSElegantMomentsComputations {args} {
    set sourceDir ""
    set momentum 7e3
    set matrixLatticeFile ""
    set matrixBeamline ""
    set matrixOffsetElement ""
    set kickLatticeFile ""
    set kickBeamline  ""
    set kickOffsetElement ""
    set forceOccurence 0
    set mainDirectory ""
    set mainPrefix ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback "" 
    set noPlots 0
    APSStrictParseArguments {sourceDir statusCallback momentum matrixLatticeFile matrixBeamline \
                               matrixOffsetElement kickLatticeFile kickBeamline  kickOffsetElement \
                               forceOccurence mainDirectory mainPrefix gridEngine makePngFiles noPlots}
    global momentsComputations errors
    foreach item [array names momentsComputations] {
        set $item $momentsComputations($item)
    }

    set tag Moments
    set rootname $mainDirectory/${mainPrefix}${tag}$momentsComputations(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names momentsComputations] {
        lappend origList <$item>
        lappend replList [set momentsComputations($item)]
    }
    set variable seed
    set firstSeed $errors(seed)
    set lastSeed [expr $firstSeed+10*($errors(numberOfSeeds)-1)]
    set seeds $errors(numberOfSeeds)
    if !$errors(on) {
        set seeds 1
    }
    if $seeds>1 {
	APSElegantPerformRuns -template $sourceDir/MomentsTemplate.ele \
	    -parameterFileList $parameterFileList \
	    -forceOccurence $forceOccurence \
	    -variable $variable \
	    -startValue $firstSeed -endValue $lastSeed -points $seeds \
	    -copyList [list done mag] \
	    -combineList [list mom erl twi w1 fin clo orb param cor scor flr]  \
	    -mergeList [list ele ele.log] \
	    -tag $tag -order $order -momentum $momentum -suffix $momentsComputations(userSuffix) \
	    -originalList $origList -replacementList $replList \
	    -suffix $momentsComputations(userSuffix) -postProcessProc APSElegantMomentsComputationsPP \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots 
    } else {
	APSElegantPerformRun -template $sourceDir/MomentsTemplate.ele \
	    -parameterFileList $parameterFileList \
	    -forceOccurence $forceOccurence \
	    -tag $tag -order $order -momentum $momentum -suffix $momentsComputations(userSuffix) \
	    -originalList $origList -replacementList $replList \
	    -suffix $momentsComputations(userSuffix) -postProcessProc APSElegantMomentsComputationsPP \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots 
    }
}

proc APSElegantMomentsComputationsPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    
    source $rootname.runCfg
    foreach item [array names momentsComputations] {
        set $item $momentsComputations($item)
    }

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.mom $tmpRoot.momh

    set parameter(histograms) 1
    set parameter(sPlots) 0
    set steps [exec sdds2stream -npages=bare ${rootname}.mom]
    if $steps<=5 {
        set parameter(sPlots) 1
        set parameter(histograms) 0
    }
    set parameter(namePattern) $momentsComputations(sourcePointNamePattern)
    set parameter(typePattern) $momentsComputations(sourcePointTypePattern)

    set valueList [APSQueryValuesDialog \
                     -nameList [list "Type pattern" "Name pattern" "Make PNG" "s-plots" "Histograms"] \
                     -defaultList [list $parameter(typePattern) $parameter(namePattern) 0 $parameter(sPlots) $parameter(histograms)] \
                     -elementList [list typePattern namePattern makePng sPlots histograms] \
                     -typeList [list none none yesNo yesNo yesNo]]
    array set parameter $valueList
    set title "Moments results for $rootname" 

    if $parameter(sPlots) {
        exec sddsplot -layout=1,2 "-topline=$title" \
	    -column=s,ex -col=s,ey -groupby=names -separate=names -split=page $rootname.mom -graph=sym,vary=subtype -order=spect \
	    -match=column,ElementName=$parameter(namePattern) \
	    -match=column,ElementType=$parameter(typePattern) &
	if $parameter(makePng) {
	    exec sddsplot -device=lpng,onwhite -output=$rootname-sPlot.png -layout=1,2 "-topline=$title" \
		-column=s,ex -col=s,ey -groupby=names -separate=names -split=page $rootname.mom -graph=sym,vary=subtype -order=spect \
		-match=column,ElementName=$parameter(namePattern) \
		-match=column,ElementType=$parameter(typePattern) &
        }
    }
    
    if $parameter(histograms) {
        # Show statistics of results
        foreach item {ex ey ez s1 s2 s3 s4 s5 s6 exbeta eybeta} {
            lappend procOptionList "-print=parameter,${item}Label,Ave/Median/StDev: %.3g/%.3g/%.3g %s,${item}Ave,${item}Median,${item}StDev,${item}Ave.units"
            lappend plotOptionList -column=$item,${item}Frequency -title=@${item}Label
        }
        eval exec sddsprocess $rootname.mom -pipe=out \
          -match=column,ElementName=$parameter(namePattern) \
          -match=column,ElementType=$parameter(typePattern) \
          | sddscombine -merge -pipe \
          | sddsprocess -pipe \
          -process=e?,ave,%sAve -process=s?,ave,%sAve -process=e?beta,ave,%sAve \
          -process=e?,median,%sMedian -process=s?,median,%sMedian -process=e?beta,median,%sMedian \
          -process=e?,stand,%sStDev -process=s?,stand,%sStDev -process=e?beta,stand,%sStDev \
          | sddsprocess -pipe \
          $procOptionList \
          | sddsmultihist -pipe=in $rootname.momh -autobins=target=10,minimum=5,maximum=60 \
          -columns=e?,s?,e?beta -separate -sides
        eval exec sddsplot "{-topline=$title}" $rootname.momh -separate $plotOptionList &
        if $parameter(makePng) {
            eval exec sddsplot -device=lpng,onwhite,template=$rootname-hist-%03ld.png \
              "{-topline=$title}" $rootname.momh -separate $plotOptionList &
        }
    }
}

proc APSElegantScanCollectiveEffectsProgram {args} {
    set template ""
    set extension ""
    set dataFile ""
    set type ""
    set mainDirectory ""
    set mainPrefix ""
    set gridEngine no
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {template extension type dataFile \
                               mainDirectory mainPrefix gridEngine \
                               statusCallback noPlots}
    global collectiveEffects scanRunDone apsAbortElegantRun apsElegantRunRootList apsElegantRunPIDList
    
    set isIBS [expr ![string compare $type IBS]]
    set isSCTS [expr ![string compare $type SCTS]]
    if {($isIBS || $isSCTS) && ![string length $dataFile]} {
        return -code error "Need data file for $type"
    }
    set postProcessProc $type
    if {$type=="SCTS"} {
        set postProcessProc SRTuneShift
    }
    foreach item {rfHarmonic charge rfVoltage emittanceRatio BBImpedance bunchLength VHarmonic harmonicRatio} {
        set ${item}List ""
    }
    if {!($isIBS || $isSCTS)} {
        if [catch {APSElegantDetermineScanVariableCollectiveEffects -mainDirectory $mainDirectory \
                     -mainPrefix $mainPrefix} scanVariable] {
            return -code error "$scanVariable"
        }
        set points $collectiveEffects(scanPoints)
        if [string length $statusCallback] {
            eval $statusCallback {"Will scan $scanVariable over $points values"}
        }
        for {set step 0} {$step<$points} {incr step} {
            foreach item {rfHarmonic superPeriods harmonicRatio} {
                set value [set collectiveEffects($item)]
                lappend ${item}List $value
            }
            foreach item {charge rfVoltage emittanceRatio BBImpedance VHarmonic} {
                set value0 [set collectiveEffects(${item}0)]
                set value1 [set collectiveEffects(${item}1)]
                lappend ${item}List [expr $value0+(1.0*$value1-$value0)/($points-1.0)*$step]
            }
            lappend rmsBunchLengthList 0
        }
    } else {
        set points [exec sdds2stream -rows=bare $dataFile]
        if [string length $statusCallback] {
            eval $statusCallback {"$points evaluation points in $dataFile"}
        }
        set scanVariable [exec sdds2stream $dataFile -column=scanVariable -pipe=out | tail -1]
        foreach item {charge rmsBunchLength rfVoltage emittanceRatio superPeriods rfHarmonic BBImpedance VHarmonic harmonicRatio} {
            set ${item}List [APSGetSDDSColumn -fileName $dataFile -column $item]
        }
    }
    set rootname $mainDirectory/${mainPrefix}$collectiveEffects(prefix)
    file delete -force $rootname.done
    set outputList ""
    set pidList ""
    for {set step 0} {$step<$points} {incr step} {
        set output $mainDirectory/${mainPrefix}$collectiveEffects(prefix)-[format %03d $step].$extension
        if [string length $statusCallback] {
            eval $statusCallback {"Preparing step $step, output $output"}
        }
        set command [eval os editstring %+<output>+$output+ $template]
        foreach item {charge rmsBunchLength rfVoltage emittanceRatio superPeriods rfHarmonic BBImpedance VHarmonic harmonicRatio} {
            set value [lindex [set ${item}List] $step]
            if [string match "*nan*" $value]==1 {
                return -code error "$item has value NaN"
            }
            set command [eval os editstring %/<$item>/$value/ $command]
            switch $item {
                charge {
                    set command [eval os editstring %/<charge_nC>/[expr $value*1e9]/ $command]
                }
                rfVoltage {
                    set command [eval os editstring %/<rfVoltage_MV>/[expr $value/1e6]/ $command]
                }
                rmsBunchLength {
                    set command [eval os editstring %/<rmsBunchLength_mm>/[expr $value*1e3]/ $command]
                }
            }
        }
        if [string length $statusCallback] {
            eval $statusCallback {"Command is $command"}
        }
        set pid unknown
        if [string compare $gridEngine "no"]!=0 {
            APSElegantAddNewProcess -postProcessProc $postProcessProc -rootname $rootname -pidList $pidList
            if [set apsAbortElegantRun($postProcessProc)] {
                catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} result
            }
            if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                return
            }
            set scriptName $output.sh
            set fd [open $scriptName w]
            puts $fd "$command"
            puts $fd "echo done > $output.done"
            close $fd
            file delete -force $output.done
            file attributes $output.sh -permission +x
            catch {exec csub $output.sh} result
            if [regexp {\((.*)} $result a b c] {
                regexp {(.*)\)} $b c pid d
            }
            if [string length $statusCallback] {
                eval $statusCallback {"$result"}
            }
            lappend scriptList $output.sh
        } else {
            APSExecLog .scan -unixCommand "$command" -width 100 -height 30 \
              -callback "set scanRunDone 1" -cancelCallback "set scanRunDone 2" \
              -abortCallback "set scanRunDone 2"
            tkwait variable scanRunDone
            if $scanRunDone==2 {
                break
            }
        }
        lappend doneList $output.done
        lappend outputList $output
        lappend pidList $pid
    }
    APSElegantAddNewProcess -postProcessProc $postProcessProc -rootname $rootname -pidList $pidList
    
    if [string compare $gridEngine "no"]!=0 {
        if [set apsAbortElegantRun($postProcessProc.$rootname)] {
            return
        }
        set waitingFor 1
        set excludeList ""
        while {$waitingFor} {
            set timeout [expr [clock seconds] + 10]
            while {[clock seconds]<$timeout} {
                if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                    return
                }
                set waitingFor 0
                foreach done $doneList pid $pidList {
                    update
                    if [set apsAbortElegantRun($postProcessProc)] {
                        if [catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} aborted] {
                            if [string length $statusCallback] {
                                eval $statusCallback {"$aborted."}
                            }
                        }
                    }
                    if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                        return
                    }
                    if {![file exists $done]  && [lsearch $excludeList $done]<0} {
                        if [catch {exec qstat | grep $pid} result] {
                            if [file exists $done] {
                                continue
                            }
			    set timeSinceChange [APSTimeSinceLastChange -rootname [file root $done]]
			    if [expr $timeSinceChange<60] {
				continue
			    }
                            if [string length $statusCallback] {
                                eval $statusCallback  {"[file root $done] probably bombed before complete."}
                            }
                            if [APSYesNoPopUp "[file root $done] (pid: $pid) probably bombed, do you want to abort $rootname?"] {
                                catch {eval exec cdel $pidList} result
                                if [string length $statusCallback] {
                                    eval $statusCallback  {"$rootname  was aborted: $result"}
                                }
                                set apsAbortElegantRun($postProcessProc.$rootname) 1
                                return
                            }
                            lappend excludeList $done
                        }
                        incr waitingFor
                    }
                }
                if $waitingFor {
                    if [set apsAbortElegantRun($postProcessProc)] {
                        if [catch {APSElegantAbortRun -postProcessProc $postProcessProc -statusCallback $statusCallback} aborted] {
                            if [string length $statusCallback] {
                                eval $statusCallback {"$aborted"}
                            }
                        }
                    }
                    if [set apsAbortElegantRun($postProcessProc.$rootname)] {
                        return
                    }
                } else {
                    break
                }
                APSWaitWithUpdate -updateInterval 1 -waitSeconds 5
            }
            if $waitingFor {
                if [string length $statusCallback] {
                    eval $statusCallback {"Waiting for $waitingFor jobs"}
                }
                APSWaitWithUpdate -updateInterval 1 -waitSeconds 5
            }
        }
        if [string length $statusCallback] {
            eval $statusCallback {"All jobs completed."}
        }
        eval file delete $scriptList $doneList
    }
    if [llength $outputList] {
        set prefix $collectiveEffects(prefix)
        if [catch {exec sddsmakedataset $mainDirectory/${mainPrefix}${prefix}.${extension}.settings \
                     -column=charge,type=double,units=C -data=[join $chargeList ,] \
                     -column=rfVoltage,type=double,units=V -data=[join $rfVoltageList ,] \
                     -column=emittanceRatio,type=double -data=[join $emittanceRatioList ,] \
                     -column=BBImpedance,type=double,units=Ohms -data=[join $BBImpedanceList ,] \
                     -column=rfHarmonic,type=long -data=[join $rfHarmonicList ,] \
                     -column=superPeriods,type=long -data=[join $superPeriodsList ,] \
                     -column=VHarmonic,type=double -data=[join $VHarmonicList ,] \
                     -column=harmonicRatio,type=long -data=[join $harmonicRatioList ,] \
                     -column=scanVariable,type=string \
                     -data=[join [APSReplicateItem -item $scanVariable -number $points] ,]} result] {
            return -code error "$result"
        }
        return [concat $mainDirectory/${mainPrefix}${prefix}.${extension}.settings $outputList]
    }
    return -code error ""
}

proc APSElegantDetermineScanVariableCollectiveEffects {args} {
    set mainDirectory ""
    set mainPrefix ""
    APSStrictParseArguments {mainDirectory mainPrefix}
    
    global collectiveEffects scanRunDone
    set scanQuantities 0
    foreach item {charge rfVoltage emittanceRatio BBImpedance VHarmonic} {
        if [expr [set collectiveEffects(${item}0)]!=[set collectiveEffects(${item}1)]] {
            incr scanQuantities 1
            set scanVariable $item
        }
    }
    if $scanQuantities!=1 {
        return -code error "Scan one and only one quantity.  All others must have the two values equal."
    }
    return $scanVariable
}

proc APSElegantRunIBS {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    global collectiveEffects basicComputations
    if ![file exists $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: please perform Basic run in order to proceed."}
        }
        return -code error "Error: please perform Basic run in order to proceed."
    }
    if ![file exists $mainDirectory/${mainPrefix}$collectiveEffects(prefix).hai] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: Haissinski must be run first"}
        }
        return -code error "Error: Haissinski must be run first"
    }
    
    if [catch {APSElegantScanCollectiveEffectsProgram -extension ibs -type IBS \
                 -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
                 -statusCallback \"$statusCallback\" -gridEngine $gridEngine \
                 -dataFile $mainDirectory/${mainPrefix}$collectiveEffects(prefix).hai \
                 -template "ibsEmittance $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi <output> -charge=<charge_nC> -coupling=<emittanceRatio> -length=<rmsBunchLength_mm> -superperiods=<superPeriods>"} result] {
        return -code error "$result"
    }
    set mainFile [lindex $result 0]
    set indivFileList [lrange $result 1 end]
    eval exec sddscombine $indivFileList -collapse -pipe=out \
      | sddsxref $mainFile -pipe=in -take=* $mainDirectory/${mainPrefix}$collectiveEffects(prefix).ibs
    eval file delete -force $result
    set collectiveEffects(ibsOutput) $mainDirectory/${mainPrefix}$collectiveEffects(prefix).ibs
    APSElegantDisplayIBS -makePngFiles $makePngFiles -statusCallback $statusCallback -noPlots $noPlots
}

proc APSElegantDisplayIBS {args} {
    set makePngFiles 0
    set statusCallback ""
    set rootname ""
    set noPlots 0
    APSStrictParseArguments {makePngFiles statusCallback rootname noPlots}
    global collectiveEffects 
    set input $collectiveEffects(ibsOutput)
    if ![file exists $input] {
        return -code error "not found: $input"
    }
    if [catch {exec sdds2stream $input -column=scanVariable \
                 | tail -1} scanVariable] {
        return -code error "$scanVariable"
    }
    
    exec sddsplot $input -graph=symbol,vary=type,subtype=type,connect=type,scale=2 \
      -legend "-topline=[ExpandFilename $input]" \
      -column=$scanVariable,(emitxInput,emitx) -end \
      -column=$scanVariable,(emityInput,emity) -end \
      -column=$scanVariable,(sigmaDelta0,sigmaDelta) -end \
      -column=$scanVariable,(sigmaz0,sigmaz) -end &
    
    if $makePngFiles {
        exec sddsplot -thick=2 -device=png,onwhite,template=$input-%ld.png "-topline=[ExpandFilename $input]" \
          $input -graph=symbol,vary=type,subtype=type,connect=type,scale=2 -legend \
          -column=$scanVariable,(emitxInput,emitx) -end \
          -column=$scanVariable,(emityInput,emity) -end \
          -column=$scanVariable,(sigmaDelta0,sigmaDelta) -end \
          -column=$scanVariable,(sigmaz0,sigmaz) -end &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG files: $input-\[0123\].png"}
        }
    }
}

proc APSElegantRunHaissinski {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}

    global collectiveEffects basicComputations
    if ![file exists $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: please perform Basic run in order to proceed."}
        }
        return -code error "Error: please perform Basic run in order to proceed."
    }
    set cmks 2.99792458e8 
    set h $collectiveEffects(rfHarmonic)
    set V [expr $collectiveEffects(rfVoltage1)/1e6]
    if [catch {exec sddsprocess $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi -pipe=out \
                 -process=s,max,sMax \
                 | sdds2stream -pipe -parameter=pCentral,Sdelta0,sMax,U0,alphac } dataList] {
        return -code error "$dataList"
    }
    #after including errors into basic computations, the .twi file has multiple pages, 
    #[lrange $dataList 0 4] is to take the data from the first page only
    APSSetVarsFromList -variableList "pCentral energySpread sMax Uo alphac" \
      -valueList "[lrange $dataList 0 4]"
    set revolutionFrequency [expr $cmks/($sMax*$collectiveEffects(superPeriods))]
    set energy [expr $pCentral*0.511]
    set bunchLength [expr 1e3*$energySpread*$cmks* \
                       sqrt($alphac/(2*3.1415926*$h))/$revolutionFrequency* \
                       sqrt($energy/sqrt($V*$V-$Uo*$Uo))]
    if [string length $statusCallback] {
        eval $statusCallback {"Initial bunch length $bunchLength mm"}
    }
    
    set haissinskiPoints 4000
    set haissinskiFraction 0.01
    set haissinskiDivisor 100.0
    set haissinskiIterations 1000
    set haissinskiTolerance 0.0001
    set extraOption "-integration=deltaTime=[expr $bunchLength/1e3/$haissinskiDivisor/$cmks],points=$haissinskiPoints,fraction=$haissinskiFraction,iterations=$haissinskiIterations,tolerance=$haissinskiTolerance -steps=1" 
    if [catch {APSElegantScanCollectiveEffectsProgram -extension hai -type Haissinski \
                 -mainDirectory $mainDirectory -mainPrefix $mainPrefix -gridEngine $gridEngine \
                 -statusCallback $statusCallback \
                 -template "nice -19 haissinski $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi <output> -model=Zn=<BBImpedance> -charge=<charge> -rf=voltage=<rfVoltage>,harmonic=<rfHarmonic> -harmonicCavity=Voltage=<VHarmonic>,factor=<harmonicRatio> -superPeriods=<superPeriods> $extraOption"} result] {
        return -code error "$result"
    }
    set mainFile [lindex $result 0]
    set indivFileList [lrange $result 1 end]

    # Combine data, compute MWI threshold
    eval exec sddscombine $indivFileList -pipe=out \
      | sddsprocess -pipe \
      {"-define=column,Time2Density,Time sqr Density *"} \
      -process=Density,integ,DensityInteg,functionOf=Time \
      -process=Time2Density,integ,Time2DensityInteg,functionOf=Time \
      {"-define=parameter,rmsBunchDuration,Time2DensityInteg DensityInteg / sqrt ,units=s"} \
      {"-define=parameter,rmsBunchLength,rmsBunchDuration c_mks *,units=m"} \
      | sddscollapse -pipe \
      | sddsxref $mainFile -pipe -take=* \
      | sddsprocess -pipe=in $mainDirectory/${mainPrefix}$collectiveEffects(prefix).hai \
      {"-define=parameter,energySpread0,$energySpread"} \
      {"-define=parameter,energy,$pCentral mev * 1e6 *,units=eV"} \
      {"-define=parameter,alphac,$alphac"} \
      {"-define=parameter,C,$sMax,units=m"} \
      {"-define=column,thresholdCurrent,2.355 sqr 2 pi * sqrt * energy * alphac * rmsBunchLength * energySpread0 sqr * C / BBImpedance /"} \
      {"-define=column,blowup,AverageCurrent thresholdCurrent / 3 rec pow 1 > ? pop : swap pop $ "} \
      {"-define=column,rmsBunchLengthMicrowave,rmsBunchLength blowup *,units=m"} \
      {"-define=column,energySpreadMicrowave,energySpread0 blowup *"} 
    eval file delete -force $result
    set collectiveEffects(haissinskiOutput) $mainDirectory/${mainPrefix}$collectiveEffects(prefix).hai
    APSElegantDisplayHaissinski -makePngFiles $makePngFiles -statusCallback $statusCallback -noPlots $noPlots
}

proc APSElegantDisplayHaissinski {args} {
    set makePngFiles 0
    set statusCallback ""
    set rootname ""
    set noPlots 0
    APSStrictParseArguments {makePngFiles statusCallback rootname noPlots}
    global collectiveEffects 
    set input $collectiveEffects(haissinskiOutput)
    if ![file exists $input] {
        return -code error "not found: $input"
    }
    if [catch {exec sdds2stream $input -column=scanVariable \
                 | tail -1} scanVariable] {
        return -code error "$scanVariable"
    }
    
    exec sddsplot $input -legend "-topline=[ExpandFilename $input]" \
      -graph=symbol,vary=type,subtype=type,connect=type,scale=2 \
      -column=$scanVariable,rmsBunchLength -end &
    
    if $makePngFiles {
        exec sddsplot -thickness=2 -device=png,onwhite -output=$input.png "-topline=[ExpandFilename $input]" \
          $input -graph=symbol,vary=type,subtype=type,connect=type,scale=2 -legend \
          -column=$scanVariable,rmsBunchLength -end &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $input.png"}
        }
    }
}

proc APSElegantRunSCTuneShift {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    global collectiveEffects basicComputations
    if ![file exists $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: please perform Basic run in order to proceed."}
        }
        return -code error "Error: please perform Basic run in order to proceed."
    }
    if ![file exists $mainDirectory/${mainPrefix}$collectiveEffects(prefix).ibs] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: IBS must be run first"}
        }
        return -code error "Error: IBS must be run first"
    }
    if ![file exists $mainDirectory/${mainPrefix}$collectiveEffects(prefix).hai] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: Haissinski must be run first"}
        }
        return -code error "Error: Haissinski must be run first"
    }
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.1 $tmpRoot.2
    if [catch {exec sddsexpand $mainDirectory/${mainPrefix}$collectiveEffects(prefix).hai -pipe=out \
                 | tee $tmpRoot.1 \
                 | sdds2stream -pipe -npages=bare} pages] {
        return -code error "$pages"
    }
    if [catch {exec sddsexpand \
                 $mainDirectory/${mainPrefix}$collectiveEffects(prefix).ibs $tmpRoot.2} result] {
        return -code error "$result"
    }
    if [catch {eval exec nice -19 sddscombine \
                 [APSReplicateItem -item $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi \
                    -number $pages] -pipe=out \
                 | sddsxref $tmpRoot.1 -pipe -leave=* -transfer=parameter,* \
                 | sddsxref $tmpRoot.2 -pipe -leave=* -transfer=parameter,* \
                 | sddsprocess -pipe \
                 {"-define=parameter,K,charge e_mks / re_mks * 2 pi * 1.5 pow / pCentral 3 pow / rmsBunchLength /"} \
                 {"-define=column,Sx,betax emitx * sigmaDelta etax * sqr + sqrt,units=m"} \
                 {"-define=column,Sy,betay emity * sqrt,units=m"} \
                 {"-define=column,SCTSIntegrand,betay Sy / Sx Sy + /,units=1/m"} \
                 -process=SCTSIntegrand,integ,SCTSIntegral,functionOf=s \
                 {"-define=parameter,spaceChargeTuneShift,SCTSIntegral K *"} \
                 | sddscollapse -pipe=in \
                 $mainDirectory/${mainPrefix}$collectiveEffects(prefix).scts } result] {
        return -code error "$result"
    }
    set collectiveEffects(scTuneShiftOutput) $mainDirectory/${mainPrefix}$collectiveEffects(prefix).scts
    APSElegantDisplaySCTuneShift -makePngFiles $makePngFiles -statusCallback $statusCallback -noPlots $noPlots
}

proc APSElegantDisplaySCTuneShift {args} {
    set makePngFiles 0
    set statusCallback ""
    set rootname ""
    set noPlots 0
    APSStrictParseArguments {makePngFiles statusCallback rootname noPlots}
    global collectiveEffects
    set input $collectiveEffects(scTuneShiftOutput)
    if ![file exists $input] {
        return -code error "not found: $input"
    }
    if [catch {exec sdds2stream $input -column=scanVariable \
                 | tail -1} scanVariable] {
        return -code error "$scanVariable"
    }
    
    exec sddsplot $input -graph=symbol,vary=type,subtype=type,connect=type,scale=2 \
      -legend "-topline=[ExpandFilename $input]" \
      -column=$scanVariable,spaceChargeTuneShift &
    
    if $makePngFiles {
        exec sddsplot -thickness=2 -device=png,onwhite -output=$input.png "-topline=[ExpandFilename $input]" \
          $input -graph=symbol,vary=type,subtype=type,connect=type,scale=2 -legend \
          -column=$scanVariable,spaceChargeTuneShift &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $input.png"}
        }
    }
}

proc APSElegantPhaseSpaceTracking {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global phaseSpaceTracking 

    set Plane $phaseSpaceTracking(offsetPlane)
    set tag PhaseSpaceTracking
    set rootname $mainDirectory/${mainPrefix}${tag}$phaseSpaceTracking(userSuffix)$Plane
    APSElegantSaveJobConfiguration -filename $rootname.runCfg -statusCallback $statusCallback \
      -momentum $momentum -matrixLatticeFile  \
      $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names phaseSpaceTracking] {
        lappend origList <$item>
        lappend replList [set phaseSpaceTracking($item)]
    }
    set plane [string tolower $phaseSpaceTracking(offsetPlane)]
    set variable offset
    APSElegantPerformRuns -template $sourceDir/PhaseSpaceTrackingTemplate.ele \
      -parameterFileList $parameterFileList \
      -variable $variable -forceOccurence $forceOccurence \
      -startValue $phaseSpaceTracking(initialOffset) \
      -endValue $phaseSpaceTracking(finalOffset) \
      -points $phaseSpaceTracking(sweepPoints) \
      -copyList done -combineList w1 -mergeList [list var ele ele.log] \
      -replacementList $replList -originalList $origList \
      -tag $tag -suffix $phaseSpaceTracking(userSuffix)$Plane \
      -order 3 -momentum $momentum \
      -postProcessProc APSElegantPhaseSpaceTrackingPP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}

proc APSQueryValuesDialog {args} {
    set nameList ""
    set defaultList ""
    set typeList ""
    set elementList ""
    set name ""
    APSStrictParseArguments {nameList defaultList typeList name elementList}
    
    global queryValuesDialogDone queryValuesDialogArray
    set queryValuesDialogDone 0

    if [info exists queryValuesDialogArray] {
        unset queryValuesDialogArray
    }

    set w [APSUniqueName .]
    APSDialogBox $w -name $name \
      -okCommand "set queryValuesDialogDone 1" \
      -cancelCommand "set queryValuesDialogDone 2"
    
    set index 0
    foreach name $nameList default $defaultList type $typeList {
        set queryValuesDialogArray($name) $default
        if [string compare $type yesNo]==0 {
            APSRadioButtonFrame .rb$index -parent $w.userFrame \
              -label "$name: " -orientation horizontal \
              -variable queryValuesDialogArray($name) \
              -buttonList "Yes No" -valueList "1 0"
        } else {
            APSLabeledEntry .le$index -parent $w.userFrame  \
              -label "$name: " \
              -textVariable queryValuesDialogArray($name) \
              -type $type
        }
        incr index
    }
    tkwait variable queryValuesDialogDone
    if $queryValuesDialogDone==2 {
        return ""
    }
    set arrayList ""
    foreach element $elementList name $nameList {
        lappend arrayList $element
        lappend arrayList $queryValuesDialogArray($name)
    }
    return $arrayList
}


proc APSElegantMakePhaseSpacePlot {args} {
    set plane x
    set rootname ""
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {plane rootname makePngFiles statusCallback noPlots}
    
    if $noPlots {
        return
    }
    set arrayList \
      [APSQueryValuesDialog -name "PhaseSpace plot for $rootname" \
         -nameList "${plane}Min ${plane}Max ${plane}pMin ${plane}pMax TuneColor PngOutput" \
         -elementList "xmin xmax ymin ymax tuneColor pngOutput" \
         -defaultList "-0.1 0.1 -0.1 0.1 1 $makePngFiles" -typeList "real real real real yesNo yesNo" \
         -name "Phase Space Plot Options"]

    if ![llength $arrayList] return
    array set limit $arrayList
    set makePngFiles $limit(pngOutput)
    set limitOptList ""
    foreach item [array names limit] {
        if [string match ?m* $item]==0 continue
        lappend limitOptList $item=[set limit($item)]
    }
    if $limit(tuneColor) {
        set input ${rootname}.w1
        exec sddsnaff $input -pipe=out -column=Pass,C${plane},C${plane}p -terminate=freq=1 \
          | sddscombine -pipe -merge \
          | sddsprocess -pipe -filter=column,C${plane}Frequency,0,0.5 \
          -filter=column,C${plane}pFrequency,0,0.5 \
          -define=column,Phase0,C${plane}Phase \
          -define=column,Phase1,C${plane}pPhase \
          | sddsprocess -pipe \
          "-redefine=column,Phase0,Phase0 Phase1 - abs pi < ? Phase0 : Phase0 Phase1 < ? Phase0 pi 2 * + : Phase0 $ $" \
          "-redefine=column,Phase1,Phase0 Phase1 - abs pi < ? Phase1 : Phase0 Phase1 < ? Phase1 : Phase1 pi 2 * + $ $" \
          "-define=column,TuneP,Phase0 Phase1 < ? C${plane}Frequency : 1 C${plane}Frequency - $ " \
          | sddsexpand -pipe=in $input.naff.tmp
        
        exec sddsxref $input $input.naff.tmp -pipe=out -leave=* -transfer=parameter,TuneP -nowarning \
          | sddssort -pipe -parameter=TuneP \
          | sddsprocess -pipe=in $input.${plane}withNaff -define=column,Tune,TuneP
        file delete $input.naff.tmp
        
        exec sddsplot $input.${plane}withNaff -split=column=Tune,width=0.01 \
          -graph=dot,vary -order=spect "-topline=[ExpandFilename $input]" \
          -col=C${plane},C${plane}p \
          -limit=[join $limitOptList ,] &
        
        if $makePngFiles {
            exec sddsplot -thickness=2 -device=png,onwhite \
              -output=${rootname}-${plane}-${plane}p.png "-topline=[ExpandFilename $input]" \
              $input.${plane}withNaff -split=column=Tune,width=0.01 \
              -graph=dot,vary -order=spect \
              -col=C${plane},C${plane}p \
              -limit=[join $limitOptList ,] &
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: ${rootname}-${plane}-${plane}p.png"}
            }
        }
    } else {
        exec sddsplot \
          -col=C${plane},C${plane}p -graph=dot ${rootname}.w1 \
           "-topline=[ExpandFilename $rootname]" \
          -limit=[join $limitOptList ,] &
        if $makePngFiles {
            exec sddsplot -thickness=2 -device=png,onwhite \
              -output=${rootname}-${plane}-${plane}p.png \
              -col=C${plane},C${plane}p -graph=dot ${rootname}.w1 \
              "-topline=[ExpandFilename $rootname]" \
              -limit=[join $limitOptList ,] &
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: ${rootname}-${plane}-${plane}p.png"}
            }
        }
    }
}

proc APSElegantMakeFFTPhaseSpacePlot {args} {
    set plane x
    set rootname ""
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {plane rootname makePngFiles statusCallback noPlots}
    

    exec sddsxref $rootname.w1  ${rootname}.vare -pipe=out -leave=* -transfer=parameter,* \
	| sddsprocess -pipe "-test=parameter,n_rows 10 >" -nowarning \
	| sddsfft -pipe \
	-column=Pass,Cx*,Cy* -window -suppressAverage \
	| sddsprocess -pipe=in ${rootname}.w1.fft \
	"-print=parameter,${plane}Label,${plane}0 = %.5f,offset"
    
    exec sddsplot -column=f,FFTC${plane} ${rootname}.w1.fft \
      -title=@${plane}Label -separate=page -split=page -mode=y=log,y=special \
      "-topline=[ExpandFilename $rootname]" &
    
    if $makePngFiles {
        exec sddsplot -thickness=2 \
          -device=png,onwhite,template=${rootname}-$plane-fft-%ld.png \
          -column=f,FFTC${plane} ${rootname}.w1.fft \
          -title=@${plane}Label -separate=page -split=page -mode=y=log,y=special \
          "-topline=[ExpandFilename $rootname]" &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG files: ${rootname}-${plane}-fft-*.png"}
        }
    }
}


proc APSElegantPhaseSpaceTrackingPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    
    source $rootname.runCfg
    set plane [string tolower $phaseSpaceTracking(offsetPlane)]
    set otherPlane [string tolower $phaseSpaceTracking(otherPlane)]
    
    exec sddsexpand ${rootname}.var ${rootname}.vare
    
    # plot phase space and FFT for main plane
    APSElegantMakePhaseSpacePlot -rootname $rootname -plane $plane -makePngFiles $makePngFiles \
      -statusCallback $statusCallback -noPlots $noPlots
    APSElegantMakeFFTPhaseSpacePlot -rootname $rootname -plane $plane -makePngFiles $makePngFiles \
      -statusCallback $statusCallback -noPlots $noPlots
    
    if [expr $phaseSpaceTracking(otherCoord)!=0.0] {
        # plot phase space and FFT for other plane
        APSElegantMakePhaseSpacePlot -rootname $rootname -plane $otherPlane \
          -makePngFiles $makePngFiles -statusCallback $statusCallback -noPlots $noPlots
        APSElegantMakeFFTPhaseSpacePlot -rootname $rootname -plane $otherPlane \
          -makePngFiles $makePngFiles -statusCallback $statusCallback -noPlots $noPlots
    }
    
    # Do NAFF analysis 
    exec sddsnaff ${rootname}.w1 -pipe=out \
      -columns=Pass,C${plane},C${otherPlane} \
      -terminateSearch=frequencies=1 -nowarnings -iterate=cycleLimit=200,accuracyLimit=1e-12 \
      | sddscombine -pipe -merge \
      | sddsxref -pipe=in ${rootname}.var -take=* ${rootname}.w1.naff
    
    exec sddsplot "-topline=[ExpandFilename $rootname]" "-xlabel=${plane}0 (m)" \
      -column=offset,C${plane}Frequency ${rootname}.w1.naff -end \
      -column=offset,C${otherPlane}Frequency ${rootname}.w1.naff &
    
    if $makePngFiles {
        exec sddsplot -thickness=2 \
          -device=png,onwhite,template=${rootname}-naff.png \
          "-topline=[ExpandFilename $rootname]" "-xlabel=${plane}0 (m)" \
          -column=offset,C${plane}Frequency ${rootname}.w1.naff -end \
          -column=offset,C${otherPlane}Frequency ${rootname}.w1.naff &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $rootname-naff.png"}
        }
    }
}


proc APSElegantOffMomentumTuneTracking {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global mainParameterFile offMomentumTuneTracking basicComputations
    set tag OffMomentumTuneTracking
    set rootname $mainDirectory/${mainPrefix}${tag}$offMomentumTuneTracking(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    
    
    if ![file exists $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: please perform Basic run in order to proceed."}
        }
        return -code error "Error: please perform Basic run in order to proceed."
    }
    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names offMomentumTuneTracking] {
        lappend origList <$item>
        lappend replList [set offMomentumTuneTracking($item)]
    }
    APSElegantPerformRuns -template $sourceDir/OffMomentumTuneTrackingTemplate.ele \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -originalList $origList -replacementList $replList \
      -variable delta -suffix $offMomentumTuneTracking(userSuffix) \
      -startValue $offMomentumTuneTracking(initialOffset) \
      -endValue $offMomentumTuneTracking(finalOffset) \
      -points $offMomentumTuneTracking(sweepPoints) \
      -tag $tag -order 3 -momentum $momentum \
      -copyList done -combineList [list w1 clo ele ele.log] \
      -postProcessProc APSElegantOffMomentumTuneTrackingPP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}



proc APSElegantOffMomentumTuneTrackingPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg

    set valueList [APSQueryValuesDialog \
		       -nameList [list "PNG output"] \
		       -defaultList [list $makePngFiles] \
		       -elementList [list makePngFiles] \
		       -typeList [list yesNo]]
    array set parameter $valueList
    set makePngFiles $parameter(makePngFiles)

    set count1 [exec sdds2stream -rows=bare $rootname.var]
    set count2 [exec sdds2stream -npage=bare $rootname.w1]
    if $count1!=$count2 {
        return -code error "The watch point file was $count2 pages but the variation log file has $count1"
    }
    exec sddsexpand ${rootname}.var ${rootname}.vare
    exec sddsxref $rootname.w1 $rootname.vare -pipe=out -leave=* -transfer=parameter,*  \
      | sddsnaff -pipe \
      -column=Pass -pair=Cx,Cxp -pair=Cy,Cyp -terminate=freq=1 \
      -iterate=cycleLimit=200,accuracyLimit=1e-12 \
      | sddsexpand -pipe \
      | sddscollapse -pipe \
      | sddsprocess -pipe \
      "-define=column,nuxTracking,CxFrequency" \
      "-define=column,nuyTracking,CyFrequency" \
      | sddsprocess -pipe=in ${rootname}.w1.naff -filter=column,nuxTracking,0,1 \
      -filter=column,nuyTracking,0,1
    
    catch {exec sddsresdiag ${rootname}.resdiag \
             -superperiodicity=$offMomentumTuneTracking(superperiodicity) \
             -order=3 }
    
    exec sddsplot \
      -aspect=1 -topline=$rootname -xlabel=\$gn\$r\$bx\$n -ylabel=\$gn\$r\$by\$n \
      "-topline=[ExpandFilename $rootname]" \
      -column=nuxTracking,nuyTracking ${rootname}.w1.naff \
      -split=column=delta,width=1e-4 -graph=symbol,vary=subtype \
      -orderColors=spectral \
      -column=nux,nuy ${rootname}.resdiag &

    if $makePngFiles {
        exec sddsplot -thickness=2 -device=png,onwhite -output=${rootname}-tunes.png \
          -aspect=1 -topline=$rootname -xlabel=\$gn\$r\$bx\$n -ylabel=\$gn\$r\$by\$n \
          "-topline=[ExpandFilename $rootname]" \
          -column=nuxTracking,nuyTracking ${rootname}.w1.naff \
          -split=column=delta,width=1e-4 -graph=symbol,vary=subtype \
          -orderColors=spectral \
          -column=nux,nuy ${rootname}.resdiag &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: ${rootname}-tunes.png"}
        }
    }

    exec sddsplot \
      "-topline=[ExpandFilename $rootname]" \
      -column=delta,nu?Tracking -separate ${rootname}.w1.naff \
      -topline=$rootname \
      -graph=symbol,connect,scale=2 &

    if $makePngFiles {
        exec sddsplot -thickness=2 -device=png,onwhite,template=${rootname}-vsDelta-%ld.png \
          "-topline=[ExpandFilename $rootname]" \
          -column=delta,nu?Tracking -separate ${rootname}.w1.naff \
          -topline=$rootname \
          -graph=symbol,connect,scale=2 &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG files: ${rootname}-vsDelta-*.png"}
        }
    }
    
}

proc APSElegantHigherOrderDispersion {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global higherOrderDispersion
    
    set tag HigherOrderDispersion
    set rootname $mainDirectory/${mainPrefix}${tag}$higherOrderDispersion(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names higherOrderDispersion] {
        lappend origList <$item>
        lappend replList [set higherOrderDispersion($item)]
    }
    set variable delta
    catch {file delete $rootname.done}
    APSElegantPerformRuns -template $sourceDir/HigherOrderDispersionTemplate.ele \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -variable $variable -suffix $higherOrderDispersion(userSuffix) \
      -startValue $higherOrderDispersion(initialOffset) \
      -endValue $higherOrderDispersion(finalOffset) \
      -points $higherOrderDispersion(sweepPoints) \
      -copyList [list mag done] -combineList [list clo ele ele.log w1] \
      -replacementList $replList -originalList $origList \
      -tag $tag -order 3 -momentum $momentum \
      -postProcessProc APSElegantHigherOrderDispersionPP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}

proc APSElegantHigherOrderDispersionPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg
    set variable delta
    
    if [catch {exec sddsconvert -retain=col,s,x,ElementName,ElementType ${rootname}.clo -pipe=out \
                 | sddsregroup -pipe \
                 | sddsxref -pipe=in $rootname.var $rootname.tmp -take=$variable -reuse=page} result] {
        return -code error "$result"
    }
    set terms [expr int($higherOrderDispersion(sweepPoints)/2)]
    if [catch {exec sddspfit $rootname.tmp -pipe=out -terms=$terms -column=$variable,x \
                 | sddsconvert -pipe -delete=column,* \
                 | sddsarray2column -pipe -convert=Coefficient \
                 | sddstranspose -pipe -root=Coefficient \
                 | sddsprocess -pipe -process=Coef*,first,%s \
                 | sddscollapse -pipe \
                 | sddsxref -pipe=in ${rootname}.clo ${rootname}.disp -take=s,Element*} result] {
        return -code error "$result"
    }
    exec sddsplot -topline=$rootname -column=s,Coefficient* -separate ${rootname}.disp "-topline=[ExpandFilename $rootname]" &
    
    if $makePngFiles {
        exec sddsplot -thickness=2 -device=png,onwhite,template=$rootname-disp-%ld.png \
          -topline=$rootname -column=s,Coefficient* -separate ${rootname}.disp "-topline=[ExpandFilename $rootname]" &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG files: $rootname-disp-*.png"}
        }
    }
}

proc APSElegantDynamicAperture {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    global dynamicAperture 
    set tag DynamicAperture
    set rootname $mainDirectory/${mainPrefix}${tag}$dynamicAperture(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    
    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names dynamicAperture] {
        lappend origList <$item>
        lappend replList [set dynamicAperture($item)]
    }
    APSElegantPerformRun -template $sourceDir/DynamicApertureTemplate.ele \
      -parameterFileList $parameterFileList -suffix $dynamicAperture(userSuffix) \
      -originalList $origList -replacementList $replList \
      -tag $tag -order 3 -momentum $momentum -postProcessProc APSElegantDynamicAperturePP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}

proc APSElegantDynamicAperturePP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    
    exec sddsplot "-topline=[ExpandFilename $rootname]" \
      -column=x,y $rootname.abnd -column=x,y $rootname.aper -graph=sym,scale=2 &    
    
    if $makePngFiles {
        exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname.png \
          "-topline=[ExpandFilename $rootname]" \
          -column=x,y $rootname.abnd -column=x,y $rootname.aper -graph=sym,scale=2 &    
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $rootname.png"}
        }
    }
}

proc APSElegantOffMomentumDynamicAperture {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global offMomentumDynamicAperture

    set tag OffMomentumDynamicAperture
    set rootname $mainDirectory/${mainPrefix}${tag}$offMomentumDynamicAperture(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    
    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names offMomentumDynamicAperture] {
        lappend origList <$item>
        lappend replList [set offMomentumDynamicAperture($item)]
    }
    set variable delta
    APSElegantPerformRuns -template $sourceDir/OffMomentumDynamicApertureTemplate.ele \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -variable $variable -suffix $offMomentumDynamicAperture(userSuffix) \
      -startValue $offMomentumDynamicAperture(deltaMinimum) \
      -endValue $offMomentumDynamicAperture(deltaMaximum) \
      -points $offMomentumDynamicAperture(deltaPoints) \
      -copyList done -combineList [list aper abnd clo ele ele.log] \
      -tag $tag -momentum $momentum -originalList $origList \
      -replacementList $replList -postProcessProc APSElegantOffMomentumDynamicAperturePP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
    
}

proc APSElegantOffMomentumDynamicAperturePP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg
    
    if [catch {exec sddsexpand $rootname.var $rootname.vare
        exec sddsxref $rootname.aper $rootname.vare -leave=* -transfer=param,delta -nowarning
        file delete -force $rootname.vare $rootname.aper~} result] {
        return -code error "$result"
    }
    set variable delta
    
    exec sddsplot -same=x,y,global \
      "-topline=[ExpandFilename $rootname]" \
      -column=x,y $rootname.aper -graph=sym,scale=2 -split=page -sep=page \
      "-title=@${variable},edit=i/\$gd\$r = /" \
      -column=x,y $rootname.abnd -graph=line -omnipresent &
    
    if $makePngFiles {
        exec sddsplot -device=png,onwhite,template=$rootname-%ld.png -thickness=2 \
          "-topline=[ExpandFilename $rootname]" -same=x,y,global \
          -column=x,y $rootname.aper -graph=sym,scale=2 -split=page -sep=page \
          "-title=@${variable},edit=i/\$gd\$r = /" \
          -column=x,y $rootname.abnd -graph=line -omnipresent &
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $rootname-*.png"}
        }
    }
}

proc APSElegantDynamicApertureErrors {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set processOnly 0
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots processOnly}
    
    global dynamicApertureErrors errors
    if ![string length $dynamicApertureErrors(template)] {
        set template $sourceDir/DynamicApertureErrorsTemplate.ele
    } elseif {![file exists [set template $dynamicApertureErrors(template)]]} {
        return -code error "template file not found"
    }
    
    lappend origList <apertureFileDisable>
    if [string length $dynamicApertureErrors(apertureFile)]==0 {
        set dynamicApertureErrors(apertureFile) "\" \""
        set resetApertureFileString 1
        lappend replList 1
    } else {
        set resetApertureFileString 0
        lappend replList 0
    }

    set errorNames [array names errors]
    foreach item [array names dynamicApertureErrors] {
        if [lsearch $errorNames $item]<0 {
            lappend origList <$item>
            lappend replList [set dynamicApertureErrors($item)]
        } else {
            unset dynamicApertureErrors($item)
        }
    }
    if $resetApertureFileString {
        set dynamicApertureErrors(apertureFile) ""
    }

    set tag DynamicApertureErrors
    set rootname $mainDirectory/${mainPrefix}${tag}$dynamicApertureErrors(userSuffix)
    if !$processOnly {
        APSElegantSaveJobConfiguration -filename $rootname.runCfg \
          -statusCallback $statusCallback -momentum $momentum \
          -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
          -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
          -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
          -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
          -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    }

    set parameterFileList [APSElegantGetParameterFileList]
    
    set variable seed
    set firstSeed $errors(seed)
    set lastSeed [expr $firstSeed+10*($errors(numberOfSeeds)-1)]
    set seeds $errors(numberOfSeeds)
    if !$errors(on) {
        set seeds 1
    }
    APSElegantPerformRuns -template $template \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -variable $variable -suffix $dynamicApertureErrors(userSuffix) \
      -startValue $firstSeed -endValue $lastSeed -points $seeds \
      -copyList [list done mag] -combineList [list twi orb cor scor aper ele ele.log] \
      -tag $tag -momentum $momentum -originalList $origList \
      -replacementList $replList -postProcessProc APSElegantDynamicApertureErrorsPP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots \
      -processOnly $processOnly -processorsPerJob $dynamicApertureErrors(nCores)
}

proc APSElegantDynamicApertureErrorsPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg
    
    if [catch {exec sddscombine $rootname.aper -pipe=out -merge \
                 | sddsprocess -pipe -process=x,spread,xSpread -process=y,spread,ySpread \
                 | sdds2stream -pipe -parameter=xSpread,ySpread} result] {
        return -code error "$result"
    }
    if ![llength $result] {
        return -code error "No particles survived tracking!"
    }

    if $errors(on) {
        exec sddscombine $rootname.aper -pipe=out \
	  | sddsprocess -pipe "-define=col,r,x sqr y sqr + sqrt,units=m" "-define=col,theta,x y atan2" \
	  | sddsenvelope -pipe -min=r -max=r -percentile=10,r -percentile=90,r -median=r -copy=theta \
	  | sddsprocess -pipe=in $rootname.aper.proc \
	    "-define=col,x%s,r%s theta cos * 1e3 *,select=r*,edit=d,units=mm" \
	    "-define=col,y%s,r%s theta sin * 1e3 *,select=r*,edit=d,units=mm" 
        
        exec sddsplot "-topline=[ExpandFilename $rootname]" -graph=line,vary \
	    "-xlabel=x (mm)" "-ylabel=y (mm)" \
	    -column=xMedian,yMedian $rootname.aper.proc -legend=spec=Median  \
	    -column=xMin,yMin $rootname.aper.proc -legend=spec=Min  \
	    -column=xMax,yMax $rootname.aper.proc -legend=spec=Max  \
	    -column=x10Percentile,y10Percentile $rootname.aper.proc -legend=spec=10Perc  \
	    -column=x90Percentile,y90Percentile $rootname.aper.proc -legend=spec=90Perc &
        
        if $makePngFiles {
            exec sddsplot -device=lpng,onwhite -output=$rootname-aper.png \
		"-topline=[ExpandFilename $rootname]" -graph=line,vary \
		"-xlabel=x (mm)" "-ylabel=y (mm)" \
		-column=xMedian,yMedian $rootname.aper.proc -legend=spec=Median  \
		-column=xMin,yMin $rootname.aper.proc -legend=spec=Min  \
		-column=xMax,yMax $rootname.aper.proc -legend=spec=Max  \
		-column=x10Percentile,y10Percentile $rootname.aper.proc -legend=spec=10Perc  \
		-column=x90Percentile,y90Percentile $rootname.aper.proc -legend=spec=90Perc &
        
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-aper.png"}
            }
        }
    } else {
        exec sddsplot -column=x,y $rootname.aper -graph=sym  "-topline=[ExpandFilename $rootname]" &
        
        if $makePngFiles {
            exec sddsplot -device=lpng,onwhite -output=$rootname-aper.png \
              -column=x,y $rootname.aper -graph=sym  "-topline=[ExpandFilename $rootname]" &
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-aper.png"}
            }
        }
    }

    if $errors(on) {
        exec sddsenvelope $rootname.twi -pipe=ou \
          -copy=s -minimum=beta*,etax -maximum=beta*,etax -mean=beta*,etax -stand=beta*,etax \
	    | sddsprocess -pipe=in $rootname.twi.env \
	    "-define=col,betaxFracStDevError,betaxStDev betaxMean / " \
	    "-define=col,betayFracStDevError,betayStDev betayMean / " 
        exec sddsplot -graph=line,vary -unsup=y "-topline=[ExpandFilename $rootname]" \
          -column=s,(betaxMin,betaxMean,betaxMax) $rootname.twi.env -end \
          -column=s,betaxFracStDevError $rootname.twi.env -end \
          -column=s,(betayMin,betayMean,betayMax) $rootname.twi.env -end \
          -column=s,betayFracStDevError $rootname.twi.env -end \
          -column=s,(etaxMin,etaxMean,etaxMax) $rootname.twi.env -end \
          -column=s,etaxStDev $rootname.twi.env -end \
          -column=s,Profile $rootname.mag -overlay=xmode=norm,yfact=0.04 -omnipresent &
        if $makePngFiles {
            exec sddsplot "-topline=[ExpandFilename $rootname]" \
		-device=png,onwhite,template=$rootname-twi-%ld.png \
		-graph=line,vary -unsup=y \
		-column=s,(betaxMin,betaxMean,betaxMax) $rootname.twi.env -end \
		-column=s,betaxFracStDevError $rootname.twi.env -end \
		-column=s,(betayMin,betayMean,betayMax) $rootname.twi.env -end \
		-column=s,betayFracStDevError $rootname.twi.env -end \
		-column=s,(etaxMin,etaxMean,etaxMax) $rootname.twi.env -end \
		-column=s,etaxStDev $rootname.twi.env -end \
		-column=s,Profile $rootname.mag -overlay=xmode=norm,yfact=0.04 -omnipresent &
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-twi-*.png"}
            }
        }
    
        exec sddsprocess $rootname.orb -pipe=out -match=parameter,Stage=corrected \
	    | sddsenvelope -pipe=in $rootname.orb.env -copy=s -rms=x,y 
        exec sddsplot -graph=line,vary -unsup=y "-topline=[ExpandFilename $rootname]" \
          -column=s,(xRms,yRms) $rootname.orb.env \
          -column=s,Profile $rootname.mag -overlay=xmode=norm,yfact=0.04 &
        if $makePngFiles {
            exec sddsplot -device=png,onwhite -output=$rootname-orb.png "-topline=[ExpandFilename $rootname]" \
              -graph=line,vary -unsup=y \
              -column=s,(xRms,yRms) $rootname.orb.env \
              -column=s,Profile $rootname.mag -overlay=xmode=norm,yfact=0.04 &
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-orb.png"}
            }
        }
    }
}

proc APSElegantKickApertureErrors {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set processOnly 0
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots processOnly}
    
    global kickApertureErrors errors basicComputations
    if ![string length $kickApertureErrors(template)] {
        if $errors(on) {
            set template $sourceDir/KickApertureErrorsTemplate.ele
        } else {
            set template $sourceDir/KickApertureTemplate.ele
        }
    } elseif {![file exists [set template $kickApertureErrors(template)]]} {
        return -code error "template file not found"
    }
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.1

    if ![file exists $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: please perform Basic run in order to proceed."}
        }
        return -code error "Error: please perform Basic run in order to proceed."
    }

    # Determine total rf voltage, phase, and frequency 
    if [catch {exec sddsprocess  $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).param -pipe=out \
                   -match=col,ElementType=RFCA -match=col,ElementParameter=VOLT,ElementParameter=PHASE,|,ElementParameter=FREQ,| \
                   | sddsconvert -pipe -retain=column,ElementParameter,ParameterValue -topage=1 \
                   | sddsbreak -pipe -rowlimit=3 \
                   | sddstranspose -pipe \
                   | sddscombine -pipe -merge \
                   | sddsprocess -pipe=in $tmpRoot.1 -process=VOLT,sum,VoltSum -process=PHASE,ave,PhaseAve -process=PHASE,spread,PhaseSpread \
                   -process=FREQ,ave,FreqAve -process=FREQ,spread,FreqSpread} result] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: Problem with RFCA data in Basic run: $result"}
        }
        return -code error "Error: Problem with RFCA data in Basic run: $result"
    }
    
    if [catch {exec sddsconvert $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi -pipe=out -topage=1 \
		   | sddsxref $tmpRoot.1 -pipe -leave=* -transfer=param,* \
		   | sddsprocess -pipe \
		   "-process=s,max,sMax" "-define=parameter,fRev,pCentral beta.p c_mks * sMax /,units=Hz" \
		   "-define=param,h,FreqAve fRev / 0.5 + int" \
		   "-define=param,Vrf,VoltSum 1e6 /,units=MeV" \
		   "-define=param,Ss,alphac pCentral mev / * 2 / pi / h / fRev sqr / Vrf / PhaseAve dcos chs / sqrt Sdelta0 * c_mks *" \
		   | sdds2stream -pipe -parameter=Ss} bunchLength] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: problem computing bunch length: $bunchLength"}
        }
        return -code error "Error: problem computing bunch length: $bunchLength"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Bunch length is $bunchLength m"}
    }

    lappend origList <Ss> <referenceTwiss>
    lappend replList $bunchLength $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi

    lappend origList <apertureFileDisable>
    if [string length $kickApertureErrors(apertureFile)]==0 {
        set kickApertureErrors(apertureFile) "\" \""
        set resetApertureFileString 1
        lappend replList 1
    } else {
        set resetApertureFileString 0
        lappend replList 0
    }

    set errorNames [array names errors]
    foreach item [array names kickApertureErrors] {
        if [lsearch $errorNames $item]<0 {
            lappend origList <$item>
            lappend replList [set kickApertureErrors($item)]
        } else {
            unset kickApertureErrors($item)
        }
    }
    if $resetApertureFileString {
        set kickApertureErrors(apertureFile) ""
    }

    set tag KickApertureErrors
    if $errors(on) {
        set rootname $mainDirectory/${mainPrefix}${tag}$kickApertureErrors(userSuffix)
    } else {
        set rootname $mainDirectory/${mainPrefix}${tag}$kickApertureErrors(userSuffix)
    }

    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    if !$processOnly {
        set kickApertureErrors(errorsOn) $errors(on)
        APSElegantSaveJobConfiguration -filename $rootname.runCfg \
          -statusCallback $statusCallback -momentum $momentum \
          -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
          -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
          -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
          -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
          -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    }

    set parameterFileList [APSElegantGetParameterFileList]
    
    if $errors(on) {
        set variable seed
        set firstSeed $errors(seed)
        set lastSeed [expr $firstSeed+10*($errors(numberOfSeeds)-1)]
        set seeds $errors(numberOfSeeds)
        APSElegantPerformRuns -template $template \
	    -processorsPerJob $kickApertureErrors(processors) \
	    -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
	    -variable $variable -suffix $kickApertureErrors(userSuffix) \
	    -startValue $firstSeed -endValue $lastSeed -points $seeds \
	    -copyList [list done mag] -combineList [list twi orb cor scor w1 fin ele ele.log] \
	    -tag $tag -momentum $momentum -originalList $origList \
	    -replacementList $replList -postProcessProc APSElegantKickApertureErrorsPP \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots \
	    -processOnly $processOnly
    } else {
        set seeds 1
        APSElegantPerformRuns -template $template \
	    -processorsPerJob $kickApertureErrors(processors) \
	    -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
	    -suffix $kickApertureErrors(userSuffix) \
	    -copyList [list done mag] -combineList [list twi orb cor scor w1 fin ele ele.log] \
	    -tag $tag -momentum $momentum -originalList $origList \
	    -replacementList $replList -postProcessProc APSElegantKickApertureErrorsPP \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots \
	    -processOnly $processOnly \
	    -variable kickValue -points $kickApertureErrors(steps) \
	    -startValue $kickApertureErrors(minimumKick) \
	    -endValue $kickApertureErrors(maximumKick) 
    }
}

proc APSElegantKickApertureErrorsPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}

    source $rootname.runCfg

    if $kickApertureErrors(errorsOn) {
        exec sddscollapse $rootname.fin -pipe=out \
          | sddsbreak -pipe -decreaseOf=$kickApertureErrors(elementName).ANGLE \
          | sddsprocess -pipe=in $rootname.fin.proc -process=Transmission,zero,KickAperture,functionOf=$kickApertureErrors(elementName).ANGLE,offset=-0.5 \
          "-print=parameter,ApertureLabel,Aperture: %g rad,KickAperture"
          
        exec sddsplot -column=$kickApertureErrors(elementName).ANGLE,Transmission $rootname.fin.proc -topline=@ApertureLabel -split=page -sep=page -same &
    } else {
        exec sddscollapse $rootname.fin -pipe=out \
          | sddsxref -pipe $rootname.var -take=* \
          | sddsprocess -pipe=in $rootname.fin.proc -nowarning \
          -process=Transmission,zero,KickAperture,functionOf=kickValue,offset=-0.5 \
          "-print=parameter,ApertureLabel,Aperture: %g mrad,KickAperture"
        
        exec sddsplot -column=kickValue,Transmission $rootname.fin.proc -topline=@ApertureLabel &
        if $makePngFiles {
            exec sddsplot -device=lpng,onwhite -thickness=2 -output=$rootname.png -topline=@ApertureLabel \
              -column=kickValue,Transmission $rootname.fin.proc &
        }
    }

}

proc APSElegantFineDynamicAperture {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global fineDynamicAperture
    
    set tag FineDynamicAperture
    set rootname $mainDirectory/${mainPrefix}${tag}$fineDynamicAperture(userSuffix)
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names fineDynamicAperture] {
        lappend origList <$item>
        lappend replList [set fineDynamicAperture($item)]
    }
    set variable xOffset
    APSElegantPerformRuns -template $sourceDir/FineDynamicApertureTemplate.ele \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -variable $variable -suffix $fineDynamicAperture(userSuffix) \
      -startValue $fineDynamicAperture(xMinimum) \
      -endValue $fineDynamicAperture(xMaximum) \
      -points $fineDynamicAperture(xPoints) \
      -copyList done -combineList [list ele ele.log los bun clo] \
      -tag $tag -momentum $momentum -originalList $origList -replacementList $replList \
      -postProcessProc APSElegantFineDynamicAperturePP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}

proc APSElegantFineDynamicAperturePP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    
    if $noPlots {
        return
    }
    set valueList [APSQueryValuesDialog -name "Fine DA Plot for $rootname" \
                     -nameList [list "Point size" "Filename on plot?" "Autotitle?" "Make PNG?" "Make EPS?"] \
                     -defaultList [list 2.0 1 1 $makePngFiles] \
                     -elementList [list pointSize filenameTitle autoTitle makePngFiles] \
                     -typeList [list integer yesNo yesNo yesNo]]
    array set parameter $valueList
    set topline ""
    if $parameter(filenameTitle) {
        set topline [ExpandFilename $rootname.da]
    }
    set titleOption ""
    if !$parameter(autoTitle) {
        set titleOption "-title="
    }
    set maxStep [lindex [lsort -integer [exec sdds2stream -par=Step $rootname.los]] end]
    
    set tmpRoot /tmp/[APSTmpString]
    set fileList ""
    for {set step 1} {$step<=$maxStep} {incr step} {
        APSAddToTempFileList $tmpRoot.clo.$step
        APSAddToTempFileList $tmpRoot.los.$step
        if [catch {exec sddsprocess $rootname.los $tmpRoot.los.$step -nowarning \
                     -filter=par,Step,$step,$step 
            exec sddsprocess $rootname.clo $tmpRoot.clo.$step -process=x,first,xCO -nowarning \
                     -filter=par,Step,[expr $step -1],[expr $step -1] } result] {
            if [string length $statusCallback] {
                eval $statusCallback {"$result"}
            }
            continue
        }
        exec sddsxref $tmpRoot.los.$step $rootname.bun -pipe=out -nowarning  \
          -equate=particleID -take=x,y -edit=column,*,ei/0/  -transfer=param,* \
          | sddsxref -pipe -leave=* -transfer=param,xCO $tmpRoot.clo.$step -nowarning \
          | sddsprocess -pipe "-redefine=column,x0,x0 xCO +,units=m" -nowarning \
          | sddscombine -pipe=in -merge $tmpRoot.da.$step -overwrite
        if $maxStep>1 {
            set topline "step $step"
            set suffix -Step$step
        } else {
            set suffix ""
        }
        APSAddToTempFileList $tmpRoot.da.$step
        lappend plotCmd "-column=x0,y0 $tmpRoot.da.$step"
        lappend plotCmd \"-topline=$topline\"
        lappend plotCmd "-graph=symbol,fill,type=2,vary=subtype,scale=$parameter(pointSize) \
         	-order=spect -split=column=Pass,width=1"
        if [string length $titleOption] {
            lappend plotCmd \"$titleOption\"
        }
        lappend plotCmd "-end"
        lappend fileList $tmpRoot.da.$step
        if $parameter(makePngFiles) {
            eval exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname.png$suffix \
              -column=x0,y0  $tmpRoot.da.$step \
              -graph=symbol,fill,type=2,vary=subtype,scale=[expr $parameter(pointSize)*1.33] \
              -order=spect -split=column=Pass,width=1 $titleOption \"-topline=$topline\" &
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname.png$suffix"}
            }
        }
    }
    if [llength $fileList] {
        if [catch {eval exec sddscombine $fileList $rootname.da -overwrite} result] {
            return -code error $result
        }
        eval exec sddsplot [join $plotCmd] &
    } else {
        if [string length $statusCallback] {
            eval $statusCallback {"Nothing to plot, something must be wrong with the processed files ($rootname)"}
        }
    }
}

proc APSElegantFrequencyMap {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global frequencyMap errors
    
    set tag FrequencyMap
    set rootname $mainDirectory/${mainPrefix}${tag}$frequencyMap(userSuffix)
    foreach item [array names errors] {
	lappend origList <$item>
	lappend replList [set errors($item)]
    }

    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    
    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names frequencyMap] {
        lappend origList <$item>
        lappend replList [set frequencyMap($item)]
    }
    if $errors(on) {
	set variable seed
	set startValue $errors(seed)
	set endValue [expr $startValue+10*($errors(numberOfSeeds)-1)]
	set points $errors(numberOfSeeds)
	set postProcess APSElegantFrequencyMapErrorPP 
	set template $sourceDir/FrequencyMapErrorsTemplate.ele 
	set mergeList ""
	set firstOnlyList ""
	set combineList  [list ele ele.log clo orb fma] 
    } elseif !$frequencyMap(singleJob) {
        set points $frequencyMap(xPoints) 
	set variable xOffset
	set startValue $frequencyMap(xMinimum) 
	set endValue $frequencyMap(xMaximum) 
	set postProcess APSElegantFrequencyMapPP 
	set template $sourceDir/FrequencyMapTemplate.ele 
	set mergeList fma
	set firstOnlyList [list clo orb] 
	set combineList [list ele ele.log]
    } else {
        set points 0
	set postProcess APSElegantFrequencyMapPP 
	set template $sourceDir/FrequencyMap1Template.ele 
    }
    if $points==0 {
	APSElegantPerformRun -template $template \
	    -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
	    -suffix $frequencyMap(userSuffix) \
	    -processorsPerJob $frequencyMap(processors) \
	    -tag $tag -momentum $momentum -originalList $origList -replacementList $replList \
	    -postProcessProc $postProcess \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
    } else {
	APSElegantPerformRuns -template $template \
	    -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
	    -variable $variable -suffix $frequencyMap(userSuffix) \
	    -startValue $startValue \
	    -endValue $endValue \
	    -points $points -processorsPerJob $frequencyMap(processors) \
	    -copyList [list done twi] -combineList $combineList -mergeList $mergeList \
	    -tag $tag -momentum $momentum -originalList $origList -replacementList $replList \
	    -postProcessProc $postProcess \
	    -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
	    -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
	    -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
	    -sourceDir $sourceDir -statusCallback $statusCallback \
	    -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
    }
}

proc APSElegantFrequencyMapPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg
    if $errors(on) {
	return [APSElegantFrequencyMapErrorPP -rootname $rootname \
		    -statusCallback $statusCallback -makePngFiles $makePngFiles \
		    -noPlots $noPlots]
    }

    if $noPlots {
        return
    }
    set valueList [APSQueryValuesDialog -name "FMA Plot for $rootname" \
                     -nameList [list "Resonance diagram order" "Minimum nux" \
                                  "Maximum nux" "Minimum nuy" "Maximum nuy" \
				  "Minimum x" "Maximum x" \
				  "Minimum y" "Maximum y" \
                                  "Point size spatial" "Point size tune" "Filename on plot?" \
                                  "Show resonances?" "Sigma normalize?" \
                                  "Emittance coupling" "Make PNG?" "Make EPS?"] \
                     -defaultList [list 4 -0.05 1.05 -0.05 1.05 -1.0 1.0 -1.0 1.0 2.0 0.25 1 0 0 0.1 $makePngFiles 0] \
                     -elementList [list order nux0 nux1 nuy0 nuy1 x0 x1 y0 y1 pointSizeSpatial \
                                     pointSizeTune filenameTitle showResonances sigmaNorm \
                                     emittanceCoupling makePngFiles makeEpsFiles] \
                     -typeList [list integer real real real real real real real real real real yesNo yesNo yesNo real yesNo yesNo]]
    if ![llength $valueList] return
    array set parameter $valueList
    catch {exec sddsresdiag $rootname.resdiag -order=$parameter(order)}
    
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.fma
    set fileList ""
    if [catch {exec grep "set errors(on) {0}" $rootname.runCfg} result] {
        set maxStep [lindex [lsort -integer [exec sdds2stream -par=Step $rootname.fma]] end]
        for {set i 1} {$i<=$maxStep} {incr i} {
            APSAddToTempFileList $tmpRoot.fma.$i
            if [catch {exec sddssort $rootname.fma -par=Step -pipe=out \
                         | sddsprocess -pipe\
                         -filter=par,Step,$i,$i -nowarnings \
                         | sddscombine -pipe=in -merge $tmpRoot.fma.$i } result] {
                return -code error $result
            }
            lappend fileList $tmpRoot.fma.$i
            lappend stepList $i
        }
    } else {
        exec sddscombine -merge $rootname.fma $tmpRoot.fma
        set layout "-layout=1,1"
        lappend fileList $tmpRoot.fma
        lappend stepList 1
    }
    
    set title1 "Color indicates initial x amplitude"
    set title2 "Color indicates initial y amplitude"
    set title3 "Color indicates diffusion"
    set topLine [ExpandFilename $rootname.fma]
    lappend plotOpt "-limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto"
    foreach file $fileList step $stepList {
        if [llength $fileList]>1 {
            set topline "x amplitude at step $step   [ExpandFilename $rootname.fma]"
            set suffix -step$step
        } else  {
            set topline [ExpandFilename $rootname.fma]
            set suffix ""
        }
        lappend plotOpt "-column=nux,nuy $rootname.resdiag"
        lappend plotOpt "-column=nux,nuy $file"
	lappend plotOpt -filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1)
        if $parameter(filenameTitle) {
            lappend plotOpt \"-topline=$topline\"
        }
        lappend plotOpt "-graph=symbol,type=2,fill,scale=$parameter(pointSizeTune),vary=subtype"
        lappend plotOpt "-order=spect"
        lappend plotOpt \"-title=$title1\"
        if $parameter(makePngFiles) {
            exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname-fma1${suffix}.png "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $file \
		-filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1) \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title1" \
              -split=column=x 
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma1${suffix}.png"}
            }
            exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname-fma2${suffix}.png "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $file \
		-filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1) \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title2" \
              -split=column=y
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma2${suffix}.png"}
            }
            exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname-fma3${suffix}.png "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $file \
		-filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1) \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title3" \
              -split=column=diffusion 
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma3${suffix}.png"}
            }
        }
        if $parameter(makeEpsFiles) {
            exec sddsplot -device=ceps -thickness=2 -output=$rootname-fma1${suffix}.eps "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $file \
		-filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1) \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title1" \
              -split=column=x
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma1${suffix}.eps"}
            }
            exec sddsplot -device=ceps,onwhite -thickness=2 -output=$rootname-fma2${suffix}.eps "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $file \
		-filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1) \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title2" \
              -split=column=y 
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma2${suffix}.eps"}
            }
            exec sddsplot -device=ceps,onwhite -thickness=2 -output=$rootname-fma3${suffix}.eps "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $file \
		-filter=col,x,$parameter(x0),$parameter(x1) -filter=col,y,$parameter(y0),$parameter(y1) \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title3" \
              -split=column=diffusion
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma3${suffix}.eps"}
            }
        }
    }
    
    eval exec sddsplot [join $plotOpt] -split=column=x &
    regsub -all {x amplitude} $plotOpt "y amplitude" plotOpt1
    regsub -all {column=x} $plotOpt1 "column=y" plotOpt2
    regsub -all {xM} $plotOpt2 "yM" plotOpt1
    eval exec sddsplot [join $plotOpt1] -split=column=y &

    regsub -all {x amplitude} $plotOpt "diffusion" plotOpt1
    regsub -all {column=x} $plotOpt1 "column=diffusion" plotOpt2
    eval exec sddsplot [join $plotOpt2] -split=column=diffusion &
    
    set xmin [expr $frequencyMap(xMinimum)<0 ? 1.05*$frequencyMap(xMinimum) : 0]
    set xmax [expr 1.05*$frequencyMap(xMaximum)]
    set ymin [expr $frequencyMap(yMinimum)<0 ? 1.05*$frequencyMap(yMinimum) : 0]
    set ymax [expr 1.05*$frequencyMap(yMaximum)]

    if $parameter(sigmaNorm) {
        if [catch {exec sddsprocess $rootname.twi -pipe=out \
                     -define=parameter,coupling,$parameter(emittanceCoupling) \
                     -process=*eta*,first,%s0 \
                     "-define=parameter,ey,ex0 coupling * coupling 1 + /" \
                     "-define=parameter,ex,ex0 coupling 1 + /" \
                     "-define=parameter,sigmax,betax0 ex * etax0 Sdelta0 * sqr + sqrt" \
                     "-define=parameter,sigmay,betay0 ey * sqrt" \
                     | sdds2stream -pipe -parameter=sigmax,sigmay} result] {
            return -code error "$result"
        }
        set xfactor [expr 1./[lindex $result 0]]
        set yfactor [expr 1./[lindex $result 1]]
        set xlabel {x/\$gs\$r}
        set ylabel {y/\$gs\$r}
    } else {
        set xfactor 1.0
        set yfactor 1.0
        set xlabel "x (m)"
        set ylabel "y (m)"
    }

    set title1 "Color indicates x tune"

    set extraOpts0 "-filter=column,nux,$parameter(nux0),$parameter(nuy1) -filter=column,nuy,$parameter(nuy0),$parameter(nuy1)"
    set extraOpts1 ""
    set extraOpts2 ""
    
    set plotCmd ""
    foreach file $fileList step $stepList {
        if [llength $fileList]>1 {
            set topline "x tune at step $step    [ExpandFilename $rootname]"
            set suffix -step$step
        } else  {
            set topline [ExpandFilename $rootname]
            set suffix ""
        }
        if $parameter(showResonances) {
            APSElegantInterpolateResonances -input $file -output ${file}-Res -order $parameter(order) \
              -statusCallback $statusCallback -planeList {x y}
            set extraOpts1 "-pspace=0.15,0.75,0,0 -lspace=1.15,1.35,0,0.95 -separate=tag -groupby=tag,req "
            set extraOpts2 "-column=x,y ${file}-Res -graph=sym,vary -legend=param=resonanceLabel -tag=@multipole -split=page "
        }
        lappend plotCmd $extraOpts1
        lappend plotCmd "-limit=xmin=$xmin,xmax=$xmax,ymin=$ymin,ymax=$ymax -factor=xmult=$xfactor,ymult=$yfactor"
        lappend plotCmd \"-xlabel=$xlabel\"
        lappend plotCmd \"-ylabel=$ylabel\"
        lappend plotCmd "-column=x,y $file -graph=symbol,type=2,fill,scale=$parameter(pointSizeSpatial),vary=subtype \
	-order=spect -omnipresent=first "
        if $parameter(filenameTitle) {
            lappend plotCmd \"-topline=$topline\"
        }
        lappend plotCmd \"-title=$title1\"
        lappend plotCmd -split=column=nux
        lappend plotCmd "$extraOpts2" 
        lappend plotCmd -end 
    }

    eval exec sddsplot [join $plotCmd] &
    if $parameter(makePngFiles) {
        eval exec sddsplot -device=lpng,onwhite -thickness=2 -output=$rootname-fma4${suffix}.png $extraOpts0 [join $plotCmd]
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $rootname-fma3${suffix}.png"}
        }
    }
    if $parameter(makeEpsFiles) {
        eval exec sddsplot -device=ceps -thickness=2 -output=$rootname-fma4${suffix}.eps $extraOpts0 [join $plotCmd]
        if [string length $statusCallback] {
            eval $statusCallback {"EPS file: $rootname-fma3${suffix}.eps"}
        }
    }

    regsub -all {nux} $plotCmd "nuy" plotCmd1
    regsub -all {x tune} $plotCmd1 "y tune" plotCmd
    eval exec sddsplot [join $plotCmd] &
    if $parameter(makePngFiles) {
        eval exec sddsplot -device=lpng,onwhite -thickness=2 -output=$rootname-fma5${suffix}.png $extraOpts0 [join $plotCmd]
        if [string length $statusCallback] {
            eval $statusCallback {"PNG file: $rootname-fma4${suffix}.png"}
        }
    }
    if $parameter(makeEpsFiles) {
        eval exec sddsplot -device=ceps,onwhite -thickness=2 -output=$rootname-fma5${suffix}.eps $extraOpts0 [join $plotCmd]
        if [string length $statusCallback] {
            eval $statusCallback {"EPS file: $rootname-fma4${suffix}.eps"}
        }
    }

    set nameList [exec sddsquery [lindex $fileList 0] -columnList -readAll]
    if [lsearch -exact $nameList diffusion]!=-1 {
        regsub -all {nuy} $plotCmd "diffusion" plotCmd1
        regsub -all {y tune} $plotCmd1 "diffusion" plotCmd
        eval exec sddsplot [join $plotCmd] &
        if $parameter(makePngFiles) {
            eval exec sddsplot -device=lpng,onwhite -thickness=2 -output=$rootname-fma6${suffix}.png [join $plotCmd]
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma5${suffix}.png"}
            }
        }
        if $parameter(makeEpsFiles) {
            eval exec sddsplot -device=ceps,onwhite -thickness=2 -output=$rootname-fma6${suffix}.eps [join $plotCmd]
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma5${suffix}.eps"}
            }
        }
    }
}

proc APSElegantFrequencyMapErrorPP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg
    
    if $noPlots {
        return
    }
    set valueList [APSQueryValuesDialog -name "FMA Plot for $rootname" \
                     -nameList [list "Resonance diagram order" "Minimum nux" \
                                  "Maximum nux" "Minimum nuy" "Maximum nuy" \
                                  "Point size spatial" "Point size tune" "Filename on plot?" \
                                  "Show resonances?" "Sigma normalize?" \
                                  "Emittance coupling" "Make PNG?" "Make EPS?"] \
                     -defaultList [list 4 -0.05 1.05 -0.05 1.05 2.0 0.25 1 0 0 0.1 $makePngFiles 0] \
                     -elementList [list order nux0 nux1 nuy0 nuy1 pointSizeSpatial \
                                     pointSizeTune filenameTitle showResonances sigmaNorm \
                                     emittanceCoupling makePngFiles makeEpsFiles] \
                     -typeList [list integer real real real real real real yesNo yesNo yesNo real yesNo yesNo]]
    if ![llength $valueList] return
    array set parameter $valueList
    catch {exec sddsresdiag $rootname.resdiag -order=$parameter(order)}
    
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.fma
    set fileList ""
    exec sddscombine -merge=Filename $rootname.fma -pipe=out \
	| sddsprocess -pipe=in -define=parameter,inputPage,i_page,type=long $rootname.fmac

    # Tune diagram plots: (nux, nuy) colored by x or y amplitude
    set title1 "Color indicates initial x amplitude"
    set title2 "Color indicates initial y amplitude"
    set topLine [ExpandFilename $rootname.fmac]
    lappend plotOpt "-limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto"
    set topline "x amplitude   [ExpandFilename $rootname.fmac]"
    lappend plotOpt "-column=nux,nuy $rootname.resdiag -omnipresent"
    lappend plotOpt "-column=nux,nuy $rootname.fmac"
    if $parameter(filenameTitle) {
	lappend plotOpt \"-topline=$topline\"
    }
    lappend plotOpt "-graph=symbol,type=2,fill,scale=$parameter(pointSizeTune),vary=subtype"
    lappend plotOpt "-order=spect -separate=tag -groupby=tag,request -tag=@inputPage"
    lappend plotOpt \"-title=$title1\"
    lappend plotOpt "-split=page,column=x,start=$frequencyMap(xMinimum),width=[expr ($frequencyMap(xMaximum)-$frequencyMap(xMinimum))/101.0] -end"
    
    eval exec sddsplot [join $plotOpt] &
    if $parameter(makePngFiles) {
	eval exec sddsplot -device=lpng,onwhite,template=${rootname}-fma1-%02ld.png -thick=2 -line=0,thick=2 [join $plotOpt] 
    }
    if $parameter(makeEpsFiles) {
	eval exec sddsplot -device=ceps -output=${rootname}-fma1.eps -thick=2 -line=0,thick=2 [join $plotOpt] 
    }

    regsub -all {x amplitude} $plotOpt "y amplitude" plotOpt1
    regsub -all {column=x} $plotOpt1 "column=y" plotOpt
    regsub -all {xM} $plotOpt "yM" plotOpt1
    eval exec sddsplot [join $plotOpt1] &
    if $parameter(makePngFiles) {
	eval exec sddsplot -device=lpng,onwhite,template=${rootname}-fma2-%02ld.png -thick=2 -line=0,thick=2 [join $plotOpt] 
    }
    if $parameter(makeEpsFiles) {
	eval exec sddsplot -device=ceps -output=${rootname}-fma2.eps -thick=2 -line=0,thick=2 [join $plotOpt] 
    }

    # Plots of tune maps vs (x, y)

    set xmin [expr $frequencyMap(xMinimum)<0 ? 1.05*$frequencyMap(xMinimum) : 0]
    set xmax [expr 1.05*$frequencyMap(xMaximum)]
    set ymin [expr $frequencyMap(yMinimum)<0 ? 1.05*$frequencyMap(yMinimum) : 0]
    set ymax [expr 1.05*$frequencyMap(yMaximum)]

    if $parameter(sigmaNorm) {
        if [catch {exec sddsprocess $rootname.twi -pipe=out \
                     -define=parameter,coupling,$parameter(emittanceCoupling) \
                     -process=*eta*,first,%s0 \
                     "-define=parameter,ey,ex0 coupling * coupling 1 + /" \
                     "-define=parameter,ex,ex0 coupling 1 + /" \
                     "-define=parameter,sigmax,betax0 ex * etax0 Sdelta0 * sqr + sqrt" \
                     "-define=parameter,sigmay,betay0 ey * sqrt" \
                     | sdds2stream -pipe -parameter=sigmax,sigmay} result] {
            return -code error "$result"
        }
        set xfactor [expr 1./[lindex $result 0]]
        set yfactor [expr 1./[lindex $result 1]]
        set xlabel {x/\$gs\$r}
        set ylabel {y/\$gs\$r}
    } else {
        set xfactor 1.0
        set yfactor 1.0
        set xlabel "x (m)"
        set ylabel "y (m)"
    }

    set title1 "Color indicates x tune"

    set extraOpts0 "-filter=column,nux,$parameter(nux0),$parameter(nuy1) -filter=column,nuy,$parameter(nuy0),$parameter(nuy1)"
    set extraOpts1 ""
    set extraOpts2 ""
    set plotCmd "-groupby=tag,request -separate=tag -tag=@inputPage "
    if $parameter(showResonances) {
	APSElegantInterpolateResonances -input $rootname.fmac -output $rootname.fmac-Res -order $parameter(order) \
	    -statusCallback $statusCallback -planeList {x y}
	set extraOpts1 "-pspace=0.15,0.75,0,0 -lspace=1.15,1.35,0,0.95 "
	set extraOpts2 "-column=x,y $rootname.fmac-Res -graph=sym,vary -legend=param=resonanceLabel -tag=@inputPage -split=page "
    }
    lappend plotCmd $extraOpts1
    lappend plotCmd "-limit=xmin=$xmin,xmax=$xmax,ymin=$ymin,ymax=$ymax -factor=xmult=$xfactor,ymult=$yfactor"
    lappend plotCmd \"-xlabel=$xlabel\"
    lappend plotCmd \"-ylabel=$ylabel\"
    lappend plotCmd "-column=x,y $rootname.fmac -graph=symbol,type=2,fill,scale=$parameter(pointSizeSpatial),vary=subtype -order=spect"
    if $parameter(filenameTitle) {
	lappend plotCmd \"-topline=$topline\"
    }
    lappend plotCmd \"-title=$title1\"
    lappend plotCmd "-split=column=nux,page "
    lappend plotCmd "$extraOpts2" 
    lappend plotCmd -end 

    eval exec sddsplot [join $plotCmd] &
    if $parameter(makePngFiles) {
        eval exec sddsplot -device=lpng,onwhite,template=$rootname-fma3-%02ld.png -thickness=2 $extraOpts0 [join $plotCmd]
    }
    if $parameter(makeEpsFiles) {
        eval exec sddsplot -device=ceps -output=$rootname-fma3.eps -thickness=2 $extraOpts0 [join $plotCmd]
    }

    regsub -all {nux} $plotCmd "nuy" plotCmd1
    regsub -all {x tune} $plotCmd1 "y tune" plotCmd
    eval exec sddsplot [join $plotCmd] &
    if $parameter(makePngFiles) {
        eval exec sddsplot -device=lpng,onwhite,template=$rootname-fma4-%02ld.png -thickness=2 $extraOpts0 [join $plotCmd]
    }
    if $parameter(makeEpsFiles) {
        eval exec sddsplot -device=ceps -output=$rootname-fma4.eps -thickness=2 $extraOpts0 [join $plotCmd]
    }

    set nameList [exec sddsquery $rootname.fmac -columnList -readAll]
    if [lsearch -exact $nameList diffusion]!=-1 {
        regsub -all {nuy} $plotCmd "diffusion" plotCmd1
        regsub -all {y tune} $plotCmd1 "diffusion" plotCmd
        eval exec sddsplot [join $plotCmd] &
        if $parameter(makePngFiles) {
            eval exec sddsplot -device=lpng,onwhite,template=$rootname-fma5-%02ld.png -thickness=2 [join $plotCmd]
        }
        if $parameter(makeEpsFiles) {
            eval exec sddsplot -device=ceps -output=$rootname-fma5.eps -thickness=2 [join $plotCmd]
        }
    }
}

proc APSElegantFrequencyMapDelta {args} {
    global frequencyMapDelta errors
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0

    if $errors(on) {
	return [eval APSElegantFrequencyMapDeltaErrors $args]
    }

    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}

    set Plane $frequencyMapDelta(plane)
    set plane [string tolower $Plane]

    set tag FrequencyMapDelta
    set rootname $mainDirectory/${mainPrefix}${tag}$frequencyMapDelta(userSuffix)$Plane
    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles

    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names frequencyMapDelta] {
        lappend origList <$item>
        lappend replList [set frequencyMapDelta($item)]
    }
    if [string compare $plane "x"]==0 {
        lappend origList <xMinimum> <xMaximum> <xPoints>
        lappend replList $frequencyMapDelta(xyMinimum) 
        lappend replList $frequencyMapDelta(xyMaximum)
        lappend replList $frequencyMapDelta(xyPoints)

        lappend origList <yMinimum> <yMaximum> <yPoints>
        lappend replList $frequencyMapDelta(otherCoordinate)
        lappend replList $frequencyMapDelta(otherCoordinate)
        lappend replList 1
    } else {
        lappend origList <yMinimum> <yMaximum> <yPoints>
        lappend replList $frequencyMapDelta(xyMinimum) 
        lappend replList $frequencyMapDelta(xyMaximum)
        lappend replList $frequencyMapDelta(xyPoints)

        lappend origList <xMinimum> <xMaximum> <xPoints>
        lappend replList $frequencyMapDelta(otherCoordinate)
        lappend replList $frequencyMapDelta(otherCoordinate)
        lappend replList 1
    }
    set variable delta
    APSElegantPerformRuns -template $sourceDir/FrequencyMapDeltaTemplate.ele \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -variable $variable -suffix $frequencyMapDelta(userSuffix)$Plane \
      -startValue $frequencyMapDelta(deltaMinimum) \
      -endValue $frequencyMapDelta(deltaMaximum) \
      -points $frequencyMapDelta(deltaPoints) \
      -copyList [list done twi] -combineList [list ele ele.log clo fma var] \
      -tag $tag -momentum $momentum -originalList $origList -replacementList $replList \
      -postProcessProc APSElegantFrequencyMapDeltaPP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}

proc APSElegantFrequencyMapDeltaErrors {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots}
    
    global frequencyMapDelta errors
    
    set Plane $frequencyMapDelta(plane)
    set plane [string tolower $Plane]

    set tag FrequencyMapDelta
    set rootname $mainDirectory/${mainPrefix}${tag}$frequencyMapDelta(userSuffix)$Plane

    foreach item [array names errors] {
	lappend origList <$item>
	lappend replList [set errors($item)]
    }

    APSElegantSaveJobConfiguration -filename $rootname.runCfg \
      -statusCallback $statusCallback -momentum $momentum \
      -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
      -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
      -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
      -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    
    set parameterFileList [APSElegantGetParameterFileList]
    foreach item [array names frequencyMapDelta] {
        lappend origList <$item>
        lappend replList [set frequencyMapDelta($item)]
    }
    switch [string tolower $frequencyMapDelta(plane)] {
	x {
	    lappend origList <xMinimum> <xMaximum> <xPoints>
	    lappend replList $frequencyMapDelta(xyMinimum) $frequencyMapDelta(xyMaximum) $frequencyMapDelta(xyPoints)
	    lappend origList <yMinimum> <yMaximum> <yPoints>
	    lappend replList $frequencyMapDelta(otherCoordinate) $frequencyMapDelta(otherCoordinate) 1
	}
	y {
	    lappend origList <yMinimum> <yMaximum> <yPoints>
	    lappend replList $frequencyMapDelta(xyMinimum) $frequencyMapDelta(xyMaximum) $frequencyMapDelta(xyPoints)
	    lappend origList <xMinimum> <xMaximum> <xPoints>
	    lappend replList $frequencyMapDelta(otherCoordinate) $frequencyMapDelta(otherCoordinate) 1
	}
    }

    set variable seed
    set startValue $errors(seed)
    set endValue [expr $startValue+10*($errors(numberOfSeeds)-1)]
    set points $errors(numberOfSeeds)
    set postProcess APSElegantFrequencyMapDeltaErrorsPP 
    set template $sourceDir/FrequencyMapDeltaErrorsTemplate.ele 
    set mergeList ""
    set firstOnlyList ""
    set combineList  [list ele ele.log clo orb fma] 

    APSElegantPerformRuns -template $template \
      -parameterFileList $parameterFileList -forceOccurence $forceOccurence \
      -variable $variable -suffix $frequencyMapDelta(userSuffix)$Plane \
      -startValue $startValue \
      -endValue $endValue \
      -points $points -processorsPerJob $frequencyMapDelta(processors) \
      -copyList [list done twi] -combineList $combineList -mergeList $mergeList \
      -tag $tag -momentum $momentum -originalList $origList -replacementList $replList \
      -postProcessProc $postProcess \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots
}


proc APSElegantInterpolateResonances {args} {
    set input ""
    set output ""
    set statusCallback APSNoOp
    set order 4
    set planeList {x y}
    if {[APSStrictParseArguments {input output statusCallback planeList order}] || \
          ![string length $input] || ![string length $output]} {
        return -code error "APSElegantInterpolateResonances: invalid arguments"
    }

    if ![file exists $input] {
        return -code error "APSElegantInterpolateResonances: not found: $input"
    }
    
    if [catch {exec sddsfindresonances $input $output -multipoles=all=$order -type=normal,skew -variables=[join $planeList ,]} result] {
        return -code error "APSElegantInterpolateResonances: $result"
    }
}

proc APSElegantFrequencyMapDeltaPP {args} {
    set rootname ""
    set statusCallback APSNoOp
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg

    if $noPlots {
        return
    }
    if $errors(on) {
	return [APSElegantFrequencyMapDeltaErrorsPP \
		    -rootname $rootname -statusCallback $statusCallback \
		    -makePngFiles $makePngFiles -noPlots $noPlots]
    }
    set valueList [APSQueryValuesDialog -name "FMA delta Plot for $rootname" \
                     -nameList [list "Resonance diagram order" "Minimum nux" \
                                  "Maximum nux" "Minimum nuy" "Maximum nuy" \
                                  "Point size spatial" "Point size tune" "Filename on plot?" \
                                  "Show resonances?" "Sigma normalize?" \
                                  "Emittance coupling?" "Make PNG?" "Make EPS?"] \
                     -defaultList [list 4 -0.05 1.05 -0.05 1.05 2.0 0.25 1 0 0 0.1 $makePngFiles 0] \
                     -elementList [list order nux0 nux1 nuy0 nuy1 pointSizeSpatial pointSizeTune \
                                     filenameTitle showResonances sigmaNorm \
                                     emittanceCoupling makePngFiles makeEpsFiles] \
                     -typeList [list integer real real real real real real yesNo yesNo yesNo real yesNo yesNo]]
    if ![llength $valueList] return
    array set parameter $valueList
    catch {exec sddsresdiag $rootname.resdiag -order=$parameter(order)}
    
    set plane [string tolower $frequencyMapDelta(plane)]
    
    set title1 "Color indicates initial $plane amplitude"
    set title2 "Color indicates initial delta amplitude"
    set topline ""
    if $parameter(filenameTitle) {
        set topline "[ExpandFilename $rootname.fma]"
    }
    
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.0 $tmpRoot.1
    
    exec sddsexpand ${rootname}.var -pipe=out \
      | sddsconvert -pipe=in $tmpRoot.0 -rename=parameter,delta=deltaP 
    set maxStep [lindex [lsort -integer [exec sdds2stream -par=Step $rootname.fma ]] end]
    
    set fileList ""
    for {set step 1} {$step<=$maxStep} {incr step} {
        exec sddsprocess $rootname.fma -pipe=out -filter=par,Step,$step,$step -nowarning \
          | sddsxref $tmpRoot.0 -pipe -leave=* -transfer=parameter,deltaP -nowarnings \
          | sddsprocess -pipe -nowarning -redefine=column,delta,deltaP,symbol=\$gd\$r \
          | sddscombine -pipe=in $tmpRoot.fmad.$step -overwrite -merge
        if $maxStep>1 {
            set topline "Step $step n    [ExpandFilename $rootname]"
            set suffix -Step$step
        }  else {
            set suffix ""
        }
        lappend fileList $tmpRoot.fmad.$step
        lappend stepList $step
        foreach type [list $plane delta] symbol {xy delta} title [list $title1 $title2] {
            lappend plot$type "-limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto"
            lappend plot$type "-column=nux,nuy $rootname.resdiag "
            lappend plot$type "-column=nux,nuy $tmpRoot.fmad.$step"
            lappend plot$type \"-topline=$topline\"
            lappend plot$type "-graph=symbol,type=2,fill,scale=$parameter(pointSizeTune),vary=subtype -order=spect" 
            lappend plot$type \"-title=$title\" 
            lappend plot$type "-split=column=$type,start=$frequencyMapDelta(${symbol}Minimum),width=[expr ($frequencyMapDelta(${symbol}Maximum)-$frequencyMapDelta(${symbol}Minimum))/101.0] -end"
        }
        
        if $parameter(makePngFiles) {
            exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname-fma1$suffix.png \
              "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $tmpRoot.fmad.$step \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title1" \
              -split=column=$plane,start=$frequencyMapDelta(xyMinimum),width=[expr ($frequencyMapDelta(xyMaximum)-$frequencyMapDelta(xyMinimum))/101.0] 
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma1$suffix.png"}
            }
            exec sddsplot -device=png,onwhite -thickness=2 -output=$rootname-fma2$suffix.png \
              "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $tmpRoot.fmad.$step \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title2" \
              -split=column=delta,start=$frequencyMapDelta(deltaMinimum),width=[expr ($frequencyMapDelta(deltaMaximum)-$frequencyMapDelta(deltaMinimum))/101.0] 
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma2$suffix.png"}
            }
        }
        if $parameter(makeEpsFiles) {
            exec sddsplot -device=ceps -thickness=2 -output=$rootname-fma1$suffix.eps \
              "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $tmpRoot.fmad.$step \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title1" \
              -split=column=$plane,start=$frequencyMapDelta(xyMinimum),width=[expr ($frequencyMapDelta(xyMaximum)-$frequencyMapDelta(xyMinimum))/101.0] 
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma1$suffix.eps"}
            }
            exec sddsplot -device=ceps -thickness=2 -output=$rootname-fma2$suffix.eps \
              "-topline=$topline" \
              -limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto \
              -column=nux,nuy $rootname.resdiag \
              -column=nux,nuy $tmpRoot.fmad.$step \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeTune)*1.33],vary=subtype \
              -order=spect \
              "-title=$title2" \
              -split=column=delta,start=$frequencyMapDelta(deltaMinimum),width=[expr ($frequencyMapDelta(deltaMaximum)-$frequencyMapDelta(deltaMinimum))/101.0] 
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma2$suffix.eps"}
            }
        }
    }
    APSAddToTmpFileList -ID elegant -fileList $fileList
    eval exec sddsplot [join [set plot$plane]] &
    eval exec sddsplot [join $plotdelta] &
    if [catch {eval exec sddscombine $fileList $rootname.fmad -overwrite} result] {
        return -code error $result
    }
    if $parameter(sigmaNorm) {
        if [catch {exec sddsprocess $rootname.twi -pipe=out \
                     -define=parameter,coupling,$parameter(emittanceCoupling) \
                     -process=*eta*,first,%s0 \
                     "-define=parameter,ey,ex0 coupling * coupling 1 + /" \
                     "-define=parameter,ex,ex0 coupling 1 + /" \
                     "-define=parameter,sigmax,betax0 ex * etax0 Sdelta0 * sqr + sqrt" \
                     "-define=parameter,sigmay,betay0 ey * sqrt" \
                     | sdds2stream -pipe -parameter=sigmax,sigmay,Sdelta0} result] {
            return -code error "$result"
        }
        if [string compare $plane x]==0 {
            set xfactor [expr 1./[lindex $result 0]]
            set xlabel {x/\$gs\$r}
        } else {
            set xfactor [expr 1./[lindex $result 1]]
            set xlabel {y/$gs$r}
        }
        set yfactor [expr 1./[lindex $result 2]]
        set ylabel {\$gd/s\$bd\$n\$r}
    } else {
        set xfactor 1.0
        set yfactor 1.0
        if [string compare $plane x]==0 {
            set xlabel "x (m)"
        } else {
            set xlabel "y (m)"
        }
        set ylabel {\$gd\$r}
    }
    set title1 "Color indicates x tune"
    set title2 "Color indicates y tune"

    set extraOpts1 ""
    set extraOpts2 ""
    if $maxStep==1 {
        set fileList $rootname.fmad
        set stepList 1
    }
    
    foreach file $fileList step $stepList {
        if $parameter(showResonances) {
            APSElegantInterpolateResonances -input $file -output ${file}-Res \
              -statusCallback $statusCallback -planeList [list $plane delta]
            set extraOpts1 "-pspace=0.15,0.75,0,0 -lspace=1.15,1.35,0,0.95"
            set extraOpts2 "-column=$plane,delta ${file}-Res -graph=sym,vary -legend=param=resonanceLabel -split=page"
        }
        if $maxStep>1 {
            set topline "Step $step   [ExpandFilename $rootname]"
            set suffix -Step$step
        } else {
            set suffix ""
        }
        foreach type {nux nuy} title [list $title1 $title2] {
            lappend plot$type "$extraOpts1"
            lappend plot$type "-factor=xmult=$xfactor,ymult=$yfactor "
            lappend plot$type \"-xlabel=$xlabel\"
            lappend plot$type \"-ylabel=$ylabel\"
            lappend plot$type "-column=$plane,delta $file"
            lappend plot$type \"-topline=$topline\"
            lappend plot$type "-graph=symbol,type=2,fill,scale=$parameter(pointSizeSpatial),vary=subtype -order=spect"
            lappend plot$type \"-title=$title\"
            lappend plot$type "-split=column=$type,width=0.0101"
            lappend plot$type "$extraOpts2"
            lappend plot$type "-end"
        }
        if $parameter(makePngFiles) {
            eval exec sddsplot $extraOpts1 -device=png,onwhite -thickness=2 -output=$rootname-fma3$suffix.png \
              -factor=xmult=$xfactor,ymult=$yfactor \
              {-xlabel=$xlabel} {-ylabel=$ylabel} \
              "{-topline=$topline}" \
              -column=$plane,delta $file \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeSpatial)*1.33],vary=subtype -order=spect \
              "{-title=$title1}" \
              -split=column=nux,width=0.0101 \
              $extraOpts2 
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma3$suffix.png"}
            }
            eval exec sddsplot $extraOpts1 -device=png,onwhite -thickness=2 -output=$rootname-fma4$suffix.png \
              -factor=xmult=$xfactor,ymult=$yfactor \
              {-xlabel=$xlabel} {-ylabel=$ylabel} \
              {"-topline=$topline"} \
              -column=$plane,delta $file \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeSpatial)*1.33],vary=subtype -order=spect \
              {"-title=$title2"} \
              -split=column=nuy,width=0.0101 \
              $extraOpts2 
            if [string length $statusCallback] {
                eval $statusCallback {"PNG file: $rootname-fma4$suffix.png"}
            }
        }
        if $parameter(makeEpsFiles) {
            eval exec sddsplot $extraOpts1 -device=ceps -thickness=2 -output=$rootname-fma3$suffix.eps \
              -factor=xmult=$xfactor,ymult=$yfactor \
              {-xlabel=$xlabel} {-ylabel=$ylabel} \
              "{-topline=$topline}" \
              -column=$plane,delta $file \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeSpatial)*1.33],vary=subtype -order=spect \
              "{-title=$title1}" \
              -split=column=nux,width=0.0101 \
              $extraOpts2 
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma3$suffix.eps"}
            }
            eval exec sddsplot $extraOpts1 -device=ceps -thickness=2 -output=$rootname-fma4$suffix.eps \
              -factor=xmult=$xfactor,ymult=$yfactor \
              {-xlabel=$xlabel} {-ylabel=$ylabel} \
              {"-topline=$topline"} \
              -column=$plane,delta $file \
              -graph=symbol,type=2,fill,scale=[expr $parameter(pointSizeSpatial)*1.33],vary=subtype -order=spect \
              {"-title=$title2"} \
              -split=column=nuy,width=0.0101 \
              $extraOpts2 
            if [string length $statusCallback] {
                eval $statusCallback {"EPS file: $rootname-fma4$suffix.eps"}
            }
        }
    }
    eval exec sddsplot [join $plotnux] &
    eval exec sddsplot [join $plotnuy] &
}

proc APSElegantFrequencyMapDeltaErrorsPP {args} {
    set rootname ""
    set statusCallback APSNoOp
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg
    
    if $noPlots {
        return
    }
    set valueList [APSQueryValuesDialog -name "FMA delta Plot for $rootname" \
                     -nameList [list "Resonance diagram order" "Minimum nux" \
                                  "Maximum nux" "Minimum nuy" "Maximum nuy" \
                                  "Point size spatial" "Point size tune" "Filename on plot?" \
                                  "Make PNG?" "Make EPS?"] \
                     -defaultList [list 4 -0.05 1.05 -0.05 1.05 2.0 0.25 1 $makePngFiles 0] \
                     -elementList [list order nux0 nux1 nuy0 nuy1 pointSizeSpatial pointSizeTune \
                                     filenameTitle \
                                     makePngFiles makeEpsFiles] \
                     -typeList [list integer real real real real real real yesNo yesNo yesNo]]
    if ![llength $valueList] return
    array set parameter $valueList
    catch {exec sddsresdiag $rootname.resdiag -order=$parameter(order)}
    
    set plane [string tolower $frequencyMapDelta(plane)]
    
    set title1 "Color indicates initial $plane amplitude"
    set title2 "Color indicates initial delta amplitude"
    set topline ""
    if $parameter(filenameTitle) {
        set topline "[ExpandFilename $rootname.fma]"
    }
    
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.0 $tmpRoot.1
    
    set plane [string tolower $frequencyMapDelta(plane)]

    catch {exec sddsresdiag $rootname.resdiag -order=$parameter(order)}

    # Tune diagram plots: (nux, nuy) colored by x/y or delta amplitude
    set title "Color indicates initial $plane amplitude"
    set topLine [ExpandFilename $rootname.fma]
    lappend plotOpt "-limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto"
    set topline "$plane amplitude   [ExpandFilename $rootname.fma]"
    lappend plotOpt "-column=nux,nuy $rootname.resdiag -omnipresent"
    lappend plotOpt "-column=nux,nuy $rootname.fma"
    if $parameter(filenameTitle) {
	lappend plotOpt \"-topline=$topline\"
    }
    lappend plotOpt "-graph=symbol,type=2,fill,scale=$parameter(pointSizeTune),vary=subtype"
    lappend plotOpt "-order=spect -separate=page -groupby=page,request"
    lappend plotOpt \"-title=$title\"
    lappend plotOpt "-split=page,column=$plane,start=$frequencyMapDelta(xyMinimum),width=[expr ($frequencyMapDelta(xyMaximum)-$frequencyMapDelta(xyMinimum))/101.0] -end"
    
    eval exec sddsplot [join $plotOpt] &
    if $parameter(makePngFiles) {
	eval exec sddsplot -device=lpng,onwhite,template=${rootname}-fma1-%02ld.png -thick=2 -line=0,thick=2 [join $plotOpt] 
    }
    if $parameter(makeEpsFiles) {
	eval exec sddsplot -device=ceps -output=${rootname}-fma1.eps -thick=2 -line=0,thick=2 [join $plotOpt] 
    }

    # Tune diagram plots: (nux, nuy) colored by x/y or delta amplitude
    set title "Color indicates initial $plane amplitude"
    set topLine [ExpandFilename $rootname.fma]
    set plotOpt "-limit=xmin=$parameter(nux0),xmax=$parameter(nux1),ymin=$parameter(nuy0),ymax=$parameter(nuy1),auto"
    set topline "delta amplitude   [ExpandFilename $rootname.fma]"
    lappend plotOpt "-column=nux,nuy $rootname.resdiag -omnipresent"
    lappend plotOpt "-column=nux,nuy $rootname.fma"
    if $parameter(filenameTitle) {
	lappend plotOpt \"-topline=$topline\"
    }
    lappend plotOpt "-graph=symbol,type=2,fill,scale=$parameter(pointSizeTune),vary=subtype"
    lappend plotOpt "-order=spect -separate=page -groupby=page,request"
    lappend plotOpt \"-title=$title\"
    lappend plotOpt "-split=page,column=delta,start=$frequencyMapDelta(deltaMinimum),width=[expr ($frequencyMapDelta(deltaMaximum)-$frequencyMapDelta(deltaMinimum))/101.0] -end"
    
    eval exec sddsplot [join $plotOpt] &
    if $parameter(makePngFiles) {
	eval exec sddsplot -device=lpng,onwhite,template=${rootname}-fma2-%02ld.png -thick=2 -line=0,thick=2 [join $plotOpt] 
    }
    if $parameter(makeEpsFiles) {
	eval exec sddsplot -device=ceps -output=${rootname}-fma2.eps -thick=2 -line=0,thick=2 [join $plotOpt] 
    }

    # Plots of tune maps vs (x/y, delta)

    set xmin [expr $frequencyMapDelta(xyMinimum)<0 ? 1.05*$frequencyMapDelta(xyMinimum) : 0]
    set xmax [expr 1.05*$frequencyMapDelta(xyMaximum)]
    set ymin [expr $frequencyMapDelta(deltaMinimum)<0 ? 1.05*$frequencyMapDelta(deltaMinimum) : 0]
    set ymax [expr 1.05*$frequencyMapDelta(deltaMaximum)]

    set title1 "Color indicates x tune"

    set extraOpts1 "-filter=column,nux,$parameter(nux0),$parameter(nuy1) -filter=column,nuy,$parameter(nuy0),$parameter(nuy1)"
    set plotCmd "-groupby=page,request -sep=page "

    lappend plotCmd "-limit=xmin=$xmin,xmax=$xmax,ymin=$ymin,ymax=$ymax"
    lappend plotCmd "-column=$plane,delta $rootname.fma -graph=symbol,type=2,fill,scale=$parameter(pointSizeSpatial),vary=subtype -order=spect"
    if $parameter(filenameTitle) {
	lappend plotCmd \"-topline=$topline\"
    }
    lappend plotCmd \"-title=$title1\"
    lappend plotCmd "-split=column=nux,page "
    lappend plotCmd "$extraOpts1" 
    lappend plotCmd -end 

    eval exec sddsplot [join $plotCmd] &
    if $parameter(makePngFiles) {
        eval exec sddsplot -device=lpng,onwhite,template=$rootname-fma3-%02ld.png -thickness=2 [join $plotCmd]
    }
    if $parameter(makeEpsFiles) {
        eval exec sddsplot -device=ceps -output=$rootname-fma3.eps -thickness=2 [join $plotCmd]
    }

    regsub -all {nux} $plotCmd "nuy" plotCmd1
    regsub -all {x tune} $plotCmd1 "y tune" plotCmd
    eval exec sddsplot [join $plotCmd] &
    if $parameter(makePngFiles) {
        eval exec sddsplot -device=lpng,onwhite,template=$rootname-fma4-%02ld.png -thickness=2 [join $plotCmd]
    }
    if $parameter(makeEpsFiles) {
        eval exec sddsplot -device=ceps -output=$rootname-fma4.eps -thickness=2 [join $plotCmd]
    }

}

proc APSElegantMomentumAperture {args} {
    set sourceDir ""
    set forceOccurence 0
    set momentum 7e3
    set matrixLatticeFile ""
    set mainDirectory ""
    set mainPrefix ""
    set kickOffsetElement ""
    set matrixLatticeFile ""
    set kickLatticeFile "" 
    set matrixBeamline ""
    set kickBeamline ""
    set matrixOffsetElement ""
    set kickOffsetElement ""
    set gridEngine no
    set makePngFiles 0
    set statusCallback ""
    set noPlots 0
    set processOnly 0
    APSStrictParseArguments {sourceDir forceOccurence  momentum matrixLatticeFile \
                               kickLatticeFile \
                               mainDirectory mainPrefix kickOffsetElement matrixLatticeFile \
                               matrixBeamline kickBeamline matrixOffsetElement \
                               gridEngine makePngFiles statusCallback noPlots processOnly}
    
    global mainParameterFile momentumAperture basicComputations
    global errors correction
    set tag MomentumAperture

    set rootname $mainDirectory/${mainPrefix}${tag}$momentumAperture(userSuffix)
    if $processOnly {
	source ${rootname}.runCfg
    }

    if ![file exists $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi] {
        if [string length $statusCallback] {
            eval $statusCallback {"Error: please perform Basic run in order to proceed."}
        }
        return -code error "Error: please perform Basic run in order to proceed."
    }

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList  $tmpRoot.0
    exec sddsconvert $mainDirectory/${mainPrefix}Basic$basicComputations(userSuffix).twi -pipe=out -topage=1 \
      | sddsprocess -pipe=in $tmpRoot.0 -nowarning \
      -filter=column,s,[expr $momentumAperture(sStart)-1e-6],[expr $momentumAperture(sEnd)+1e-6] \
      -match=column,ElementName=$momentumAperture(pattern),ElementType=$momentumAperture(typePattern),&
    set nElements [exec sdds2stream -rows=bare $tmpRoot.0]
    if $nElements==0 {
        return -code error "Error: no elements selected for tracking."
    }
    if $nElements<$momentumAperture(numberOfJobs) {
        set jobs $nElements
        set elementsPerJob 1
    } else {
        set elementsPerJob [expr ($nElements*1.0)/$momentumAperture(numberOfJobs)]
        set jobs $momentumAperture(numberOfJobs)
    }

    if !$processOnly {
	APSElegantSaveJobConfiguration -filename ${rootname}.runCfg \
	    -statusCallback $statusCallback -momentum $momentum \
	    -matrixLatticeFile  $matrixLatticeFile -matrixBeamline $matrixBeamline \
	    -matrixOffsetElement $matrixOffsetElement -kickLatticeFile $kickLatticeFile \
	    -kickBeamline $kickBeamline -kickOffsetElement $kickOffsetElement \
	    -forceOccurence $forceOccurence -mainDirectory $mainDirectory \
	    -mainPrefix $mainPrefix -gridEngine $gridEngine -makePngFiles $makePngFiles
    }

    set parameterFileList [APSElegantGetParameterFileList]
    set order 3
    set template $sourceDir/MomentumApertureTemplate.ele

    lappend origList <apertureFileDisable>
    if [string length $momentumAperture(apertureFile)]==0 {
        set momentumAperture(apertureFile) "\" \""
        set resetApertureFileString 1
        lappend replList 1
    } else {
        set resetApertureFileString 0
        lappend replList 0
    }
    foreach item [array names momentumAperture] {
        lappend origList <$item>
        lappend replList [set momentumAperture($item)]
    }
    #lappend origList <suffix>
    #lappend replList $momentumAperture(userSuffix)

    foreach item [list order momentum mainDirectory mainPrefix matrixLatticeFile kickLatticeFile parameterFileList matrixBeamline kickBeamline matrixOffsetElement kickOffsetElement forceOccurence] {
        lappend origList <$item>
        lappend replList [set $item]
    }
    if $resetApertureFileString {
        set momentumAperture(apertureFile) ""
    }

    if $errors(on) {
        foreach name [array names errors] {
            if {$name=="on"} {
                continue
            }
            lappend origList <$name>
            lappend replList $errors($name)
        }
        set tmpDir [file dir $template]
        if !$errors(maskTable) {
            lappend origList <ERROR>
            lappend replList $tmpDir/ErrorsTemplate.ele
        }
        if [string length $errors(errorInputFile)] {
            set origList [concat [list <ERRORPARAM>] $origList]
            set replList [concat [list $tmpDir/ErrorParametersTemplate.ele] $replList]
        }
    } else {
        lappend origList <numberOfSeeds>
        lappend replList 1
        lappend origList <seed>
        lappend replList $errors(seed)
    }
    foreach name [array names correction] {
	lappend origList <$name>
	lappend replList $correction($name)
    }
    set suffix0 $momentumAperture(userSuffix)
    set elementsToSkip 0
    for {set job 0} {$job<$jobs} {incr job} {
        set elementsToProcess [expr int(($job+1)*$elementsPerJob+0.5) - int($job*$elementsPerJob+0.5)]
        set origList1 $origList
        set replList1 $replList
        set suffix ${suffix0}-[format %03d $job]
        foreach item {elementsToSkip elementsToProcess suffix} {
            lappend origList1 <$item>
            lappend replList1 [set $item]
        }

        set eleFile ${rootname}-[format %03d $job].ele
	if !$processOnly {
	    exec replaceText $template $eleFile \
		-original=[join $origList1 ,] -replacement=[join $replList1 ,]
	    eval $statusCallback {"$eleFile: $elementsToProcess points"}
	}
        lappend eleFileList $eleFile
        set elementsToSkip [expr $elementsToSkip+$elementsToProcess]
    }

    
    APSElegantPerformRuns \
      -eleFileList $eleFileList \
      -suffix $momentumAperture(userSuffix) \
      -copyList [list done mag] -combineList [list clo twi ele ele.log mmap orb scor cor] \
      -tag MomentumAperture \
      -postProcessProc APSElegantMomentumAperturePP \
      -mainDirectory $mainDirectory -mainPrefix $mainPrefix \
      -matrixLatticeFile $matrixLatticeFile -kickLatticeFile $kickLatticeFile \
      -matrixBeamline $matrixBeamline -kickBeamline $kickBeamline \
      -matrixOffsetElement $matrixOffsetElement -kickOffsetElement $kickOffsetElement \
      -sourceDir $sourceDir -statusCallback $statusCallback \
      -gridEngine $gridEngine -makePngFiles $makePngFiles -noPlots $noPlots -processOnly $processOnly \
      -processorsPerJob $momentumAperture(nCores)

}

proc APSElegantMomentumAperturePP {args} {
    set rootname ""
    set statusCallback ""
    set makePngFiles 0
    set noPlots 0
    APSStrictParseArguments {rootname statusCallback makePngFiles noPlots}
    source $rootname.runCfg

    set maxStep [lindex [lsort -integer [exec sdds2stream $rootname.mmap -par=Step]] end]
    set tmpRoot /tmp/[APSTmpString]
    if {![file exists $rootname.mmaps] || [file mtime $rootname.mmap]>[file mtime $rootname.mmaps]} {
	exec sddssort $rootname.mmap -pipe=out -parameter=Step \
	    | sddscombine -pipe -merge=Step \
	    | sddssort -pipe -column=s \
	    | sddsprocess -pipe=in $rootname.mmaps "-print=parameter,StepLabel,Step %ld,Step"
    }
    if {$maxStep>1} {
	set topline @StepLabel
    } else {
	set topline [ExpandFilename $rootname]
    }
    lappend plotCmd "-column=s,deltaNegative -column=s,deltaPositive $rootname.mmaps -groupby=page -separate=page -same=global -split=page"
    lappend plotCmd \"-topline=$topline\"
    lappend plotCmd "-column=s,Profile ${rootname}.mag -overlay=xmode=norm,yfact=0.04 -omnipresent"
    if $makePngFiles {
	exec sddsplot -thick=2 -device=png,onwhite,template=$rootname-%03ld.png $plotCmd &
	if [string length $statusCallback] {
	    eval $statusCallback {"PNG file: ${rootname}-*.png"}
        }
    }
    eval exec sddsplot [join $plotCmd] &

    if {$maxStep>1} {
	exec sddsprocess $rootname.mmaps -pipe=out "-redefine=column,deltaNegative,deltaNegative -1 *" \
	    | sddsenvelope -pipe \
	    -copy=s -median=delta????tive -min=delta????tive -max=delta????tive -perc=10,delta????tive -perc=90,delta????tive \
	    | sddsprocess -pipe=in $rootname.mmaps.env "-redefine=column,%s,%s -1 *,select=deltaNegative*"
	set plotCmd -graph=line,vary,fixforrequest 
	foreach type {10Percentile Min Median Max 90Percentile} {
	    lappend plotCmd -column=s,deltaNegative$type -col=s,deltaPositive$type $rootname.mmaps.env -legend=spec=$type {-ylabel=Momentum Acceptance}
	}
	lappend plotCmd -column=s,Profile ${rootname}.mag -overlay=xmode=norm,yfact=0.04
	if $makePngFiles {
	    eval exec sddsplot -thick=2 -device=png,onwhite,template=$rootname-env.png -topline=[ExpandFilename $rootname] $plotCmd &
	}
	if [string length $statusCallback] {
	    eval $statusCallback {"PNG file: ${rootname}-env.png"}
        }
	eval exec sddsplot -topline=[ExpandFilename $rootname] $plotCmd &
    }
}


proc APSElegantAbortRun {args} {
    set postProcessProc ""
    set statusCallback ""
    set rootname ""
    APSStrictParseArguments {postProcessProc statusCallback rootname}
    global apsAbortElegantRun apsElegantRunRootList apsElegantRunPIDList apsAbortSelection
    
    if ![string length $postProcessProc] {
        return -code error "Process did not provided for APSElegantAbortRun."
    }
    set rootList [set apsElegantRunRootList($postProcessProc)]
    foreach root $rootList {
        if [file exist $root.done] {
            set id [lsearch $rootList $root]
            set rootList [lreplace $rootList $id $id]
        }
    }
    if [winfo exist .scroll$postProcessProc] {
        return 0
    }
    set apsAbortElegantRun($postProcessProc) 0
    set apsAbortSelection($postProcessProc) ""
    APSScrolledListWindow .scroll$postProcessProc -itemList $rootList -selectionVar apsAbortSelection($postProcessProc) \
      -acceptButton 0
    tkwait window .scroll$postProcessProc
    set selectionList [set apsAbortSelection($postProcessProc)]
    if ![string length $selectionList] {
        return -code error "Nothing selected for aborting."
    }
    
    set aborted 0
    foreach root $selectionList {
        if ![info exist apsAbortElegantRun($postProcessProc.$root)] {
            set apsAbortElegantRun($postProcessProc.$root) 0
        }
        if [APSYesNoPopUp "Are you sure to abort $root?"] {
            catch {eval exec cdel [set apsElegantRunPIDList($postProcessProc.$root)]} result
            if [string length $statusCallback] {
                eval $statusCallback {"$root was aborted: $result"}
            }
            #set fileList [glob -nocomplain ${root}*]
            file delete -force $root.done
            set fileList [glob -nocomplain ${root}-*]
            catch {eval file delete -force $fileList} result
            set id [lsearch $rootList $root]
            set rootList [lreplace $rootList $id $id]
            set apsAbortElegantRun($postProcessProc.$root) 1
            incr aborted
        }
    }
    set apsElegantRunRootList($postProcessProc) $rootList
    
    return $aborted
}

proc APSElegantAddNewProcess {args} {
    set postProcessProc ""
    set rootname ""
    set pidList ""
    APSStrictParseArguments {postProcessProc rootname pidList}

    global apsAbortElegantRun apsElegantRunRootList apsElegantRunPIDList apsAbortSelection
    if ![string length $postProcessProc] {
        return
    }
    
    global apsAbortElegantRun apsElegantRunRootList apsElegantRunPIDList 
    if ![info exist apsAbortElegantRun($postProcessProc)] {
        set apsAbortElegantRun($postProcessProc) 0
    }
    if ![info exist apsElegantRunRootList($postProcessProc)] {
        set apsElegantRunRootList($postProcessProc) ""
    }
    set id [lsearch [set apsElegantRunRootList($postProcessProc)] $rootname]
    if {$id<0} {
        lappend apsElegantRunRootList($postProcessProc) $rootname
    }
    set apsElegantRunPIDList($postProcessProc.$rootname) $pidList
    set apsAbortElegantRun($postProcessProc.$rootname) 0
    return
}

proc ExpandFilename {filename} {
    set dirname [file dir $filename]
    set file0   [file tail $filename]
    if [string compare $dirname .]==0 {
        set dirname [pwd]
    }
    return [file join $dirname $file0]
}
