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

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]

if [info exists env(LOCO_BINDIR)] {
    set locoBinDir $env(LOCO_BINDIR)
} else {
    puts stderr "Error: LOCO_BINDIR environment variable is not defined"
    exit
}

source $locoBinDir/locoCommonProcedures

set acceleratorCode elegant

set usage "calculateTwissCorrection -mode <correct|scan|plot|calcEmit|minEmit|runDqsTask> ..."
set args $argv

set argMode commandString
set scriptParametersFile ""
set verbose 0
APSParseArguments {argMode scriptParametersFile verbose}
if [string length $scriptParametersFile] {
    if {![string length $scriptParametersFile]} {
	puts stderr "Arguments: $argv"
	puts stderr $usage
	exit
    } else {
	if [catch {open $scriptParametersFile r} fid] {
	    return -code error "$fid"
	} else {
	    gets $fid args
	    close $fid
	}
    }
}

set mode ""
APSParseArguments {mode}
if ![string length $mode] {
    puts stderr "Arguments: $argv"
    puts stderr $usage
    exit
}

switch -exact -- $mode {
    correct {
	set requiredArgList [list calcMode lteMeasured beamlineMeasured lteDesired beamlineDesired \
				 outputFile elementListFile splitTasks workDir \
				 useTunes useDQS weightList calculateMatrix calculateInverse useRelative \
				 useInvSolution locoResultFile SVratio corFraction iterations \
				 abortFile useMeasDisp measDispFile matrixFile]
    }
    scan {
	set requiredArgList [list calcMode lteMeasured beamlineMeasured lteDesired beamlineDesired workDir \
				 outputFile elementListFile weightList calculateMatrix useRelative \
				 SVstart SVend SVsteps matrixFile corFraction useDQS splitTasks iterations useTunes \
				 useMeasDisp measDispFile abortFile]
    }
    plot {
	set requiredArgList [list calcMode lteMeasured beamlineMeasured lteDesired beamlineDesired paramFileListAchieved \
				 weightList doneFile workDir twiMeasured twiDesired twiAchieved elementListFile \
				 useTunes useRelative]
    }
    minEmit {
	set requiredArgList [list calcMode workDir lteMeasured beamlineMeasured elementListFile emitArrayList optimTerm rootname]
    }
    calcEmit {
	set requiredArgList [list calcMode workDir lteMeasured beamlineMeasured lteDesired \
				 beamlineDesired emitArrayList]
    }
    runDqsTask {
	set requiredArgList [list calcMode path eleTemplate varList useRelative acceleratorCode]
    }
    default {
	puts stdout $usage
	exit
    }
}

foreach var $requiredArgList {set $var ""}
APSParseArguments $requiredArgList
set missingVarList ""
foreach var $requiredArgList {
    if ![string length [set $var]] { lappend missingVarList $var }
}
if [llength $missingVarList] {
    puts stderr "Arguments: $argv"
    puts stderr "The following variables are missing: $missingVarList"
    exit
}

#------ Not required variables:
set paramFileListMeasured ""
set paramFileListDesired ""
set paramFileListAchieved ""
set tmpDir /tmp
set betaTargetFile ""
set optimTerm1 ""
APSParseArguments {paramFileListMeasured paramFileListDesired paramFileListAchieved tmpDir betaTargetFile optimTerm1}

set outputStatusDevice stdout

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

proc ReadListFromFile { args } {
    APSParseArguments {calcMode listFile}
    set mainList ""
    if {[string compare $calcMode beta] == 0} {
	set paramList [list Quad xBpm yBpm dBpm]
    } else {
	set paramList [list Quad hCorr vCorr xBpm yBpm dBpm]
    }
    foreach param $paramList {
	lappend mainList [join [exec sddsprocess $listFile -pipe=out -match=para,ListName=$param -nowarning \
				    | sdds2stream -pipe=in -col=List] ]
    }
    return $mainList
}

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

proc TwissCorrection { args } {
    
    global workDir tmpDir outputStatusDevice outputStatusFile
    global measuredFiles achievedFiles desiredFiles
    global matrixFile matrixFileFiltered inverseMatrixFile measDifference
    global eleMatrixTemplate elementsUpdateFile measuredBpms measuredDispFile
    global xbpmList ybpmList dbpmList weightList
    global twissVectorDesired

    set adjustVectorValues 0
    APSParseArguments { calcMode lteMeasured beamlineMeasured paramFileListMeasured lteDesired beamlineDesired paramFileListDesired \
			    outputFile quadList xbpmList ybpmList dbpmList hcorrList vcorrList splitTasks useTunes useDQS \
			    weightList calculateMatrix calculateInverse useRelative useInvSolution locoResultFile \
			    SVratio corFraction iterations outputStatusDevice outputStatusFile abortFile \
			    useMeasDisp measDispFile matrixFile adjustVectorValues}
    
    set deleteFiles ""
    OutputStatusMessage "Calculations started..."

    if [catch {InitialPreparations -quadList $quadList -lteMeasured $lteMeasured -beamlineMeasured $beamlineMeasured \
		   -paramFileListMeasured $paramFileListMeasured -lteDesired $lteDesired -useTunes $useTunes \
		   -beamlineDesired $beamlineDesired -paramFileListDesired $paramFileListDesired \
		   -hcorrList $hcorrList -vcorrList $vcorrList} result] {
	return -code error "InitialPreparations: $result"
    }

    #--- Calculate initial twiss vectors...
    OutputStatusMessage "Calculating initial vectors..."
    if [catch {BuildMeasurementVector -calcMode $calcMode -eleFile $desiredFiles(ele) -twissFile $desiredFiles(twiss) \
		   -hyFile $desiredFiles(hyrm) -vxFile $desiredFiles(vxrm)} measVectorDesired] {
	return -code error "BuildMeasurementVector (desired): $measVectorDesired"
    }
    if $adjustVectorValues {
	if [catch {AdjustVectorValues -vectorFile $measVectorDesired} result] {
	    return -code error "AdjustVectorValues: $result"
	}
    }
    if $useMeasDisp {
	if [catch {BuildMeasurementVector -calcMode $calcMode -eleFile $measuredFiles(ele) -dispFile $measDispFile \
		       -twissFile $measuredFiles(twiss) -hyFile $measuredFiles(hyrm) \
		       -vxFile $measuredFiles(vxrm)} measVectorMeasured] {
	    return -code error "BuildMeasurementVector: $measVectorMeasured"
	}
    } else {
	if [catch {BuildMeasurementVector -calcMode $calcMode -eleFile $measuredFiles(ele) -twissFile $measuredFiles(twiss) \
		       -hyFile $measuredFiles(hyrm) -vxFile $measuredFiles(vxrm)} measVectorMeasured] {
	    return -code error "BuildMeasurementVector (measured): $measVectorMeasured"
	}
    }
    set nameColumn Rootname
    set dataColumn Measurement
    if [catch {CalculateVectorDifference -vectorFile1 $measVectorDesired -vectorFile2 $measVectorMeasured \
		   -outputFile $measDifference -useRelative $useRelative -nameColumn $nameColumn -dataColumn $dataColumn} result ] {
	return -code error "CalculateVectorDifference: $result"
    }

    if [catch {rmsDisplayOutput -calcMode $calcMode -iteration -1 -diffFile $measDifference -twissFile $measuredFiles(twiss) \
		   -weightList $weightList -dataColumn MeasurementDiff} rmsList] {
	return -code error "rmsDisplayOutput: $rmsList"
    }
    set rmsTotal0 [lindex $rmsList 0]
    set tol [expr $rmsTotal0 / 10000]
    
    if !$useInvSolution {
	if $calculateMatrix {
	    OutputStatusMessage "Doing the twiss response matrix..."
	    if [catch {CalculateTwissResponseMatrix -calcMode $calcMode -matrixFile $matrixFile \
			   -quadList $quadList -useRelative $useRelative -splitTasks $splitTasks -useQsub $useDQS \
			   -abortFile $abortFile} result] {
		return -code error "CalculateTwissResponseMatrix: $result"
	    }
	}
	if $calculateInverse {
	    OutputStatusMessage "Doing the sddspseudoinverse..."
	    if [catch {CalculateInverse -matrixFile $matrixFile -matrixFileFiltered $matrixFileFiltered \
			   -inverseMatrixFile $inverseMatrixFile -SVratio $SVratio -quadList $quadList \
			   -diffFile $measDifference} result] {
		return -code error "CalculateInverse: $result"
	    }
	}
    }

    set tmpFile /tmp/[APSTmpString]-twissCorr
    set vectorFile $workDir/vector_out
    lappend deleteFiles $tmpFile $vectorFile $measVectorDesired $measVectorMeasured

#--- Main Iterations -------------------------------------------------------------------------------------
    
    if $useInvSolution {set iterations 1}
    set rmsTotalPrev $rmsTotal0
    for {set I 0} {$I < $iterations} {incr I} {
	
	if !$useInvSolution {
	    exec sddscombine $measDifference -pipe=out -merge \
		| sddsmatrixmult -pipe=in $inverseMatrixFile $vectorFile -commute
	}

	#--- Updating the elements_update file after the iteration...
	if !$useInvSolution {
	    exec sddsxref $elementsUpdateFile $vectorFile -pipe=out -take=MeasurementDiff \
		| sddsprocess -pipe "-redefine=col,ParameterValue,ParameterValue MeasurementDiff $corFraction * + " \
		| sddsconvert -pipe=in $tmpFile -delete=column,MeasurementDiff
	    file copy -force $tmpFile $elementsUpdateFile
	} else {
	    if [catch {exec sddscombine $locoResultFile -pipe=out -merge \
			   | sddsprocess -pipe "-match=col,ElementParameter=K1,ElementParameter=KNL,|" -nowarning \
			   | sddsprocess -pipe=in $elementsUpdateFile \
			   "-redef=col,ParameterValue,ParameterValue -1 *"} result] {
		return -code error "Error updating: $result"
	    }
	}

	#--- Create twissVector after the iteration...
	if [catch {BuildMeasurementVector -calcMode $calcMode -eleFile $achievedFiles(ele) -twissFile $achievedFiles(twiss) \
		       -hyFile $achievedFiles(hyrm) -vxFile $achievedFiles(vxrm)} measVectorAfterIter] {
	    eval file delete $deleteFiles
	    return -code error "BuildMeasurementVector: $measVectorAfterIter"
	}
	if [catch {CalculateVectorDifference -vectorFile1 $measVectorDesired -vectorFile2 $measVectorAfterIter \
		       -outputFile $measDifference -useRelative $useRelative -nameColumn $nameColumn -dataColumn $dataColumn} result ] {
	    eval file delete $deleteFiles $measVectorAfterIter
	    return -code error "CalculateVectorDifference: $result"
	}
	if [catch {rmsDisplayOutput -calcMode $calcMode -iteration $I -diffFile $measDifference -twissFile $achievedFiles(twiss) \
		       -weightList $weightList -dataColumn MeasurementDiff} rmsList] {
	    return -code error "rmsDisplayOutput: $rmsList"
	}
	file delete $measVectorAfterIter
	
	if [file exists $abortFile] {
	    if [catch { StopExecution } result] {
		return -code error "TwissCorrection: $result"
	    }
	    eval file delete $deleteFiles $measVectorAfterIter
	    return -code error "Interrupted by user."
	}
	file copy -force $elementsUpdateFile $outputFile
	if {[expr abs($rmsTotalPrev - [lindex $rmsList 0])] < $tol} {
	    OutputStatusMessage "Iterations converged. Exiting."
	    break
	}
	set rmsTotalPrev [lindex $rmsList 0]
    }
    eval file delete $deleteFiles $measVectorAfterIter
    return $rmsList
}

#-------------------------------------------------------------------------------------------------------------------------
proc AdjustVectorValues {args} {
    global tmpDir betaTargetFile
    APSParseArguments {vectorFile}
    set tmpRoot $tmpDir/[APSTmpString]
    if [catch {exec sdds2stream $betaTargetFile -para=Plane} result] {
	return -code error "Error reading $betaTargetFile"
    } else {
	if {[llength $result] != 4} {
	    return -code error "Error: $betaTargetFile must be 4 pages long."
	}
    }
    exec sddsxref $vectorFile $betaTargetFile -pipe=out -take=TargetBeta -match=Rootname -nowarning -fillin \
	| sddsprocess -pipe "-redef=col,Measurement,TargetBeta 0 == ? Measurement : TargetBeta \$" \
	| sddsconvert -pipe=in $tmpRoot -del=col,TargetBeta
    file copy -force $tmpRoot $vectorFile
    file delete $tmpRoot
}
#-------------------------------------------------------------------------------------------------------------------------

proc InvertLOCOSolution { args } {
    global outputStatusDevice
    APSParseArguments { outputStatusDevice }
    global locoResultFile

    set locoResultsFile ""
    set dbwin [APSUniqueName .]
    APSDialogBox $dbwin -name "LOCO results file" -width 60 -contextHelp " " -cancelCommand {set locoResultFile ""}
    APSLabeledEntry .le1 -parent $dbwin.userFrame -width 60 \
	-label "LOCO result file:" \
	-textVariable locoResultFile \
	-contextHelp "Name of the file with quadrupoles calculated by LOCO."
    update
    tkwait window $dbwin
    if ![file exists $locoResultFile] {
	return -code error "Error: File $locoResultFile does not exist."
    }
    OutputStatusMessage "LOCO result file has been chosen."
    return $locoResultFile
}

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

proc InitialPreparations { args } {

    global workDir tmpDir calcMode
    global matrixFile matrixFileFiltered inverseMatrixFile measDifference
    global eleMatrixTemplate elementsUpdateFile measuredBpms
    global measuredFiles achievedFiles desiredFiles
    global xbpmList ybpmList dbpmList weightList calcMode correctorFile

    APSParseArguments {quadList lteMeasured beamlineMeasured paramFileListMeasured lteDesired beamlineDesired \
			    paramFileListDesired useTunes hcorrList vcorrList}

    set tmpRoot $tmpDir/[APSTmpString]-iniPrep
    catch {exec mkdir $workDir/tmp}
    # ----- Required internal files -----------------------
    set matrixFileFiltered $workDir/tmp/twissCorrectionMatrixFiltered.sdds
    set inverseMatrixFile  $workDir/tmp/twissCorrectionMatrixInverse.sdds
    set measDifference     $workDir/tmp/measDifference.sdds
    set eleMatrixTemplate  $workDir/tmp/twissCorrectionMatrixTemplate.ele
    set elementsUpdateFile $workDir/tmp/elements_update.sdds
    set measuredBpms       $workDir/tmp/measuredBpms.sdds
    
    set  desiredFiles(lte)       $lteDesired
    set  desiredFiles(beamline)  $beamlineDesired
    set  desiredFiles(paramList) $paramFileListDesired
    set  desiredFiles(ele)       $workDir/tmp/desired.ele
    set  desiredFiles(outParam)  $workDir/tmp/desired.param
    set  desiredFiles(twiss)     $workDir/tmp/desired.twi
    set  desiredFiles(hyrm)      $workDir/tmp/desired.hyrm
    set  desiredFiles(vxrm)      $workDir/tmp/desired.vxrm

    set measuredFiles(lte)       $lteMeasured
    set measuredFiles(beamline)  $beamlineMeasured
    set measuredFiles(paramList) $paramFileListMeasured
    set measuredFiles(ele)       $workDir/tmp/measured.ele
    set measuredFiles(outParam)  $workDir/tmp/measured.param
    set measuredFiles(twiss)     $workDir/tmp/measured.twi
    set measuredFiles(hyrm)      $workDir/tmp/measured.hyrm
    set measuredFiles(vxrm)      $workDir/tmp/measured.vxrm

    set achievedFiles(lte)       $lteMeasured
    set achievedFiles(beamline)  $beamlineMeasured
    set achievedFiles(paramList) [concat $paramFileListMeasured $elementsUpdateFile]
    set achievedFiles(ele)       $workDir/tmp/achieved.ele
    set achievedFiles(outParam)  $workDir/tmp/achieved.param
    set achievedFiles(twiss)     $workDir/tmp/achieved.twi
    set achievedFiles(hyrm)      $workDir/tmp/achieved.hyrm
    set achievedFiles(vxrm)      $workDir/tmp/achieved.vxrm

    #--- Create elements_update.sdds file for iterations...
    if [llength $quadList] {
	if [string match "coupling" $calcMode] {set elementParameter KNL} else {set elementParameter K1}
	if [catch {exec sddsmakedataset -pipe=out -col=ElementName,type=string -data=[join $quadList ,] \
		       | sddsprocess -pipe=in $elementsUpdateFile -print=col,ElementParameter,$elementParameter \
		       -print=col,ParameterMode,differential -def=col,ParameterValue,0} result] {
	    return -code error "Error making elementsUpdateFile: $result"
	}
    } else {
	return -code error "Error: List quadList has zero length."
    }
    
    #--- Create files with lists of bpms for later filtering...
    if $useTunes { set tuneList [list nux nuy] } else { set tuneList "" }
    set bpmList     [list $xbpmList $ybpmList $dbpmList $tuneList]
    set fileExtList [list xbpm ybpm dbpm nu]
    set planeList   [list X Y D Q]
    if {[string compare $calcMode beta] == 0} {
	set weightList1 $weightList
    } else {
	set weightList1 [list [lindex $weightList 0] [lindex $weightList 0] [lindex $weightList 1]]
    }
    foreach bpmList $bpmList fileExt $fileExtList plane $planeList weight $weightList1 {
	if [llength $bpmList] {
	    set dataOption "-data=[join $bpmList ,]"
	} else {
	    set dataOption "-data"
	}
	if [catch {exec sddsmakedataset -pipe=out -col=ElementName,type=string $dataOption \
		       | sddsprocess -nowarning -pipe=in $measuredBpms.$fileExt \
		       -print=para,Plane,$plane -def=para,Weight,$weight} result] {
	    return -code error "Error making measuredBpm file for plane $plane: $result"
	}
    }
    if {[string compare $calcMode coupling] == 0} {
	set correctorFile $workDir/correctors.param
	exec sddsmakedataset -pipe=out -col=ElementName,type=string -data=[join $hcorrList ,] \
	    | sddsprocess -pipe=in $tmpRoot.hcorr -print=col,ElementParameter,STEERING -def=col,ParameterValue,1
	exec sddsmakedataset -pipe=out -col=ElementName,type=string -data=[join $vcorrList ,] \
	    | sddsprocess -pipe=in $tmpRoot.vcorr -print=col,ElementParameter,STEERING -def=col,ParameterValue,1
	exec sddscombine $tmpRoot.hcorr $tmpRoot.vcorr $correctorFile -merge -overWrite
	file delete $tmpRoot.hcorr $tmpRoot.vcorr
    }

    #--- Create elegant files...
    foreach arrayName [list measuredFiles achievedFiles desiredFiles] {
	array set filesArray [array get $arrayName]
	switch $calcMode {
	    beta {
		if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $filesArray(ele) \
			       -run_setup [list "lattice $filesArray(lte) use_beamline $filesArray(beamline) parameters $filesArray(outParam) default_order 2"] \
			       -load_parameters [list "filename_list \"$filesArray(paramList)\""] \
			       -closed_orbit [list "fixed_length 0 output $filesArray(twiss).orb"] \
			       -twiss_output [list "filename $filesArray(twiss)"] \
			       -run_control [list "n_steps 1"] \
			       -bunched_beam [list "n_particles_per_bunch 1"] \
			   } result] {
		    return -code error "Fit_GenerateElegantFileFromLTE (ele file $filesArray(ele)): $result"
		}
	    }
	    coupling {
		if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $filesArray(ele) \
			       -run_setup [list "lattice $filesArray(lte) use_beamline $filesArray(beamline) parameters $filesArray(outParam)"] \
			       -load_parameters [list "filename_list \"$filesArray(paramList)\""] \
			       -alter_elements [list "name * type *KICK item STEERING value 0" "name * type *KQUAD item HSTEERING value 0" \
						    "name * type *BEN* item XSTEERING value 0 allow_missing_parameters 1"] \
			       -load_parameters2 [list "filename $correctorFile"] \
			       -twiss_output [list "filename $filesArray(twiss)"] \
			       -run_control [list "n_steps 1"] \
			       -correct [list "mode orbit method global n_xy_cycles 1 fixed_length 1"] \
			       -correction_matrix_output [list "response2 $filesArray(hyrm) response3 $filesArray(vxrm) coupled 1 fixed_length 1"] \
			       -bunched_beam [list "n_particles_per_bunch 1"] \
			   } result] {
		    return -code error "Fit_GenerateElegantFileFromLTE (ele file $filesArray(ele)): $result"
		}
	    }
	}
    }
}

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

proc BuildMeasurementVector {args} {
    set dispFile ""
    APSParseArguments {calcMode eleFile twissFile dispFile hyFile vxFile}
    switch $calcMode {
	beta {
	    if [catch {BuildTwissVector -eleFile $eleFile -twissFile $twissFile -dispFile $dispFile} outputFile] {
		return -code error "BuildTwissVector: $outputFile"
	    }
	}
	coupling {
	    if [catch {BuildRMVector -eleFile $eleFile -hyFile $hyFile -vxFile $vxFile -twissFile $twissFile} outputFile] {
		return -code error "BuildRMVector: $outputFile"
	    }
	}
    }
    return $outputFile
}

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

proc BuildRMVector {args} {
    # h and v stand for corrector plane, and x and y stand for bpm plane.
    APSParseArguments {eleFile hyFile vxFile twissFile}
    global tmpDir measuredBpms acceleratorCode weightList

    set deleteFiles ""
    set tmpRoot $tmpDir/[APSTmpString]-rmVector
    set outputFile $tmpRoot.out
    set elegantOutFile $tmpRoot.ele.log
    file delete $elegantOutFile
    lappend deleteFiles $elegantOutFile
    if [catch {exec $acceleratorCode $eleFile > $elegantOutFile} result] {
	return -code error "elegant (ele file: $eleFile; output file: $elegantOutFile): $result"
    }
    #--- Making one-column file from the RM:
    set fileList ""
    foreach filename [list $hyFile $vxFile] ext [list hyrm vxrm] bpmExt [list ybpm xbpm] {
	if [catch {exec sddsselect $filename $measuredBpms.$bpmExt -pipe=out -match=BPMName=ElementName \
		       | sddsxref -pipe $measuredBpms.$bpmExt -leave=* -transfer=para,Plane \
		       | sddsbreak -pipe -rowLimit=1 \
		       | sddsprocess -pipe -process=BPMName,first,BPMName \
		       | sddsconvert -pipe -del=col,BPMName,s \
		       | sddstranspose -pipe -oldColumnNames=Rootname -root=Measurement \
		       | sddsprocess -pipe -reprint=col,Rootname,%s%s,Rootname,BPMName -redef=para,Weight,[lindex $weightList 0] \
		       | sddscombine -pipe=in $tmpRoot.$ext -merge} result] {
	    return -code error "Error making one-column file (rm file: $filename; ext: $ext): $result"
	}
	lappend fileList $tmpRoot.$ext
	lappend deleteFiles $tmpRoot.$ext
    }
    #--- Add dispersion from twiss file 
    if [catch {exec sddsconvert $twissFile -pipe=out -retain=col,ElementName,etay \
		   | sddsselect -pipe $measuredBpms.dbpm -match=ElementName \
		   | sddsprocess -pipe -redef=para,Weight,[lindex $weightList 1] \
		   | sddsconvert -pipe=in $tmpRoot.etay -rename=col,etay=Measurement -rename=col,ElementName=Rootname} result] {
	return -code error "Error adding dispersion (twissFile: $twissFile): $result"
    }
    lappend fileList $tmpRoot.etay
    lappend deleteFiles $tmpRoot.etay
    eval exec sddscombine $fileList $outputFile
    eval file delete $deleteFiles
    return $outputFile
}

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

proc BuildTwissVector { args } {

    global tmpDir measuredBpms acceleratorCode
    set eleFile ""
    set dispFile ""
    APSStrictParseArguments {eleFile twissFile dispFile}
    
    set tmpRoot $tmpDir/[APSTmpString].twissVector
    set outputFile $tmpRoot.out
    set elegantOutFile $tmpRoot.ele.log

    file delete $elegantOutFile
    if [catch {exec $acceleratorCode $eleFile > $elegantOutFile} result] {
	return -code error "elegant (ele file: $eleFile; output file: $elegantOutFile): $result"
    } else {
	file delete $elegantOutFile
    }

    #--- Substituting etax column in twissFile with the measured dispersion.
    if [string length $dispFile] {
	exec sddsxref -nowarning $twissFile -pipe=out $dispFile -take=xDispersion -match=ElementName=Rootname \
	    | sddsselect -pipe $measuredBpms.dbpm -match=ElementName \
	    | sddsprocess -pipe "-redef=col,etax,xDispersion 1000.0 /,units=m" \
	    | sddsconvert -pipe=in $tmpRoot.twiss -del=col,xDispersion
	file copy -force $tmpRoot.twiss $twissFile
	file delete $tmpRoot.twiss
    }

    set fileList ""
    foreach fileExt [list xbpm ybpm dbpm] column [list betax betay etax] {
	exec sddsxref $measuredBpms.$fileExt $twissFile -pipe=out -take=$column -match=ElementName -nowarning \
	    | sddsconvert -pipe=in $tmpRoot.$fileExt -rename=col,$column=Measurement -rename=col,ElementName=Rootname 
	lappend fileList $tmpRoot.$fileExt
    }

    exec sddscollapse $twissFile -pipe=out \
	| sddsconvert -pipe -retain=col,nu? \
	| sddscollect -pipe=in $tmpRoot.tmp "-collect=match=nu*,col=Measurement,edit="
    set tuneList [exec sdds2stream $tmpRoot.tmp -col=Measurement]
    if {[string first "NaN" [lindex $tuneList 0]] > -1 || [string first "NaN" [lindex $tuneList ]] > -1} {
	file delete $tmpRoot.xbpm $tmpRoot.ybpm $tmpRoot.dbpm $tmpRoot.tmp
	return -code error "Error: Tunes are unstable!"
    }

    exec sddsxref $measuredBpms.nu $tmpRoot.tmp -pipe=out -take=Measurement -match=ElementName=Rootname -nowarning \
	| sddsconvert -pipe=in $tmpRoot.nu -rename=col,ElementName=Rootname
    lappend fileList $tmpRoot.nu
    
    eval exec sddscombine $fileList $outputFile -overWrite
    eval file delete $fileList $tmpRoot.tmp
    return $outputFile
}

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

proc CalculateVectorDifference {args} {
    APSStrictParseArguments {vectorFile1 vectorFile2 outputFile useRelative nameColumn dataColumn}
    if $useRelative {
	if [catch {exec sddsxref -nowarning $vectorFile1 $vectorFile2 -pipe=out -take=$dataColumn -rename=col,$dataColumn=${dataColumn}1 \
		       -match=$nameColumn \
		       | sddsprocess -nowarning -pipe \
		       "-def=col,${dataColumn}Diff,Plane \"D\" streq ? $dataColumn ${dataColumn}1 - Weight * : $dataColumn ${dataColumn}1 - ${dataColumn}1 / Weight * \$" \
		       -process=${dataColumn}Diff,standardDeviation,Rms \
		       | sddsconvert -pipe=in $outputFile -retain=col,${dataColumn}Diff,$nameColumn} result] {
	    return -code error "Error calculating difference: $result"
	}
    } else {
	if [catch {exec sddsxref -nowarning $vectorFile1 $vectorFile2 -pipe=out -take=$dataColumn -rename=col,$dataColumn=${dataColumn}1 \
		       -match=$nameColumn \
		       | sddsprocess -nowarning -pipe "-def=col,${dataColumn}Diff,$dataColumn ${dataColumn}1 - Weight *" \
		       -process=${dataColumn}Diff,standardDeviation,Rms \
		       | sddsconvert -pipe=in $outputFile -retain=col,${dataColumn}Diff,$nameColumn} result] {
	    return -code error "Error calculating difference: $result"
	}
    }
}

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

proc rmsDisplayOutput {args} {

    APSStrictParseArguments {calcMode iteration diffFile twissFile weightList dataColumn}
    
    if [catch {exec sddsprocess $diffFile -pipe=out "-redef=col,$dataColumn,$dataColumn Weight /" \
		   | sddscombine -pipe -merge \
		   | sddsprocess -pipe -process=$dataColumn,standardDeviation,rmsTotal \
		   | sdds2stream -pipe=in -para=rmsTotal} rmsTotal] {
	return -code error "Error calculating total rms (diffFile $diffFile): $rmsTotal"
    }
    set returnList $rmsTotal

    set rowList [join [exec sdds2stream $diffFile -rows=bare] ]
    set rmsList [join [exec sdds2stream $diffFile -parameter=Rms] ]
    if {[string compare $calcMode beta] == 0} {
	set calculatedTuneX [exec sdds2stream -para=nux $twissFile]
	set calculatedTuneY [exec sdds2stream -para=nuy $twissFile]
	if {[string first "NaN" $calculatedTuneX] > -1 || [string first "NaN" $calculatedTuneY] > -1 \
		||[string first "nan" $calculatedTuneX] > -1 || [string first "nan" $calculatedTuneY] > -1} {
	    return -code error "Error: Tunes are unstable!"
	}
	set TUNEX [format "%10.4f" $calculatedTuneX]
	set TUNEY [format "%10.4f" $calculatedTuneY]
    }
    switch $calcMode {
	beta {
	    foreach rms [list rmsX rmsY rmsD rmsN] index [list 0 1 2 3] {
		if [lindex $rowList $index] {
		    set scaledRms [expr [lindex $rmsList $index] / [lindex $weightList $index]]
		    set $rms [format "%7.4f" $scaledRms]
		    lappend returnList $scaledRms
		} else { 
		    set $rms NaN 
		}
	    }
	    set outputLine "Iteration $iteration. \nQx = $TUNEX,   Qy = $TUNEY \n"
	    append outputLine "RMS total: [format "%7.4f" $rmsTotal]; --> "
	    append outputLine "x: $rmsX; y: $rmsY; disp: $rmsD; nu: $rmsN"
	}
	coupling {
	    foreach rms [list rmsX rmsY rmsD] index [list 0 1 2] \
		weight [list [lindex $weightList 0] [lindex $weightList 0] [lindex $weightList 1]] {
		    if [lindex $rowList $index] {
			set scaledRms [expr [lindex $rmsList $index] / $weight]
			set $rms [format "%7.4f" $scaledRms]
			lappend returnList $scaledRms
		    } else { 
			set $rms NaN 
		    }
		}
	    set outputLine "Iteration $iteration.\n"
	    append outputLine "RMS total: [format "%7.4f" $rmsTotal]; --> "
	    append outputLine "x: $rmsX; y: $rmsY; disp: $rmsD"
	    
	}
    }
    OutputStatusMessage $outputLine
    return $returnList
}


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

proc CalculateInverse { args } {

    global tmpDir measuredBpms
    APSStrictParseArguments {matrixFile matrixFileFiltered inverseMatrixFile SVratio quadList diffFile}

    #--- Filter the twiss response matrix amd multiply with the weight.
    if ![llength $quadList] {
	return -code error "Error: quadList is zero length."
    }
    set takeColumnsOption [join $quadList ","]
    if [catch {exec sddsxref $diffFile $matrixFile -pipe=out -take=$takeColumnsOption -match=Rootname -nowarning \
		   | sddsconvert -pipe -del=col,MeasurementDiff \
		   | sddsprocess -pipe=in $matrixFileFiltered \
		   "-redef=col,%s,%s Weight *,select=*,exclude=Rootname"} result] {
	return -code error "Error filtering out non-used bpms (diffFile: $diffFile; matrixFile $matrixFile): $result"
    }
    #--- To avoid problem with the column naming in pseudoinverse, reprint the Rootname with unique names for each page
    if {$SVratio < 1} {set svratioOption "-minimumSingularValueRatio=$SVratio"} else {set svratioOption "-largestSingularValues=$SVratio"}
    if [catch {exec sddsprocess $matrixFileFiltered -pipe=out -nowarning "-reprint=col,Rootname,%s%s,Rootname,Plane" \
		   | sddscombine -pipe -merge \
		   | sddspseudoinverse -pipe=in $inverseMatrixFile $svratioOption \
		   -sFile=$matrixFileFiltered.SV -economy} result] {
	return -code error "Error inverting matrix: $result"
    }
}

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

proc CalculateFilesForPlotting {args} {
    global measuredBpms
    APSParseArguments {calcMode lteMeasured beamlineMeasured paramFileListMeasured lteDesired beamlineDesired paramFileListDesired \
			   paramFileListAchieved weightList doneFile workDir twiMeasured twiDesired twiAchieved \
			   xbpmList ybpmList dbpmList useTunes useRelative}
    
    set deleteFiles ""
    OutputStatusMessage "Calculations started..."

    #--- Create files with lists of bpms for later filtering...
    set measuredBpms $workDir/measuredBpms.sdds
    if $useTunes { set tuneList [list nux nuy] } else { set tuneList "" }
    set bpmList     [list $xbpmList $ybpmList $dbpmList $tuneList]
    set fileExtList [list xbpm ybpm dbpm nu]
    set planeList   [list X Y D Q]
    foreach bpmList $bpmList fileExt $fileExtList plane $planeList weight $weightList {
	if [llength $bpmList] {set dataOption "-data=[join $bpmList ,]"} else {set dataOption "-data"}
	if [catch {exec sddsmakedataset -pipe=out -col=ElementName,type=string $dataOption \
		       | sddsprocess -nowarning -pipe=in $measuredBpms.$fileExt \
		       -print=para,Plane,$plane -def=para,Weight,$weight} result] {
	    return -code error "Error making measuredBpm file for plane $plane: $result"
	}
	lappend deleteFiles $measuredBpms.$fileExt
    }

    set lteFileList [list $lteMeasured $lteDesired $lteMeasured]
    set beamlineList [list $beamlineMeasured $beamlineDesired $beamlineMeasured]
    set paramFileListList [list $paramFileListMeasured $paramFileListDesired $paramFileListAchieved]
    set twiFileList [list $twiMeasured $twiDesired $twiAchieved]
    set rootList [list measured desired achieved]
    foreach lteFile $lteFileList beamline $beamlineList paramFileList $paramFileListList \
	twissFile $twiFileList root $rootList {
	    #--- Create elegant files...
	    set eleFile $workDir/$root.ele
	    set vectorName ${root}Vector
	    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
			   -run_setup [list "lattice $lteFile use_beamline $beamline"] \
			   -load_parameters [list "filename_list \"$paramFileList\""] \
			   -twiss_output [list "filename $twissFile"] \
			   -run_control [list "n_steps 1"] \
			   -bunched_beam [list "n_particles_per_bunch 1"] \
		       } result] {
		return -code error "Fit_GenerateElegantFileFromLTE (ele file $eleFile): $result"
	    }
	    #------ Calculating beta functions:
	    if [catch {BuildMeasurementVector -calcMode $calcMode -eleFile $eleFile -twissFile $twissFile} $vectorName] {
		return -code error "BuildTwissVector: [set $vectorName]"
	    }
	}

    #------ Calculating difference:
    set measDifference $workDir/diff.twi
    lappend deleteFiles $measDifference
    if [catch {CalculateVectorDifference -vectorFile1 $desiredVector -vectorFile2 $achievedVector \
		   -outputFile $measDifference -useRelative $useRelative -nameColumn Rootname \
		   -dataColumn Measurement} result ] {
	return -code error "CalculateVectorDifference: $result"
    }
    if [catch {rmsDisplayOutput -calcMode $calcMode -iteration -1 -diffFile $measDifference -twissFile $workDir/achieved.twi \
		   -weightList $weightList -dataColumn MeasurementDiff} result] {
	return -code error "rmsDisplayOutput: $result"
    }
    eval file delete $deleteFiles
    exec touch $doneFile
}

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

proc CalculateEmittances {args} {
    global acceleratorCode desiredFiles
    APSParseArguments {calcMode workDir lteMeasured beamlineMeasured paramFileListMeasured lteDesired \
			   beamlineDesired paramFileListDesired paramFileListAchieved emitArrayList}
    set deleteFiles ""
    OutputStatusMessage "Calculations started (make sure the .lte file contains kick elements and a single rf cavity named RF)..."

    array set emitArray $emitArrayList
    set energy $emitArray(energy)
    if ![file exists $workDir] {exec mkdir $workDir}
    #------ Run elegant to calculate beam losses and rf frequency:
    if [catch {GetRFParameters -lteFile $lteDesired -beamline $beamlineDesired -paramFileList $paramFileListDesired \
		   -rfVoltage $emitArray(rfVoltage) -rfH $emitArray(rfH) -workDir $workDir -energy $energy} result] {
	return -code error "GetRFParameters: $result"
    }
    set rfVolt $emitArray(rfVoltage)
    foreach {rfcaName rfPhi rfFreq} $result {}
    #------ Make elegant template for moments calculations:
    OutputStatusMessage "Calculating beam moments..."
    set lteFileList [list $lteMeasured $lteDesired]
    set beamlineList [list $beamlineMeasured $beamlineDesired]
    set paramFileListList [list $paramFileListMeasured $paramFileListDesired]
    set rootList [list measured desired]
    if [string length $paramFileListAchieved] {
	lappend lteFileList $lteMeasured
	lappend beamlineList $beamlineMeasured
	lappend paramFileListList $paramFileListAchieved
	lappend rootList achieved
    }
    set eleFile $workDir/moments.ele
#    set pinholeSourceName S35B:M
    set pinholeSourceName S??B:M3
    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		   -divide_elements [list "name $pinholeSourceName divisions 10"] \
		   -run_setup [list "lattice <LTEFILE> use_beamline <BEAMLINE> p_central_mev $energy default_order 2 parameters [file rootname $eleFile].param semaphore_file <DONEFILE>"] \
		   -load_parameters [list "filename_list \"\\\"<PARAMFILELIST>\\\"\" allow_missing_files 1"] \
		   -alter_elements [list "name $rfcaName item VOLT value $rfVolt" \
					"name $rfcaName item PHASE value $rfPhi" \
					"name $rfcaName item FREQ value $rfFreq" \
					"name * type KQUAD item ISR value 1" \
					"name * type KSEXT item ISR value 1" \
					"name * type *BEN* item ISR value 1" \
					"name * type KQUAD item ISR1PART value 0" \
					"name * type KSEXT item ISR1PART value 0" \
					"name * type *BEN* item ISR1PART value 0" \
					"name * type KQUAD item SYNCH_RAD value 1" \
					"name * type KSEXT item SYNCH_RAD value 1" \
					"name * type *BEN* item SYNCH_RAD value 1"] \
		   -rf_setup [list "name $rfcaName harmonic $emitArray(rfH) bucket_half_height 0.04"] \
		   -run_control [list "n_steps 1"] \
		   -closed_orbit [list "closed_orbit_accuracy 1e-8 closed_orbit_iterations 500 iteration_fraction 0.25"] \
		   -twiss_output [list "output_at_each_step 0 radiation_integrals 1" "filename <TWISSFILE> radiation_integrals 1"] \
		   -moments_output [list "filename <MOMENTSFILE> radiation 1 n_slices 10 matched 1 verbosity 1"] \
		   -bunched_beam [list "n_particles_per_bunch 1"] \
		   -track [list "center_on_orbit 1"] \
	       } result] {
	return -code error "Fit_GenerateElegantFileFromLTE (ele file $eleFile): $result"
    }
    #------ Run elegant calculations:
    foreach lteFile $lteFileList beamline $beamlineList paramFileList $paramFileListList root $rootList {
	set twissFile $workDir/moments.$root.twi
	set momentsFile $workDir/moments.$root.mom
	set doneFile $workDir/moments.$root.done
	catch {file delete $eleFile.log}
	if {[string length $paramFileList] == 0} {set paramFileList dummy}
	set command "$acceleratorCode $eleFile \
		       \"-macro=LTEFILE=$lteFile,BEAMLINE=$beamline,PARAMFILELIST=$paramFileList,TWISSFILE=$twissFile,MOMENTSFILE=$momentsFile,DONEFILE=$doneFile\""
	if [catch {eval exec $command > $eleFile.$root.log} result] {
	    return -code error "Error running elegant (see $eleFile.log\ncommand: $command: $result"
	}
	set e$root [exec sddsprocess $momentsFile -pipe=out -process=exbeta,aver,ex -process=eybeta,aver,ey -process=s6,aver,dEE \
			| sdds2stream -pipe=in -para=e1,e2,ex,ey,dEE]
    }
    #------ Check is there is rf voltage in the lattice:
    if [catch {exec sddsprocess [file rootname $eleFile].param -pipe=out -match=col,ElementType=RFCA* \
		   -match=col,ElementParameter=VOLT -process=ParameterValue,sum,RFVOLTAGE \
		   | sdds2stream -pipe=in -para=RFVOLTAGE} rfVolt] {
	return -code error "Error calculating total rf voltage: $result"
    } else {
	if {$rfVolt < 3e6 || $rfVolt > 6e6} {
	    OutputStatusMessage "----> Warning: total RF voltage is unusual: $rfVolt"
	}
    }
    OutputStatusMessage "Results of moments calculations:"
    OutputStatusMessage "Ideal emittances:     e1 = [format %10.2e [lindex $edesired 0]]; e2 = [format %10.2e [lindex $edesired 1]]; ex = [format %10.2e [lindex $edesired 2]]; ey = [format %10.2e [lindex $edesired 3]]; dE/E = [format %10.2e [lindex $edesired 4]]."
    OutputStatusMessage "Measured  emittances: e1 = [format %10.2e [lindex $emeasured 0]]; e2 = [format %10.2e [lindex $emeasured 1]]; ex = [format %10.2e [lindex $emeasured 2]]; ey = [format %10.2e [lindex $emeasured 3]]; dE/E = [format %10.2e [lindex $emeasured 4]]."
    if [string length $paramFileListAchieved] {
	OutputStatusMessage "Corrected emittances: e1 = [format %10.2e [lindex $eachieved 0]]; e2 = [format %10.2e [lindex $eachieved 1]]; ex = [format %10.2e [lindex $eachieved 2]]; ey = [format %10.2e [lindex $eachieved 3]]; dE/E = [format %10.2e [lindex $eachieved 4]]."
    }
}

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

proc GetRFParameters {args} {
    global acceleratorCode
    set outputParamFile ""
    APSParseArguments {workDir lteFile beamline paramFileList rfVoltage rfH outputParamFile energy}
    OutputStatusMessage "Calculating rf parameters..."
    set eleFile $workDir/rfparam.ele
    set twissFile $workDir/rfparam.twi
    if {[string length $paramFileList] == 0} {set paramFileList dummy}
    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		   -run_setup [list "lattice $lteFile use_beamline $beamline default_order 2 p_central_mev $energy \
                                        parameters [file rootname $eleFile].param centroid [file rootname $eleFile].cen"] \
		   -load_parameters [list "filename_list \"$paramFileList\" allow_missing_files 1"] \
		   -alter_elements [list "name * type KQUAD item N_KICKS value 50" \
					"name * type KSEXT item N_KICKS value 3" \
					"name * type CSBEND item N_KICKS value 100" \
					"name * type CSBEND item EDGE_ORDER value 1" \
					"name * type CSBEND item INTEGRATION_ORDER value 4"] \
		   -run_control [list "n_steps 1"] \
		   -closed_orbit [list "closed_orbit_accuracy 1e-8 closed_orbit_iterations 500 iteration_fraction 0.25"] \
		   -twiss_output [list "output_at_each_step 0 radiation_integrals 1" "filename $twissFile radiation_integrals 1"] \
		   -bunched_beam [list "n_particles_per_bunch 1"] \
		   -track [list "center_on_orbit 1"] \
	       } result] {
	return -code error "Fit_GenerateElegantFileFromLTE (ele file $eleFile): $result"
    }
    catch {file delete $eleFile.log}
    if [catch {exec $acceleratorCode $eleFile > $eleFile.log} result] {
	return -code error "Error running elegant (see $eleFile.log\ncommand: \"$acceleratorCode $eleFile\"): $result"
    }
    set U0 [expr [exec sdds2stream $twissFile -par=U0] * 1e6]
    set phi [exec rpnl "180 $U0 $rfVoltage / dasin -"]
    set C [exec sddsprocess [file rootname $eleFile].cen -pipe=out -process=Cs,last,C \
	       | sdds2stream -pipe=in -para=C]
    set freq [exec rpnl "c_mks $C / $rfH *"]
    set rfcaName [exec sddsprocess $workDir/rfparam.param -pipe=out -match=col,ElementType=RFCA -match=col,ElementParameter=VOLT "-filter=col,ParameterValue,0,0,!" \
		      | sdds2stream -pipe=in -col=ElementName]
    if {[llength $rfcaName] > 1} {return -code error "Error: More than one RF cavity with non-zero voltage"}
    if [string length $outputParamFile] {
	exec sddsmakedataset $outputParamFile \
	    -col=ElementName,type=string -data=$rfcaName,$rfcaName,$rfcaName \
	    -col=ElementParameter,type=string -data=VOLT,PHASE,FREQ \
	    -col=ParameterValue,type=double -data=$rfVoltage,$phi,$freq
    }
    return [list $rfcaName $phi $freq]
}

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

proc MinimizeEmittance {args} {
    global acceleratorCode
    APSParseArguments {workDir quadList lteMeasured beamlineMeasured paramFileListMeasured emitArrayList optimTerm \
	optimTerm1 rootname}
    set deleteFiles ""
    OutputStatusMessage "Calculations started (make sure the .lte file contains kick elements and a single rf cavity named RF)..."
    array set emitArray $emitArrayList
    set energy $emitArray(energy)
    set rfParamFile $workDir/$rootname.rfparam
    #------ Run elegant to calculate beam losses and rf frequency:
    if [catch {GetRFParameters -lteFile $lteMeasured -beamline $beamlineMeasured -paramFileList $paramFileListMeasured \
		   -rfVoltage $emitArray(rfVoltage) -rfH $emitArray(rfH) -workDir $workDir \
		   -outputParamFile $rfParamFile  -energy $energy} result] {
	return -code error "GetRFParameters: $result"
    }
    set paramFileList [concat $paramFileListMeasured $rfParamFile]

    #------ Insert element M1 into .lte file after every *END element:
    set lteFile $workDir/$rootname.lte
    if [catch {open $lteMeasured r} fid1] {return -code error "Error opening file: $fid1"}
    if [catch {open $lteFile w} fid2] {return -code error "Error opening file: $fid2"}
    for {set i 1} {$i < 41} {incr i} {lappend nameList S${i}END}
    puts $fid2 "M1: MARK, FIT_POINT=1"
    while {[gets $fid1 line] >= 0} {
	foreach name $nameList {
	    if {[string first $name $line] != -1 && [string first MARK $line] == -1} {
		set index [expr [string first $name $line] + [string length $name]]
		set string1 [string range $line 0 [expr $index - 1]]
		set string2 [string range $line $index 999]
		set line ""
		append line $string1 ,M1 $string2
		break
	    }
	}
	puts $fid2 $line
    }
    close $fid1
    close $fid2

    #------ Make elegant file for emittance minimization:
    set eleFile $workDir/$rootname.ele
    set stepSize 0.001
    set lowerLimit -0.12
    set upperLimit 0.12
    foreach skewQuad $quadList {
	lappend optimizationVariableList "name $skewQuad item KNL step_size $stepSize lower_limit $lowerLimit upper_limit $upperLimit"
    }
    set optimizationTermList [list "term \"\\\"$optimTerm\\\"\" field_string @ field_initial_value 1 field_final_value 39 field_interval 1"]
    if [string length $optimTerm1] {lappend optimizationTermList "term \"\\\"$optimTerm1\\\"\" "}
    #------ Here optimization term is made of form "\"term\"", that's why I need so many \\\.
    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		   -run_setup [list "lattice $lteFile use_beamline $beamlineMeasured default_order 2 parameters [file rootname $eleFile].param final [file rootname $eleFile].fin"] \
		   -load_parameters [list "filename_list \"$paramFileList\" allow_missing_files 1"] \
		   -alter_elements [list "name * type KQUAD item N_KICKS value 10" \
					"name * type KSEXT item N_KICKS value 3" \
					"name * type CSBEND item N_KICKS value 10" \
					"name * type CSBEND item EDGE_ORDER value 1" \
					"name * type CSBEND item INTEGRATION_ORDER value 4" \
					"name * type KQUAD item ISR value 1" \
					"name * type KSEXT item ISR value 1" \
					"name * type CSBEND item ISR value 1" \
					"name * type KQUAD item SYNCH_RAD value 1" \
					"name * type KSEXT item SYNCH_RAD value 1" \
					"name * type CSBEND item SYNCH_RAD value 1"] \
		   -run_control [list "n_steps 1"] \
		   -moments_output [list "filename [file rootname $eleFile].mom radiation 1 n_slices 10 matched 1 verbosity 0"] \
		   -optimization_setup [list "mode minimize method simplex target 1e-14 tolerance 1e-14 n_passes 5 n_restarts 1 n_evaluations 200 log_file /dev/tty verbose 1 output_sparsing_factor 10"] \
		   -optimization_term $optimizationTermList \
		   -optimization_variable $optimizationVariableList \
		   -bunched_beam [list "n_particles_per_bunch 1"] \
		   -optimize [list ""] \
	       } result] {
	return -code error "Fit_GenerateElegantFileFromLTE (ele file $eleFile): $result"
    }
###    -optimization_term [list "term \"\\\"$optimTerm\\\"\" field_string @ field_initial_value 1 field_final_value 39 field_interval 1"] \
    
    #------ Running optimization:
    exec $acceleratorCode $eleFile >&@ stdout
}

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

proc CalculateTwissResponseMatrix { args } {

    global workDir desiredFiles locoBinDir eleMatrixTemplate correctorFile acceleratorCode
    global qsubRespProcCommand queueSystemName 
    APSStrictParseArguments {calcMode matrixFile quadList useRelative abortFile splitTasks useQsub}

    #------ For submitting several jobs without queue:
    if $useQsub {set qsubCommand "exec \$scriptFile &"} else {set qsubCommand "exec \$scriptFile"}
    set queueSystemName PS
    set qsubRespProcCommand "lindex \$qsubResponse 0"
    set remotePath ""

    set waitTime 3600
    set waitInterval 2
    set submissionPause 0
    set continuePrevious 0 
    set usePopupWindow 0

    switch $calcMode {
	beta {
	    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleMatrixTemplate \
			   -run_setup [list "lattice $desiredFiles(lte) use_beamline $desiredFiles(beamline)"] \
			   -load_parameters [list "filename_list \"$desiredFiles(paramList)\"" "filename <PARAMFILE> change_defined_values 0"] \
			   -twiss_output [list "filename <TWIFILE>"] \
			   -run_control [list "n_steps <NSTEPS>"] \
			   -bunched_beam [list "n_particles_per_bunch 1"] \
		       } result] {
		return -code error "Fit_GenerateElegantFileFromLTE (ele file $eleMatrixTemplate): $result"
	    }
	} 
	coupling {
	    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleMatrixTemplate \
			   -run_setup [list "lattice $desiredFiles(lte) use_beamline $desiredFiles(beamline)"] \
			   -load_parameters [list "filename_list \"$desiredFiles(paramList)\"" "filename <PARAMFILE> change_defined_values 0"] \
			   -alter_elements [list "name * type *KICK item STEERING value 0" "name * type *KQUAD item HSTEERING value 0" \
						"name * type *BEN* item XSTEERING value 0 allow_missing_parameters 1"] \
			   -load_parameters2 [list "filename $correctorFile"] \
			   -twiss_output [list "filename <TWIFILE>"] \
			   -run_control [list "n_steps <NSTEPS>"] \
			   -correct [list "mode orbit method global n_xy_cycles 1 fixed_length 1"] \
			   -correction_matrix_output [list "response2 <HYRMFILE> response3 <VXRMFILE> coupled 1 fixed_length 1"] \
			   -bunched_beam [list "n_particles_per_bunch 1"] \
		       } result] {
		return -code error "Fit_GenerateElegantFileFromLTE (ele file $eleMatrixTemplate): $result"
	    }
	}
    }

    set varList $quadList
    set scriptName calculateTwissCorrection
    set scriptParameters " -mode runDqsTask -calcMode $calcMode -eleTemplate $eleMatrixTemplate -useRelative $useRelative -acceleratorCode $acceleratorCode"

    set rootTaskName twiDeriv
    set tmpDirName $workDir/dqs/twiss
    if ![file exists $workDir/dqs] {exec mkdir $workDir/dqs}
    if ![file exists $workDir/dqs/twiss] {exec mkdir $workDir/dqs/twiss}
    if [llength $quadList] {
	OutputStatusMessage "Doing quadrupoles..."
	set verbose 0
	if [catch {Fit_CalculateResponseMatrixDerivative -varList $varList \
		       -splitTasks $splitTasks -scriptName $scriptName \
		       -scriptParameters $scriptParameters -matrixFile $matrixFile -tmpDirName $tmpDirName \
		       -useQsub $useQsub -qsubCommand $qsubCommand -verbose $verbose \
		       -rootTaskName $rootTaskName -continuePrevious $continuePrevious -usePopupWindow $usePopupWindow \
		       -waitTime $waitTime -waitInterval $waitInterval -submissionPause $submissionPause \
		       -abortFile $abortFile} result] {
	    return -code error "Fit_CalculateResponseMatrixDerivative: $result"
	}
    } else {
	return -code error "Error: quadList has zero length."
    }
    file delete $eleMatrixTemplate

}

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

proc OutputStatusMessage {text} {
    global outputStatusDevice outputStatusFile
    switch -exact $outputStatusDevice {
        statusScreen { APSSetVarAndUpdate status $text }
        stdout { puts stdout $text }
        file {
            if {![info exists outputStatusFile] || ![string length $outputStatusFile]} {
                return -code error "OutputStatusMessage: outputStatusFile variable is not defined."
            }
            if [file exists $outputStatusFile] {
                set fid [open $outputStatusFile a]
                puts $fid $text
                close $fid
            } else {
                set fid [open $outputStatusFile w]
                puts $fid $text
                close $fid
            }
        }
        default { return -code error "OutputStatusMessage: wrong outputStatusDevice: $outputStatusDevice" }
    }
}

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

proc StopExecution { } {
}

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

proc ScanSVnumber {args} {

    global outputStatusDevice outputStatusFile

    APSParseArguments {calcMode lteMeasured beamlineMeasured paramFileListMeasured lteDesired beamlineDesired paramFileListDesired \
			   outputFile quadList xbpmList ybpmList dbpmList weightList calculateMatrix useRelative \
			   SVstart SVend SVsteps matrixFile corFraction useDQS splitTasks iterations useTunes \
			   useMeasDisp measDispFile outputStatusDevice abortFile hcorrList vcorrList}

    set outputFileList ""
    set svList ""
    set k1List ""
    set rmsList ""
    set rmsXList ""
    set rmsYList ""
    set rmsDList ""
    set rmsNList ""
    
    set SVstep [expr ($SVend - $SVstart) / ($SVsteps - 1)]
    for {set I 0} {$I < $SVsteps} {incr I} {
	OutputStatusMessage "Step: $I."

	if [file exists $abortFile] {
	    return -code error "Scan interrupted by user."
	}

	set SVnumber [expr int($SVstart + $SVstep * $I)]
	if [catch {TwissCorrection \
		       -calcMode $calcMode \
		       -lteMeasured $lteMeasured \
		       -beamlineMeasured $beamlineMeasured \
		       -paramFileListMeasured $paramFileListMeasured \
		       -lteDesired $lteDesired \
		       -beamlineDesired $beamlineDesired \
		       -paramFileListDesired $paramFileListDesired \
		       -outputFile $outputFile \
		       -quadList $quadList \
		       -xbpmList $xbpmList \
		       -ybpmList $ybpmList \
		       -dbpmList $dbpmList \
		       -hcorrList $hcorrList \
		       -vcorrList $vcorrList \
		       -weightList $weightList \
		       -calculateMatrix 0 \
		       -calculateInverse 1 \
		       -useRelative $useRelative \
		       -SVratio $SVnumber \
		       -matrixFile $matrixFile \
		       -corFraction $corFraction \
		       -useDQS $useDQS \
		       -splitTasks $splitTasks \
		       -iterations $iterations \
		       -useTunes $useTunes \
		       -useInvSolution 0 \
		       -locoResultFile dummy \
		       -useMeasDisp $useMeasDisp \
		       -measDispFile $measDispFile \
		       -outputStatusDevice $outputStatusDevice \
		       -abortFile abortFile} resultList] {
	    OutputStatusMessage "TwissCorrection: $resultList"
	} else {
	    exec sddsprocess $outputFile $outputFile.$I -nowarning \
		-def=para,SV,$SVnumber \
		-process=ParameterValue,rms,K1rms \
		-def=para,TotalRms,[lindex $resultList 0]
	    lappend outputFileList $outputFile.$I
	    lappend svList $SVnumber
	    lappend k1List [exec sdds2stream $outputFile.$I -param=K1rms]
	    lappend rmsList [lindex  $resultList 0]
	    lappend rmsXList [lindex $resultList 1]
	    lappend rmsYList [lindex $resultList 2]
	    lappend rmsDList [lindex $resultList 3]
	    lappend rmsNList [lindex $resultList 4]
	}
    }
    exec sddsmakedataset twissScan.sdds \
	-col=SV,type=double -data=[join $svList ,] \
	-col=rmsK1,type=double -data=[join $k1List ,] \
	-col=rmsTotal,type=double -data=[join $rmsList ,] \
	-col=rmsX,type=double -data=[join $rmsXList ,] \
	-col=rmsY,type=double -data=[join $rmsYList ,] \
	-col=rmsD,type=double -data=[join $rmsDList ,] \
	-col=rmsN,type=double -data=[join $rmsNList ,]
    eval exec sddscombine $outputFileList -pipe=out \
	| sddsprocess -pipe=in $outputFile.scan "\"-print=para,BottomLine,Krms=%8.2e; Meas rms=%8.2e,K1rms,TotalRms\"" \
	"\"-print=para,TopLine,Number of SV = %3.0f,SV\""
    eval file delete $outputFileList

}

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

proc RunDqsTask {args} {

    set verbose 0
    APSParseArguments {calcMode path eleTemplate varList useRelative acceleratorCode verbose}

    cd $path
    set elegantOutFile $path/elegant.out
    set twiFile        $path/aps.twi
    set hyFile         $path/aps.hyrm
    set vxFile         $path/aps.vxrm
    set matrixFile     $path/responseMatrix.sdds
    set paramFile      $path/variables.param
    set delta 0.0001
    set numberElements [llength $varList]
    set Nruns [expr $numberElements + 1]

    #--- Run elegant to calculate the multipage twiss response
    catch {file delete $elegantOutFile}
    if {[string compare $calcMode beta] == 0} {
	set macroCommand PARAMFILE=$paramFile,TWIFILE=$twiFile,NSTEPS=$Nruns
	exec sddsmakedataset -pipe=out -col=ElementName,type=string -data=[join [concat S0A:Q0 $varList] ,] \
	    | sddsprocess -pipe -print=col,ElementParameter,K1 -print=col,ParameterMode,DIFFERENTIAL \
	    -def=col,ParameterValue,$delta \
	    | sddsbreak -pipe=in $paramFile -rowlimit=1
     } else {
	set macroCommand PARAMFILE=$paramFile,TWIFILE=$twiFile,HYRMFILE=$hyFile,VXRMFILE=$vxFile,NSTEPS=$Nruns
	 exec sddsmakedataset -pipe=out -col=ElementName,type=string -data=[join [concat S0A:Q0 $varList] ,] \
	    | sddsprocess -pipe -print=col,ElementParameter,KNL -print=col,ParameterMode,DIFFERENTIAL \
	    -def=col,ParameterValue,$delta \
	    | sddsbreak -pipe=in $paramFile -rowlimit=1
    }
    if $verbose {
	puts stdout "Running elegant..."
	puts stdout "$acceleratorCode $eleTemplate -macro=$macroCommand > $elegantOutFile"
    }
    if [catch {exec $acceleratorCode $eleTemplate -macro=$macroCommand > $elegantOutFile} result] {
	puts stderr "elegant: $result"
	return -code error
    }

    #--- Postprocessing...

    set tmpRoot /tmp/[APSTmpString]-twissMatrix
    if $verbose {puts stdout "Postprocessing..."}
    if {[string compare $calcMode beta] == 0} {
	#------ Beta mode calculations:
	set elementNameFile $path/elementName.sdds
	set baseFile $path/base.twi
	exec sddsprocess $twiFile $twiFile.bpms -match=col,ElementType=MONI
	exec sddsconvert $twiFile.bpms $baseFile -keepPages=1
	exec sddscombine $paramFile -pipe=out -merge \
	    | sddsprocess -pipe=in $elementNameFile -clip=1,0
	
	if $useRelative {
	    set command1 "\"-redef=col,ChangeIn\$column,ChangeIn\$column \$column / \$delta /\""
	    set command2 "\"-redef=col,nux,ChangeInnux \[lindex \$baseNu 0\] / \$delta /\""
	    set command3 "\"-redef=col,nuy,ChangeInnuy \[lindex \$baseNu 1\] / \$delta /\""
	} else {
	    set command1 "\"-redef=col,ChangeIn\$column,ChangeIn\$column \$delta /\""
	    set command2 "\"-redef=col,nux,ChangeInnux \$delta /\"" 
	    set command3 "\"-redef=col,nuy,ChangeInnuy \$delta /\""
	}
	
	foreach column [list betax betay etax] parameter [list X Y D] {
	    eval exec sddschanges $twiFile.bpms -pipe=out -change=$column -copy=ElementName \
		| sddsxref -nowarning -pipe $baseFile -take=$column -match=ElementName -reuse=page \
		| sddsprocess -pipe "$command1" \
		| sddsconvert -pipe -del=col,$column \
		| sddstranspose -pipe -newColumnName=ElementName \
		| sddscombine -pipe -merge \
		| sddsxref -pipe $elementNameFile -take=ElementName \
		| sddstranspose -pipe -newColumnName=ElementName -oldColumnNames=Rootname \
		| sddsconvert -pipe -del=para,* \
		| sddsprocess -pipe=in $matrixFile.$column -print=para,Plane,$parameter
	}
	set baseNu [exec sddsprintout $baseFile -para=nu? -noTitle -noLabel]
	eval exec sddscollapse $twiFile -pipe=out \
	    | sddsconvert -pipe -retain=col,nu? \
	    | sddsbreak -pipe -rowlimit=1 \
	    | sddschanges -pipe -changes=nux -changes=nuy \
	    | sddscombine -pipe -merge \
	    | sddsprocess -pipe "$command2" "$command3" -print=para,Plane,Q \
	    | sddsxref -pipe $elementNameFile -take=ElementName \
	    | sddsconvert -pipe -del=col,ChangeInnu? \
	    | sddstranspose -pipe=in $matrixFile.tunes -oldColumn=Rootname -newColumn=ElementName
	
	exec sddscombine $matrixFile.betax $matrixFile.betay $matrixFile.etax $matrixFile.tunes $matrixFile -overwrite
    } else {
	#------ Coupling mode calculations:
	set nFiles [exec sdds2stream $hyFile -nPages=bare]
	foreach ext [list hyrm vxrm] rmFile [list $hyFile $vxFile] {
	    exec sddsconvert $rmFile -pipe=out -del=col,s \
		| sddschanges -pipe -changes=exclude=BPMName,* -copy=BPMName \
		| sddssplit -pipe=in -rootname=[file rootname $rmFile] -digits=2 -ext=$ext
	}
	exec sddsprocess $twiFile -pipe=out -match=col,ElementType=MONI \
	    | sddschanges -pipe -changes=etay -copy=ElementName \
	    | sddssplit -pipe=in -rootname=[file rootname $twiFile] -digits=2 -ext=etay
	
	set matrixFileList ""
	set deleteFiles ""
	for {set i 1} {$i < $nFiles} {incr i} {
	    set fileList ""
	    set tmpRoot /tmp/[APSTmpString]-twissMatrix
	    set elementName [lindex $varList [expr $i - 1]]
	    if {$i < 10} {set index 0$i} else {set index $i}
	    foreach file [list $hyFile $vxFile] ext [list hyrm vxrm] bpmExt [list ybpm xbpm] {
		set filename [file rootname $file]$index.$ext
		if [catch {exec sddsbreak $filename -pipe=out -rowLimit=1 \
			       | sddsprocess -pipe -process=BPMName,first,BPMName \
			       | sddstranspose -pipe -oldColumnNames=Rootname -root=Measurement \
			       | sddsprocess -pipe -reprint=col,Rootname,%s%s,Rootname,BPMName \
			       | sddscombine -pipe=in $tmpRoot.$ext -merge} result] {
		    return -code error "Error making one-column file: $result"
		}
		lappend fileList $tmpRoot.$ext
		lappend deleteFiles $tmpRoot.$ext $filename
	    }
	    exec sddsconvert [file rootname $twiFile]$index.etay -pipe=out -retain=col,ElementName,ChangeInetay \
		| sddsconvert -pipe=in $tmpRoot.etay -rename=col,ChangeInetay=Measurement -rename=col,ElementName=Rootname
	    lappend fileList $tmpRoot.etay
	    lappend deleteFiles $tmpRoot.etay [file rootname $twiFile]$index.etay
	    eval exec sddscombine $fileList -pipe=out \
		| sddsprocess -pipe "\"-redef=col,Measurement,Measurement $delta / \"" "-reedit=col,Rootname,%/ChangeIn//" \
		| sddsconvert -pipe=in $matrixFile.$elementName -rename=col,Measurement=$elementName
	    lappend matrixFileList $matrixFile.$elementName
	}
	if {[llength $matrixFileList] == 1} {
	    file copy $matrixFileList $matrixFile
	} else {
	    eval exec sddsxref $matrixFileList $matrixFile -take=* -leave=Rootname
	}
	eval file delete [concat $deleteFiles $matrixFileList]
    }
    exec echo END > $path/task.completed
    exit
}

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

if {[string compare $mode calcEmit] != 0 && [string compare $mode runDqsTask] != 0} {
    if [catch {ReadListFromFile -calcMode $calcMode -listFile $elementListFile} elementList] {
	puts stderr "ReadListFromFile: $elementList"
	exit
    }
    if {[string compare $calcMode beta] == 0} {
	set quadList [lindex $elementList 0]
	set xbpmList [lindex $elementList 1]
	set ybpmList [lindex $elementList 2]
	set dbpmList [lindex $elementList 3]
	set hcorrList ""
	set vcorrList ""
    } else {
	set quadList [lindex $elementList 0]
	set hcorrList [lindex $elementList 1]
	set vcorrList [lindex $elementList 2]
	set xbpmList [lindex $elementList 3]
	set ybpmList [lindex $elementList 4]
	set dbpmList [lindex $elementList 5]
    }
}
if [string length $betaTargetFile] {
    set adjustVectorValues 1
} else {
    set adjustVectorValues 0
}
switch -exact $mode {
    correct {
	if [catch {TwissCorrection \
		       -calcMode $calcMode \
		       -lteMeasured $lteMeasured \
		       -beamlineMeasured $beamlineMeasured \
		       -paramFileListMeasured $paramFileListMeasured \
		       -lteDesired $lteDesired \
		       -beamlineDesired $beamlineDesired \
		       -paramFileListDesired $paramFileListDesired \
		       -outputFile $outputFile \
		       -quadList $quadList \
		       -xbpmList $xbpmList \
		       -ybpmList $ybpmList \
		       -dbpmList $dbpmList \
		       -hcorrList $hcorrList \
		       -vcorrList $vcorrList \
		       -weightList $weightList \
		       -calculateMatrix $calculateMatrix \
		       -calculateInverse $calculateInverse \
		       -useRelative $useRelative \
		       -SVratio $SVratio \
		       -matrixFile $matrixFile \
		       -corFraction $corFraction \
		       -useDQS $useDQS \
		       -splitTasks $splitTasks \
		       -iterations $iterations \
		       -useTunes $useTunes \
		       -useInvSolution $useInvSolution \
		       -locoResultFile $locoResultFile \
		       -useMeasDisp $useMeasDisp \
		       -measDispFile $measDispFile \
		       -outputStatusDevice $outputStatusDevice \
		       -adjustVectorValues $adjustVectorValues \
		       -abortFile $abortFile} result] {
	    OutputStatusMessage "TwissCorrection: $result \nInterrupt iterations."
	    exit 1
	} else {
	    set finalOutput "Final results: "
	    foreach rms $result {append finalOutput [format %8.4f $rms]; append finalOutput "  "}
	    OutputStatusMessage $finalOutput
	    OutputStatusMessage "Iterations are done."
	}
    }
    scan {
	if [catch {ScanSVnumber \
		       -calcMode $calcMode \
		       -lteMeasured $lteMeasured \
		       -beamlineMeasured $beamlineMeasured \
		       -paramFileListMeasured $paramFileListMeasured \
		       -lteDesired $lteDesired \
		       -beamlineDesired $beamlineDesired \
		       -paramFileListDesired $paramFileListDesired \
		       -outputFile $outputFile \
		       -quadList $quadList \
		       -xbpmList $xbpmList \
		       -ybpmList $ybpmList \
		       -dbpmList $dbpmList \
		       -hcorrList $hcorrList \
		       -vcorrList $vcorrList \
		       -weightList $weightList \
		       -calculateMatrix $calculateMatrix \
		       -useRelative $useRelative \
		       -SVstart $SVstart \
		       -SVend $SVend \
		       -SVsteps $SVsteps \
		       -matrixFile $matrixFile \
		       -corFraction $corFraction \
		       -useDQS $useDQS \
		       -splitTasks $splitTasks \
		       -iterations $iterations \
		       -useTunes $useTunes \
		       -useMeasDisp $useMeasDisp \
		       -measDispFile $measDispFile \
		       -outputStatusDevice $outputStatusDevice \
		       -abortFile $abortFile} result] {
	    OutputStatusMessage "ScanSVnumber: $result \nInterrupt iterations."
	    exit 1
	} else {
	    OutputStatusMessage "Scan is done."
	}
    }
    plot {
	if [catch {CalculateFilesForPlotting \
		       -calcMode $calcMode \
		       -lteMeasured $lteMeasured \
		       -beamlineMeasured $beamlineMeasured \
		       -paramFileListMeasured $paramFileListMeasured \
		       -lteDesired $lteDesired \
		       -beamlineDesired $beamlineDesired \
		       -paramFileListDesired $paramFileListDesired \
		       -paramFileListAchieved $paramFileListAchieved \
		       -xbpmList $xbpmList \
		       -ybpmList $ybpmList \
		       -dbpmList $dbpmList \
		       -weightList $weightList \
		       -doneFile $doneFile \
		       -workDir $workDir \
		       -useTunes $useTunes \
		       -useRelative $useRelative \
		       -twiMeasured $twiMeasured \
		       -twiDesired $twiDesired \
		       -twiAchieved $twiAchieved} result] {
	    OutputStatusMessage "CalculateFilesForPlotting: $result"
	    exit 1
	}
    }
    minEmit {
	if [catch {MinimizeEmittance \
		       -workDir $workDir \
		       -quadList $quadList \
		       -lteMeasured $lteMeasured \
		       -beamlineMeasured $beamlineMeasured \
		       -paramFileListMeasured $paramFileListMeasured \
		       -optimTerm $optimTerm \
		       -optimTerm1 $optimTerm1 \
		       -rootname $rootname \
		       -emitArrayList $emitArrayList} result] {
	     OutputStatusMessage "MinimizeEmittance: $result"
	    exit 1
	}
    }
    calcEmit {
	if [catch {CalculateEmittances \
		       -calcMode $calcMode \
		       -workDir $workDir \
		       -lteMeasured $lteMeasured \
		       -beamlineMeasured $beamlineMeasured \
		       -paramFileListMeasured $paramFileListMeasured \
		       -lteDesired $lteDesired \
		       -beamlineDesired $beamlineDesired \
		       -paramFileListDesired $paramFileListDesired \
		       -paramFileListAchieved $paramFileListAchieved \
		       -emitArrayList $emitArrayList} result] {
	    OutputStatusMessage "CalculateEmittances: $result"
	    exit 1
	}
    }
    runDqsTask {
	if [catch {RunDqsTask -calcMode $calcMode -path $path -eleTemplate $eleTemplate -varList $varList \
		       -useRelative $useRelative -acceleratorCode $acceleratorCode -verbose $verbose} result] {
	    OutputStatusMessage "RunDqsTaks: $result"
	    exit 1
	}
    }
}
