#!/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)] {
    puts stderr "   Error: LOCO_BINDIR environment variable is not defined"
    exit
} else {
    set locoBinDir $env(LOCO_BINDIR)
}

if [info exists env(LOCO_TMPDIR)] {
    set tmpDir $env(LOCO_TMPDIR)
} else {
    set tmpDir $env(HOME)/tmp
}
if ![file exists $tmpDir] {exec mkdir -p $tmpDir}
#set auto_path [linsert $auto_path 0 $locoBinDir/tclLib]
source $locoBinDir/tclLib/fittingProcedures.tcl

set args $argv
set rememberArgs $args

set acceleratorCode ""
set runMode ""
APSParseArguments {acceleratorCode runMode}
if {![string length $acceleratorCode] || ![string length $runMode]} {
    puts stderr "Error: variables acceleratorCode and/or runMode are empty."
    puts stderr "Calling arguments: $rememberArgs"
    exit
}
switch -exact -- $acceleratorCode {
    elegant {set varName ELEGANT_BINDIR}
    optim {set varName OPTIM_BINDIR}
}
if ![info exists env($varName)] {
    puts stderr "   Error: $varName environment variable is not defined"; exit
} else {
    set accelCodeBinDir $env($varName)
}

#
#--- Argument checking first (too many arguments, need to check them all - good for debugging)...
#

switch -exact $runMode {
    getSDDSLattice {
	set fullVarList [list lteFile beamlineName latticeParamFileList optimFile workDir sddsLatticeFile bRho] 
	set requiredVarListelegant [list lteFile beamlineName workDir sddsLatticeFile bRho]
	set requiredVarListoptim [list optimFile workDir sddsLatticeFile bRho]
	set defaultVarList ""
	set defaultValueList ""
    }
    getBetaFunctions {
	set fullVarList [list lteFile beamlineName workDir latticeParamFileList twiFile closedOrbit \
			     twissRefFile twissRefElement malignElement fixedOrbitLength optimFile fourD \
			     verbose bRho]
	set requiredVarListelegant [list lteFile beamlineName workDir twiFile bRho]
	set requiredVarListoptim [list optimFile workDir twiFile fourD bRho]
	set defaultVarList [list closedOrbit fixedOrbitLength fourD verbose]
	set defaultValueList [list 1 0 1 0]
    }
    getResponseMatrix {
	set varList [list lteFile beamlineName workDir latticeParamFileList twiFile \
			     hrmFile vrmFile hCorrList vCorrList kickX kickY useKickFiles kickFileX kickFileY \
			     fitDispersion dispFitWeight dispColumn \
			     malignElement twissRefFile twissRefElement \
			     verbose sddsLatticeFile optimFile fourD optimNonlin bRho locoSearchString]
	set calcList [list closedOrbit fixedOrbitLength directCalc coupledMatrix useDoubleOrbits]
	set qsubList [list useQsub numberOfQsubTasks waitInterval waitTime qsubCommand qsubRespProcCommand \
			  submissionPause queueSystemName]
	set fullVarList [concat $varList $calcList $qsubList]
	set requiredVarListelegant [list lteFile beamlineName workDir twiFile \
					hrmFile vrmFile hCorrList vCorrList directCalc kickX kickY coupledMatrix \
					fitDispersion dispFitWeight dispColumn useQsub \
					useKickFiles useDoubleOrbits bRho]
	set requiredVarListoptim [list optimFile workDir twiFile fourD sddsLatticeFile hrmFile vrmFile hCorrList vCorrList \
				      optimNonlin coupledMatrix bRho kickX kickY locoSearchString fitDispersion dispFitWeight \
				      dispColumn useQsub]
	set defaultVarList [list closedOrbit fixedOrbitLength directCalc fourD verbose usQsub numberOfQsubTasks submissionPause]
	set defaultValueList [list 1 0 0 1 0 0 1 0]
    }
    runCalculateOrbit {
	set fullVarList [list locoBinDir accelCodeBinDir latticeFile orbitFile workDir nonlin correctorFile corrList kick \
			     sddsLatticeFile bRho tmpDir accelCode fixedOrbitLength \
			     closedOrbit refCorr useDoubleOrbits useKickFiles kickFile]
	set requiredVarListelegant [list locoBinDir accelCodeBinDir latticeFile orbitFile workDir nonlin correctorFile corrList kick \
					sddsLatticeFile bRho tmpDir accelCode fixedOrbitLength \
					closedOrbit refCorr useDoubleOrbits]
	set requiredVarListoptim $requiredVarListelegant
	set defaultVarList [list useKickFiles]
	set defaultValueList [list 0]
    }
}
set error 0
foreach var $fullVarList {set $var ""}
if [llength $defaultVarList] {foreach varName $defaultVarList varValue $defaultValueList {set $varName $varValue}}
APSParseArguments $fullVarList
foreach var [set requiredVarList$acceleratorCode] {
    if ![string length [set $var]] {set error 1; puts stderr "Error: variable $var is empty."}
}
if $error {exit}

#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#--- Optim specific procedures ----------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------

proc RemoveTabs {args} {
    set inputFile ""
    set outputFile ""
    APSParseArguments {inputFile outputFile}
    if [catch {open $inputFile r} fid] {
        return -code error "$fid"
    }
    set data [read -nonewline $fid]
    close $fid
    set data [join [split $data \t] " "]
    
    if [catch {open $outputFile w} fid] {
        return -code error "$fid"
    }
    puts -nonewline $fid $data
    close $fid
}

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

proc Optim2sdds { args } {
    global tmpDir
    APSParseArguments { optimMode inputFile outputFile }
    set tmpRoot $tmpDir/[APSTmpString]-optim2sdds
    switch -exact -- $optimMode {
        s {
            if [catch {exec plaindata2sdds $inputFile -pipe=out -inputMode=ascii -outputMode=binary "-separator= " \
                           -noRowCount -order=rowMajor -skiplines=1 \
                           -column=Index,double \
                           -column=ElementName,string \
                           -column=s,double,units=m \
                           -column=betax,double,units=m \
                           -column=alphax,double \
                           -column=psix,double \
                           -column=etax,double,units=m \
                           -column=etaxp,double \
                           -column=betay,double,units=m \
                           -column=alphay,double \
                           -column=psiy,double \
                           -column=etay,double,units=m \
                           -column=etayp,double \
                           -column=ElementType,string \
                           -column=Length,double,units=m \
                           -column=Angle,double,units=mrad \
                           -column=K1,double \
                           -column=K2,double \
                           -column=Tilt,double,units=rad \
                           -column=E1,double,units=rad \
                           -column=E2,double,units=rad \
                           -column=Energy,double,units=MeV \
                           | sddsprocess -pipe=in $outputFile \
                           "-reedit=col,ElementType,%/MONT/MONI/" \
                           -process=psix,last,nux -process=psiy,last,nuy \
                           "-redef=col,%s,%s 2 3.1415 * *,select=psi?,units=rad"} result] {
                return -code error "Error doing -s optimMode: $result"
            }
        }
        c {
            if [catch {RemoveTabs -inputFile $inputFile -outputFile $tmpRoot.1} result] {
                return -code error "RemoveTabs: $result"
            }
            if [catch {exec plaindata2sdds $tmpRoot.1 -pipe=out -inputMode=ascii -outputMode=binary "-separator= " \
                           -noRowCount -order=rowMajor -skiplines=1 \
                           -column=Index,double \
                           -column=ElementName,string \
                           -column=s,double,units=cm \
                           -column=betax1,double,units=cm \
                           -column=alphax1,double \
                           -column=betay1,double,units=cm \
                           -column=alphay1,double \
                           -column=teta1,double \
                           -column=betax2,double,units=cm \
                           -column=alphax2,double \
                           -column=betay2,double,units=cm \
                           -column=alphay2,double \
                           -column=teta2,double \
                           -column=U,double \
                           -column=etax,double,units=cm \
                           -column=etaxp,double \
                           -column=etay,double,units=cm \
                           -column=etayp,double \
                           -column=psix,double \
                           -column=psiy,double \
                           -column=M56,double \
                           -column=Energy,double,units=MeV \
                           | sddsprocess -pipe=in $tmpRoot.2 "-redef=col,%s,%s 100 /,select=*eta*,exclude=teta*,units=m" \
                           -process=psix,last,nux -process=psiy,last,nuy \
                           "-redef=col,%s,%s 2 3.1415 * *,select=psi?,units=rad"} result] {
                return -code error "Error doing -c optimMode: $result"
            }
            if [catch {MakeElementTypeColumn -inputFile $tmpRoot.2 -outputFile $outputFile} result] {
                return -code error "MakeElementTypeColumn: -c mode: $result"
            }
            file delete $tmpRoot.1 $tmpRoot.2
        }
        t {
            if [catch {RemoveTabs -inputFile $inputFile -outputFile $tmpRoot.1} result] {
                return -code error "RemoveTabs: $result"
            }
            if [catch {exec plaindata2sdds $tmpRoot.1 -pipe=out -inputMode=ascii -outputMode=binary "-separator= " \
                           -noRowCount -order=rowMajor -skiplines=1 \
                           -column=Index,double \
                           -column=s,double,units=cm \
                           -column=ElementName,string \
                           -column=x,double,units=cm \
                           -column=xp,double,units=mrad \
                           -column=y,double,units=cm \
                           -column=yp,double,units=mrad \
                           -column=st,double,units=cm \
                           -column=dpp,double \
                           | sddsprocess -pipe=in $tmpRoot.2 "-redef=col,x,x 10 *,units=mm" "-redef=col,y,y 10 *,units=mm" \
                           "-redef=col,s,s 100 /,units=m"} result] {
                return -code error "Error doing -t optimMode: $result"
            }
            if [catch {MakeElementTypeColumn -inputFile $tmpRoot.2 -outputFile $outputFile} result] {
                return -code error "MakeElementTypeColumn: -t mode: $result"
            }
            file delete $tmpRoot.1 $tmpRoot.2
        }
        default {
            return -code error "Wrong optimMode $optimMode."
        }
    }
}

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

proc CalculateOptimRM {args} {
    
    global tmpDir
    
    set nonlin "0"
    set useQsub 0
    APSParseArguments {optimFile sddsLatticeFile hrmFile vrmFile nonlin hCorrList vCorrList workDir useQsub coupledMatrix \
                           fitDispersion dispColumn dispFitWeight twiFile bRho kickX kickY locoSearchString \
			   qsubCommand numberOfQsubTasks waitInterval waitTime accelCodeBinDir verbose}
    
    if [catch {CalculateDirectRM \
		   -optimFile $optimFile \
		   -sddsLatticeFile $sddsLatticeFile \
		   -hrmFile $hrmFile \
		   -vrmFile $vrmFile \
		   -hCorrList $hCorrList \
		   -vCorrList $vCorrList \
		   -workDir $workDir \
		   -useQsub $useQsub \
		   -coupledMatrix $coupledMatrix \
		   -fitDispersion $fitDispersion \
		   -dispColumn $dispColumn \
		   -dispFitWeight $dispFitWeight \
		   -twiFile $twiFile \
		   -kickX $kickX \
		   -kickY $kickY \
		   -qsubCommand $qsubCommand \
		   -numberOfQsubTasks $numberOfQsubTasks \
		   -waitInterval $waitInterval \
		   -waitTime $waitTime \
		   -accelCode optim \
		   -accelCodeBinDir $accelCodeBinDir \
		   -bRho $bRho \
		   -locoSearchString $locoSearchString \
		   -verbose $verbose \
		   -nonlin $nonlin} result] {
	return -code error "CalculateDirectRM: $result"
    }
    
    
}

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

proc CalculateOptimBetas {args} {
    
    global tmpDir
    
    set optimFile ""
    set twiFile ""
    set nonlin "0"
    set fourD "0"
    set workDir ""
    APSParseArguments {optimFile twiFile nonlin fourD workDir accelCodeBinDir}
    
    switch -exact -- $nonlin {
        0 {set nonlinInput Y}
        1 {set nonlinInput E}
        default {return -code error "Wrong nonlin parameter $nonlin: must be 0 or 1."}
    }
    
    set tmpRoot $tmpDir/[APSTmpString]-twiss
    set optimOutFile $workDir/optim.out
    file delete $optimOutFile
    if $fourD {
        if [catch {exec $accelCodeBinDir/optim32 -c $optimFile $tmpRoot "*" Y N 0.0 $nonlinInput \
                       > $optimOutFile} result] {
            return -code error "Error running optim: look in $optimOutFile file"
        }
        if [catch {Optim2sdds -optimMode c -inputFile $tmpRoot -outputFile $twiFile} result] {
            return -code error "Optim2sdds: $result"
        }
        file delete $tmpRoot
    } else {
        if [catch {exec $accelCodeBinDir/optim32 -s $optimFile $tmpRoot "*" Y N \# 0.0 $nonlinInput \
                       > $optimOutFile} result] {
            return -code error "Error running optim: look in $optimOutFile file"
        }
        if [catch {Optim2sdds -optimMode s -inputFile $tmpRoot -outputFile $twiFile} result] {
            return -code error "Optim2sdds: $result"
        }
        file delete $tmpRoot
    }
}

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

proc MakeElementTypeColumn { args } {
    APSParseArguments { inputFile outputFile }
    set firstSymbolList [list k    i    o     q]
    set typeList        [list KICK MONI DRIFT QUAD]
    set fileList ""
    foreach firstSymbol $firstSymbolList elementType $typeList {
        set pattern ${firstSymbol}*
        exec sddsprocess -nowarning $inputFile $inputFile.$firstSymbol -match=col,ElementName=$pattern \
            -print=col,ElementType,$elementType
        lappend fileList $inputFile.$firstSymbol
    }
    eval exec sddscombine $fileList $inputFile.all -merge
    exec sddsselect $inputFile $inputFile.all -pipe=out -match=ElementName -invert \
        | sddsprocess -pipe=in $inputFile.other -print=col,ElementType,OTHER
    exec sddsprocess $inputFile.all $inputFile.all.no1stSymbol "-reedit=col,ElementName,a 1d"
    exec sddscombine $inputFile.all.no1stSymbol $inputFile.other -pipe=out -merge \
        | sddssort -pipe=in $outputFile -col=Index,increasing
    eval file delete $fileList $inputFile.all $inputFile.other $inputFile.all.no1stSymbol
}

#------ Takes length from sddsLatticeFile and calculates field in kG

proc SetKick {args} {
    APSParseArguments {correctorFile corrName kick sddsLatticeFile bRho}
    if {$kick == 0} {
        set corrField 0.0
    } else {
        if [catch {GetCorrectorLength -corrName $corrName -sddsLatticeFile $sddsLatticeFile} corrLength] {
            return -code error "GetCorrectorLength: $corrLength"
        }
	#--- kick[rad], bRho[Tm], corrLength[m]
        #--- 10 is to trasnfrom T to kG.
        set corrField [expr $kick * $bRho / $corrLength * 10]
    }
    if [catch {open $correctorFile w} fid] {
        return -code error "Problem opening file: $fid"
    }
    puts $fid "\$b${corrName}=$corrField"
    close $fid
}

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

proc GetCorrectorLength { args } {
    global tmpDir
    set tmpRoot $tmpDir/[APSTmpString].corrLength
    APSParseArguments {corrName sddsLatticeFile}
    set fileLength [exec sddsprocess -nowarning $sddsLatticeFile -pipe=out -match=col,ElementName=$corrName \
                        | tee $tmpRoot \
                        | sdds2stream -pipe=in -rows=bare]
    if {$fileLength > 1} {
	#---- For considering separators, I commented the check below:
	#        return -code error "number of correctors in file $sddsLatticeFile matching $corrName is: \
			       #                             $fileLength"
	set corrLengthList [exec sdds2stream $tmpRoot -col=Length]
	set corrLength 0
	foreach length $corrLengthList {set corrLength [expr $corrLength + $length]}
    } else {
	set corrLength [exec sdds2stream $tmpRoot -col=Length]
    }
    file delete $tmpRoot
    return $corrLength
}

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

proc GetOrbit {args} {
    APSParseArguments {latticeFile orbitFile nonlin workDir tmpDir accelCodeBinDir}
    
    switch -exact -- $nonlin {
        0 {set nonlinInput Y}
        1 {set nonlinInput E}
        default {return -code error "Wrong nonlin argument"}
    }

    set optimOutFile $workDir/optim.out
    file delete $optimOutFile
    if [catch {exec $accelCodeBinDir/optim32 -t $latticeFile $orbitFile.tmp "i*" Y $nonlinInput T 0 > $optimOutFile} result] {
	set errorMessage "optim parameters: -t $latticeFile $orbitFile.tmp \"i*\" Y $nonlinInput T 0"
        return -code error "$accelCodeBinDir/optim32: $result: $errorMessage"
    }
    #--- sdds orbit file is in mm.
    if [catch {Optim2sdds -optimMode t -inputFile $orbitFile.tmp -outputFile $orbitFile} result] {
        return -code error "Optim2sdds (inputFile $orbitFile.tmp): $result"
    }
    file delete $orbitFile.tmp
}

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

proc Make2pageOrbitFileOptim {args} {
    APSParseArguments {inputFile outputFile columnName}

    #--- Normal response matrix is: Page 1 is x-orbit at x-bpms; Page 2 is y-orbit at y-bpms):
    #--- Cross  response matrix is: Page 1 is y-orbit at x-bpms; Page 2 is x-orbit at y-bpms):

    set patternList [list *H* *V* *H* *V*]
    set planeList [list X Y X Y]
    set bpmPlaneList [list X Y X Y]
    set orbitPlaneList [list X Y Y X]
    set orbitColumnList [list x y y x]
    set outputList [list $outputFile.1 $outputFile.2 $outputFile.3 $outputFile.4]

    foreach pattern $patternList plane $planeList bpmPlane $bpmPlaneList orbitPlane $orbitPlaneList \
	orbitColumn $orbitColumnList output $outputList {
	    exec sddsprocess -nowarning $inputFile -pipe=out "-match=col,ElementType=MONI,ElementName=$pattern,&" -print=para,Plane,$plane \
		-print=para,BpmPlane,$bpmPlane -print=para,OrbitPlane,$orbitPlane \
		| sddsconvert -pipe=in $output -retain=col,ElementName -retain=col,$orbitColumn \
		-rename=col,$orbitColumn=$columnName
	}
    if {([exec sdds2stream -rows=bare $outputFile.1] == 0) || ([exec sdds2stream -rows=bare $outputFile.2] == 0)} {
        return -code error "sddsprocess returns no elements matching *H* or *V* patterns \
                            in orbit file $inputFile. Make sure the elements (BMPs) in .opt file fit these patterns."
    }
    exec sddscombine $outputFile.1 $outputFile.2 $outputFile -overWrite
    exec sddscombine $outputFile.3 $outputFile.4 $outputFile.XRM -overWrite
    eval file delete $outputList

}


#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#--- Elegant specific procedures --------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------


#--- Nondirect uses elegant response_matrix_output command which uses beta functions (no coupled response)

proc NondirectElegantResponse {args} {
    global bRho
    APSParseArguments {accelCodeBinDir workDir lteFile beamlineName latticeParamFileList hCorrList vCorrList hrmFile vrmFile \
			   twiFile fixedOrbitLength coupledMatrix useResponseFromOrbits includeTwissCalc kickX kickY \
			   useQsub qsubCommand numberOfQsubTasks waitInterval waitTime verbose}

    set deleteFiles ""
    set commandList ""
    set jobNameList ""
    set doneFileList ""
    set eleLogFileList ""

    #------ Prepare job for twiss calculation:
    if $includeTwissCalc {
	set tmpRoot $workDir/[APSTmpString]-calculateElegantBetas
	set eleFile $tmpRoot.ele
	set localTwiFile $tmpRoot.twi
	set doneFile $tmpRoot.done
	set elegantOutFile $tmpRoot.log
	lappend deleteFiles $eleFile $doneFile $elegantOutFile $localTwiFile
	set energy [format %10.4e [expr $bRho * 299792458e-6]]
	if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		       -run_setup [list "lattice $lteFile use_beamline $beamlineName default_order 2 semaphore_file $doneFile p_central_mev $energy"] \
		       -load_parameters [list "filename_list \"$latticeParamFileList\""] \
		       -run_control [list "n_steps 1"] \
		       -closed_orbit [list "fixed_length 0"] \
		       -twiss_output [list "filename $localTwiFile matched 1 output_at_each_step 1"] \
		       -bunched_beam [list "n_particles_per_bunch 1"] \
		   } result] {
	    return -code error "Fit_GenerateElegantFileFromLTE1: $result"
	}
	lappend commandList "$accelCodeBinDir/elegant $eleFile > $elegantOutFile"
	lappend eleLogFileList $elegantOutFile
	lappend jobNameList beta
	lappend doneFileList $doneFile
    }

    #------ Prepare jobs for RM calculations:
    if [catch {Fit_SplitList -List [concat $hCorrList $vCorrList] -splitTasks $numberOfQsubTasks} listAfterSplitting] {
	return -code error "Fit_SplitList: $listAfterSplitting"
    }
    set rootList ""
    set tmpRoot0 $workDir/[APSTmpString]-singleElegResp
    set counter 0
    foreach taskList $listAfterSplitting {
	set tmpRoot ${tmpRoot0}$counter
	if [catch {SingleElegantResponse -accelCodeBinDir $accelCodeBinDir \
		       -lteFile $lteFile -beamlineName $beamlineName -kickX $kickX -kickY $kickY \
		       -latticeParamFileList $latticeParamFileList -corrList $taskList -twiFile $twiFile \
		       -coupledMatrix $coupledMatrix -fixedOrbitLength $fixedOrbitLength \
		       -useResponseFromOrbits $useResponseFromOrbits -tmpRoot $tmpRoot} result] {
	    return -code error "SingleElegantResponse: $result"
	}
	lappend commandList [lindex $result 0]
	lappend eleLogFileList [lindex $result 1]
	lappend jobNameList orbit$counter
	lappend doneFileList $tmpRoot.done
	lappend rootList $tmpRoot
	set deleteFiles [concat $deleteFiles [lindex $result 2]]
	incr counter
    }
    #------ Submit and wait
    if $useQsub {
	if [catch {Fit_SubmitJobs -commandList $commandList -jobNameList $jobNameList -doneFileList $doneFileList \
		       -verbose $verbose} returnList] {
	    return -code error "Fit_SubmitJobs: $returnList"
	}
	set pidList [lindex $returnList 0]
	set logFileList [lindex $returnList 1]
	set scriptFileList [lindex $returnList 2]
	set dotOFileList [lindex $returnList 3]
	set deleteFiles [concat $deleteFiles $scriptFileList $dotOFileList]
	if [catch {Fit_WaitForTasks_New -pidList $pidList -jobNameList $jobNameList -commandList $commandList \
		       -logFileList $logFileList -doneFileList $doneFileList -waitTime $waitTime \
		       -waitInterval $waitInterval -usePopupWindow 0 \
		       -useQsub $useQsub -abortFile [APSTmpString] \
		       -verbose $verbose} result] {
	    return -code error "Fit_WaitForTasks_New: $result"
	}
    } else {
	foreach command $commandList {
	    if [catch {eval exec $command} result] {
		return -code error "$command: $result"
	    }
	}
    }
    if $includeTwissCalc {file copy -force $localTwiFile $twiFile}

    #------ Analyze if elegant printed error in orbit convergence (elegant does not abort in case of orbit divergence):
    foreach logFile $eleLogFileList {
	if ![catch {exec grep "error: closed orbit did not converge" $logFile} result] {
	    #--- grep gives error if no match
	    return -code error "elegant reported not converging orbits, see $logFile."
	}
    }

    #------ Assemble rm files:
    set tmpRoot $workDir/[APSTmpString]-nondirectResponse
    if {[llength $rootList] == 1} {
	file copy -force $rootList.hrm $tmpRoot.hrm
	file copy -force $rootList.vrm $tmpRoot.vrm
	file copy -force $rootList.hvrm $tmpRoot.hvrm
	file copy -force $rootList.vhrm $tmpRoot.vhrm
    } else {
	foreach root $rootList {
	    lappend hrmFileList $root.hrm
	    lappend vrmFileList $root.vrm
	    lappend hvrmFileList $root.hvrm
	    lappend vhrmFileList $root.vhrm
	}
	eval exec sddsxref $hrmFileList $tmpRoot.hrm -take=* -leave=BPMName,s -nowarning
	eval exec sddsxref $vrmFileList $tmpRoot.vrm -take=* -leave=BPMName,s -nowarning
	eval exec sddsxref $hvrmFileList $tmpRoot.hvrm -take=* -leave=BPMName,s -nowarning
	eval exec sddsxref $vhrmFileList $tmpRoot.vhrm -take=* -leave=BPMName,s -nowarning
    }
    #------ Reformat the way I need:
    if {$coupledMatrix == 2} {
	#------ Here I just blindly change suffix assuming that in the APS lattice file all the BPM are double plane. Filtering is done later anyway.
	lappend deleteFiles $tmpRoot.hrm $tmpRoot.vrm $tmpRoot.vhrm $tmpRoot.hvrm
	#------ Parameter file for direct response:
	exec sddsmakedataset -pipe=out -col=plane,type=string -data=X,Y \
	    | sddsbreak -pipe -rowlimit=1 \
	    | sddsprocess -pipe=in $tmpRoot.params -process=plane,first,Plane -process=plane,first,BpmPlane \
	    -process=plane,first,OrbitPlane 
	#------ Parameter file for XRM response:
	exec sddsmakedataset -pipe=out -col=plane1,type=string -data=X,Y -col=plane2,type=string -data=Y,X \
	    | sddsbreak -pipe -rowlimit=1 \
	    | sddsprocess -pipe=in $tmpRoot.params.XRM -process=plane1,first,Plane -process=plane1,first,BpmPlane \
	    -process=plane2,first,OrbitPlane
	lappend deleteFiles $tmpRoot.params $tmpRoot.params.XRM
	#------ hrm file:
	exec sddscombine $tmpRoot.hrm $tmpRoot.vhrm -pipe=out \
	    | sddsconvert -pipe -del=col,s \
	    | sddsxref -pipe=in $tmpRoot.params $hrmFile -leave=* -transfer=para,*Plane
	#------ hrm.XRM file
	exec sddsprocess $tmpRoot.hrm $tmpRoot.hrm.1 "-reedit=col,BPMName,%@X@Y@"
	exec sddsprocess $tmpRoot.vhrm $tmpRoot.vhrm.1 "-reedit=col,BPMName,%@Y@X@"
	exec sddscombine $tmpRoot.vhrm.1 $tmpRoot.hrm.1 -pipe=out \
	    | sddsconvert -pipe -del=col,s \
	    | sddsxref -pipe=in $tmpRoot.params.XRM $hrmFile.XRM -leave=* -transfer=para,*Plane
	lappend deleteFiles $tmpRoot.hrm.1 $tmpRoot.vhrm.1
	#------ vrm file:
	exec sddscombine $tmpRoot.hvrm $tmpRoot.vrm -pipe=out \
	    | sddsconvert -pipe -del=col,s \
	    | sddsxref -pipe=in $tmpRoot.params $vrmFile -leave=* -transfer=para,*Plane
	#------ vrm.XRM file
	exec sddsprocess $tmpRoot.vrm $tmpRoot.vrm.1 "-reedit=col,BPMName,%@Y@X@"
	exec sddsprocess $tmpRoot.hvrm $tmpRoot.hvrm.1 "-reedit=col,BPMName,%@X@Y@"
	exec sddscombine $tmpRoot.vrm.1 $tmpRoot.hvrm.1 -pipe=out \
	    | sddsconvert -pipe -del=col,s \
	    | sddsxref -pipe=in $tmpRoot.params.XRM $vrmFile.XRM -leave=* -transfer=para,*Plane
	lappend deleteFiles $tmpRoot.vrm.1 $tmpRoot.hvrm.1
    }
    eval file delete $deleteFiles
}

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

proc SingleElegantResponse {args} {
    global bRho
    APSParseArguments {accelCodeBinDir lteFile beamlineName latticeParamFileList corrList twiFile \
			   coupledMatrix fixedOrbitLength useResponseFromOrbits tmpRoot kickX kickY}
    set deleteFiles ""
    set elegantOutFile $tmpRoot.log
    set eleFile $tmpRoot.ele
    set doneFile $tmpRoot.done
    set hrmFile $tmpRoot.hrm
    set vrmFile $tmpRoot.vrm
    set hvrmFile $tmpRoot.hvrm
    set vhrmFile $tmpRoot.vhrm
    lappend deleteFiles $tmpRoot.log $tmpRoot.ele $tmpRoot.done $tmpRoot.hrm $tmpRoot.vrm $tmpRoot.hvrm $tmpRoot.vhrm

    exec sddsmakedataset -pipe=out -col=ElementName,type=string -data=[join $corrList ,] \
	| sddsprocess -pipe=in $tmpRoot.use -print=col,ElementParameter,STEERING -def=col,ParameterValue,1
    lappend deleteFiles $tmpRoot.use
    set correctorsFile $tmpRoot.use

    #--- Create elegant file for RM calculations:
    switch -exact $coupledMatrix {
	0 {set correctionMatrixOutput "response \"$hrmFile $vrmFile\" output_at_each_step 1 fixed_length $fixedOrbitLength"}
	1 {set correctionMatrixOutput "response \"$hrmFile $vrmFile\" output_at_each_step 1 fixed_length $fixedOrbitLength coupled 1"}
	2 {set correctionMatrixOutput "response \"$tmpRoot.hrm $tmpRoot.vrm $tmpRoot.vhrm $tmpRoot.hvrm\" output_at_each_step 1 fixed_length $fixedOrbitLength coupled 1 use_response_from_computed_orbits $useResponseFromOrbits"}
    }

    #------ load_parameters2 always goes after alter_elements
    set energy [format %10.4e [expr $bRho * 299792458e-6]]
    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		   -run_setup [list "lattice $lteFile use_beamline $beamlineName semaphore_file $doneFile p_central_mev $energy"] \
		   -alter_elements [list "name * type *KICK* item STEERING value 0"] \
		   -load_parameters2 [list "filename_list \"[concat $latticeParamFileList $correctorsFile]\""] \
		   -run_control [list "n_steps 1"] \
		   -correct [list "mode orbit n_iterations 0 n_xy_cycles 0 fixed_length $fixedOrbitLength fixed_length_matrix $fixedOrbitLength use_response_from_computed_orbits $useResponseFromOrbits corrector_tweek \"$kickX $kickY\""] \
		   -correction_matrix_output [list "$correctionMatrixOutput"] \
		   -bunched_beam [list "n_particles_per_bunch 1"] \
	       } result] {
	return -code error "Fit_GenerateElegantFileFromLTE1: $result"
    }
    lappend deleteFiles $tmpRoot.orb
    
    set command "$accelCodeBinDir/elegant $eleFile > $elegantOutFile"
    return [list $command $elegantOutFile $deleteFiles]
}

#----------------------------------------------------------------------------------------------------------------------------
#--- Main elegant procedure

proc CalculateElegantRM {args} {
    
    APSParseArguments {lteFile beamlineName latticeParamFileList includeTwissCalc \
			   hrmFile vrmFile hCorrList vCorrList workDir useQsub fixedOrbitLength kickX kickY \
                           directCalc twiFile fitDispersion dispFitWeight dispColumn coupledMatrix closedOrbit \
			   qsubCommand numberOfQsubTasks waitInterval waitTime accelCodeBinDir verbose useDoubleOrbits \
			   twissRefFile twissRefElement malignElement useKickFiles kickFileX kickFileY}

    if {$directCalc == 1} {
	if [catch {CalculateDirectRM -lteFile $lteFile -beamlineName $beamlineName -latticeParamFileList $latticeParamFileList \
		       -hrmFile $hrmFile -vrmFile $vrmFile \
		       -hCorrList $hCorrList -vCorrList $vCorrList -workDir $workDir -useQsub $useQsub \
		       -coupledMatrix $coupledMatrix -fitDispersion $fitDispersion -dispColumn $dispColumn \
		       -dispFitWeight $dispFitWeight -twiFile $twiFile -kickX $kickX -kickY $kickY \
		       -qsubCommand $qsubCommand -numberOfQsubTasks $numberOfQsubTasks -verbose $verbose \
		       -waitInterval $waitInterval -waitTime $waitTime -accelCode elegant \
		       -fixedOrbitLength $fixedOrbitLength -accelCodeBinDir $accelCodeBinDir \
		       -closedOrbit $closedOrbit -useDoubleOrbits $useDoubleOrbits \
		       -useKickFiles $useKickFiles -kickFileX $kickFileX -kickFileY $kickFileY \
		       -twissRefFile $twissRefFile -twissRefElement $twissRefElement -malignElement $malignElement} result] {
            return -code error "CalculateDirectRM: $result"
        }
    } else {
	if {$directCalc == 2} {set useResponseFromOrbits 1} else {set useResponseFromOrbits 0}
        if [catch {NondirectElegantResponse -workDir $workDir -lteFile $lteFile -beamlineName $beamlineName \
		       -latticeParamFileList $latticeParamFileList -twiFile $twiFile \
                       -hrmFile $hrmFile -vrmFile $vrmFile -hCorrList $hCorrList -vCorrList $vCorrList \
                       -fixedOrbitLength $fixedOrbitLength -coupledMatrix $coupledMatrix \
		       -useResponseFromOrbits $useResponseFromOrbits -verbose $verbose \
		       -useQsub $useQsub -qsubCommand $qsubCommand -numberOfQsubTasks $numberOfQsubTasks \
		       -waitInterval $waitInterval -waitTime $waitTime -accelCode elegant  -kickX $kickX -kickY $kickY \
		       -accelCodeBinDir $accelCodeBinDir -includeTwissCalc $includeTwissCalc} result] {
            return -code error "NondirectElegantResponse: $result"
        }
	#--- Adding $dispColumn for dispersion fitting.
	if $fitDispersion {
	    if [catch {AddDispersionColumn -hrmFile $hrmFile -vrmFile $vrmFile -hrmXFile $hrmFile.XRM -vrmXFile $vrmFile.XRM \
			   -twiFile $twiFile -dispColumn $dispColumn -closedOrbit $closedOrbit \
			   -dispFitWeight $dispFitWeight -coupledMatrix $coupledMatrix} result] {
		return -code error "AddDispersionColumn: $result"
	    }
	}
    }
}

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

proc CalculateElegantBetas {args} {
    global tmpDir bRho
    #------ don't always want to supply reference file
    set deleteFiles ""
    set closedOrbit 1
    set twissRefFile ""
    set twissRefElement ""
    APSParseArguments {lteFile beamlineName latticeParamFileList twiFile workDir accelCodeBinDir \
			    closedOrbit twissRefFile twissRefElement fixedOrbitLength}
    set tmpRoot $tmpDir/[APSTmpString]-calculateElegantBetas
    set eleFile $tmpRoot.ele
    lappend deleteFiles $eleFile
    set localClosedOrbit $closedOrbit
    if {!$closedOrbit && (![string length $twissRefFile] || ![string length $twissRefElement])} {
	return -code error "Error: twissRefFile and/or twissRefElement are empty for closedOrbit=0 option."
    }
    #------ output_at_each_step is required to calculate twiss parameters on new orbit.
    set energy [format %10.4e [expr $bRho * 299792458e-6]]
    if $closedOrbit {
	set twissOption [list "filename $twiFile matched $closedOrbit output_at_each_step 1"]
	#------ Fixed_length=0 for beta function calculations only
	if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		       -run_setup [list "lattice $lteFile use_beamline $beamlineName default_order 2 p_central_mev $energy"] \
		       -load_parameters [list "filename_list \"$latticeParamFileList\""] \
		       -run_control [list "n_steps 1"] \
		       -closed_orbit [list "fixed_length 0"] \
		       -twiss_output $twissOption \
		       -bunched_beam [list "n_particles_per_bunch 1"] \
		   } result] {
	    return -code error "Fit_GenerateElegantFileFromLTE1: $result"
	}
    } else {
	set twissOption [list "filename $twiFile matched $localClosedOrbit reference_file $twissRefFile reference_element $twissRefElement"]
	if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		       -run_setup [list "lattice $lteFile use_beamline $beamlineName default_order 2 p_central_mev $energy"] \
		       -load_parameters [list "filename_list \"$latticeParamFileList\""] \
		       -run_control [list "n_steps 1"] \
		       -twiss_output $twissOption \
		       -bunched_beam [list "n_particles_per_bunch 1"] \
		   } result] {
	    return -code error "Fit_GenerateElegantFileFromLTE1: $result"
	}
    }
    set elegantOutFile $tmpRoot.log
    if [catch {exec $accelCodeBinDir/elegant $eleFile > $elegantOutFile} result] {
        return -code error "Error running elegant with file $eleFile (see $elegantOutFile): $result"
    }
    lappend deleteFiles $elegantOutFile

    #------ Running elegant again to calculate etax starting from 0 (measurement for beamline):
    if !$closedOrbit {
	set betaValues [exec sddsprocess $twissRefFile -pipe=out -match=col,ElementName=$twissRefElement \
			    | sdds2stream -pipe=in -col=betax,betay]
	if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
		       -run_setup [list "lattice $lteFile use_beamline $beamlineName default_order 2 p_central_mev $energy"] \
		       -load_parameters [list "filename_list \"$latticeParamFileList\""] \
		       -twiss_output [list "filename $twiFile.tmpDisp matched $localClosedOrbit beta_x [lindex $betaValues 0] beta_y [lindex $betaValues 1] eta_x 0.0"] \
		       -run_control [list "n_steps 1"] \
		       -bunched_beam [list "n_particles_per_bunch 1"] \
		   } result] {
	    return -code error "Fit_GenerateElegantFileFromLTE1: $result"
	}
	set elegantOutFile $tmpRoot.log
	if [catch {exec $accelCodeBinDir/elegant $eleFile > $elegantOutFile} result] {
	    return -code error "Error running elegant with file $eleFile (see $elegantOutFile): $result"
	}
	exec sddsxref $twiFile $twiFile.tmpDisp -take=etax,etay -rename=col,etax=etax_0 -rename=col,etay=etay_0 -nowarning
	lappend deleteFiles ${twiFile}~ $twiFile.tmpDisp
    }
    eval file delete $deleteFiles
}

#----------------------------------------------------------------------------------------------------------------------------
#--- inputFile is multipage file where each page is orbit due to one of correctors

proc Make2pageOrbitFileElegant { args } {
    global tmpDir
    APSParseArguments { inputFile outputFile correctorFile closedOrbit useDoubleOrbits }
    
    #--- Normal response matrix (Page 1 is x-orbit at x-bpms; Page 2 is y-orbit at y-bpms):
    #--- Cross  response matrix (Page 1 is y-orbit at x-bpms; Page 2 is x-orbit at y-bpms):
    
    set tmpRoot $tmpDir/[APSTmpString]-2pageOrbitFile
    set bpmTypeList [list HMON VMON HMON VMON]
    set planeList [list X Y X Y]
    set bpmPlaneList [list X Y X Y]
    set orbitPlaneList [list X Y Y X]
    if $closedOrbit {set orbitColumnList [list x y y x]} else {set orbitColumnList [list Cx Cy Cy Cx]}
    set outputList [list $tmpRoot.1 $tmpRoot.2 $tmpRoot.3 $tmpRoot.4]
    set deleteFiles ""
    
    if $useDoubleOrbits {
	foreach bpmType $bpmTypeList plane $planeList bpmPlane $bpmPlaneList orbitPlane $orbitPlaneList \
	    orbitColumn $orbitColumnList output $outputList {
		set localTmpRoot $tmpRoot-$orbitPlane-$bpmPlane
		exec sddsprocess $inputFile -pipe=out "-match=col,ElementType=$bpmType,ElementType=MONI,|" \
		    | sddsconvert -pipe -retain=col,ElementName,$orbitColumn \
		    | sddsprocess -pipe=in $localTmpRoot.all "-def=para,PageIndex,i_page 2 / i_page 2 / int -"
		exec sddsprocess $localTmpRoot.all $localTmpRoot.1 -filter=para,PageIndex,0.4,0.6
		exec sddsprocess $localTmpRoot.all $localTmpRoot.2 -filter=para,PageIndex,-0.1,0.1
		exec sddsprocess $correctorFile $localTmpRoot.corr "-def=para,PageIndex,i_page 2 / i_page 2 / int -" \
		    -filter=para,PageIndex,0.4,0.6
		#------ Next command is to get some impression of nonlinearity of response:
		if [catch {lindex [lsort -real -decreasing [join [exec sddsxref $localTmpRoot.1 $localTmpRoot.2 -pipe=out \
								      -take=$orbitColumn -rename=col,$orbitColumn=${orbitColumn}1 \
								      | sddsprocess -pipe "-redef=col,Delta,$orbitColumn ${orbitColumn}1 +" \
								      -process=Delta,standard,StDev -process=Delta,max,Max \
								      | sdds2stream -pipe=in -para=StDev]] ] 0} maxStDev] {
		    return -code error "Error calculating maximum stdev (file1: $localTmpRoot.1; file2: $localTmpRoot.2; orbitColumn: $orbitColumn): $maxStDev"
		}
		exec sddschanges $localTmpRoot.1 -pipe=out -base=$localTmpRoot.2 -change=$orbitColumn \
		    -parallelPages -copy=ElementName \
		    | sddstranspose -pipe -newColumn=ElementName -oldColumn=Orbit \
		    | sddsxref -pipe $localTmpRoot.corr -leave=* -transfer=para,ColumnName \
		    | sddsprocess -pipe -print=col,Corrector,%s,ColumnName \
		    | sddscombine -pipe -merge \
		    | sddstranspose -pipe -newColumn=Corrector -oldColumn=ElementName \
		    | sddsconvert -pipe -del=para,* \
		    | sddsprocess -pipe=in $output -reprint=para,Plane,$plane -reprint=para,BpmPlane,$bpmPlane \
		    -reprint=para,OrbitPlane,$orbitPlane -def=para,MaxNonlinStDev,$maxStDev
		lappend deleteFiles $output $localTmpRoot.all $localTmpRoot.1 $localTmpRoot.2 $localTmpRoot.corr
	    }
    } else {
	foreach bpmType $bpmTypeList plane $planeList bpmPlane $bpmPlaneList orbitPlane $orbitPlaneList \
	    orbitColumn $orbitColumnList output $outputList {
		exec sddsprocess $inputFile -pipe=out "-match=col,ElementType=$bpmType,ElementType=MONI,|" \
		    | sddsconvert -pipe -retain=col,ElementName,$orbitColumn \
		    | sddstranspose -pipe -newColumn=ElementName -oldColumn=Orbit \
		    | sddsxref -pipe $correctorFile -leave=* -transfer=para,ColumnName \
		    | sddsprocess -pipe -print=col,Corrector,%s,ColumnName \
		    | sddscombine -pipe -merge \
		    | sddstranspose -pipe -newColumn=Corrector -oldColumn=ElementName \
		    | sddsconvert -pipe -del=para,* \
		    | sddsprocess -pipe=in $output -reprint=para,Plane,$plane -reprint=para,BpmPlane,$bpmPlane \
		    -reprint=para,OrbitPlane,$orbitPlane -def=para,MaxNonlinStDev,0
		lappend deleteFiles $output
	    }
    }
    exec sddscombine $tmpRoot.1 $tmpRoot.2 $outputFile -overWrite
    exec sddscombine $tmpRoot.3 $tmpRoot.4 $outputFile.XRM -overWrite
    eval file delete $deleteFiles
}

#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#------ Common procedures ---------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------

proc AddDispersionColumn {args} {
    global tmpDir
    APSParseArguments { hrmFile vrmFile hrmXFile vrmXFile twiFile dispColumn dispFitWeight coupledMatrix closedOrbit }
    set tmpRoot $tmpDir/[APSTmpString]-addDisp

    if $closedOrbit {
	set etaxCol etax; set etayCol etay
    } else {
	set etaxCol etax_0; set etayCol etay_0
    }
    exec sddsconvert $twiFile $tmpRoot.dx -retain=col,ElementName,$etaxCol -rename=col,$etaxCol=$dispColumn
    exec sddsconvert $twiFile $tmpRoot.dy -retain=col,ElementName,$etayCol -rename=col,$etayCol=$dispColumn
    lappend tmpFileList $tmpRoot.dx $tmpRoot.dy
    switch -regexp -- $coupledMatrix {
	0 {
	    set dispFile $tmpRoot.dx
	    set dispFileCrossRM $tmpRoot.dy
	}
	1 {
	    set dispFile $tmpRoot.dy
	    set dispFileCrossRM $tmpRoot.dx
	}
	2 {
	    exec sddscombine $tmpRoot.dx $tmpRoot.dy $tmpRoot.d1 -overWrite
	    exec sddscombine $tmpRoot.dy $tmpRoot.dx $tmpRoot.d2 -overWrite
	    set dispFile $tmpRoot.d1
	    set dispFileCrossRM $tmpRoot.d2
	    lappend tmpFileList $tmpRoot.d1 $tmpRoot.d2
	}
    }

    exec sddsxref $hrmFile $dispFile -pipe=out -nowarning -take=$dispColumn -match=BPMName=ElementName \
	| sddsprocess -pipe=in $tmpRoot.hrm "-redef=col,$dispColumn,$dispColumn $dispFitWeight *"
    file copy -force $tmpRoot.hrm $hrmFile
    if [file exists $hrmXFile] {
	exec sddsxref $hrmXFile $dispFileCrossRM -pipe=out -nowarning -take=$dispColumn -match=BPMName=ElementName \
	    | sddsprocess -pipe=in $tmpRoot.hrm.XRM "-redef=col,$dispColumn,$dispColumn $dispFitWeight *"
	file copy -force $tmpRoot.hrm.XRM $hrmXFile
    }
    eval file delete $tmpFileList $tmpRoot.hrm $tmpRoot.hrm.XRM
}

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

proc Truncate2pageFiles {args} {
    APSParseArguments {hrmFile vrmFile coupledMatrix}
    if {$coupledMatrix == 2} { return }
    switch -exact -- $coupledMatrix {
        0 { set pageX 1; set pageY 2 }
	1 { set pageX 2; set pageY 1 }
    }
    if [llength $hrmFile] {
	exec sddsconvert $hrmFile -nowarning -keepPage=$pageX
	exec sddsconvert $hrmFile.XRM -nowarning -keepPage=$pageX
	file delete $hrmFile~ $hrmFile.XRM~
    }
    if [llength $vrmFile] {
	exec sddsconvert $vrmFile -nowarning -keepPage=$pageY
	exec sddsconvert $vrmFile.XRM -nowarning -keepPage=$pageY
	file delete $vrmFile~ $vrmFile.XRM~
    }
}

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

proc SplitMultipageFile {args} {
    global tmpDir
    APSParseArguments {filename splitTasks}
    set tmpRoot $tmpDir/[APSTmpString]-splitMultipageFile
    set fileList ""
    if [catch {exec sdds2stream $filename -npages=bare} nPages] {return -code error $nPages}
    #--- When nPages is less than splitTasks, the split algorithm below does not work, so we redefine splitTaks
    if {[expr $nPages / 2] < $splitTasks} {set splitTasks [expr int($nPages / 2)]}
    set fullFileSize [exec rpnl "$nPages $splitTasks / int "]
    set remainder [exec rpnl "$nPages $nPages $splitTasks / int $splitTasks * -"]
    set counter 0
    set page2 0
    for {set i 0} {$i < $splitTasks} {incr i} {
	if {$i == [expr $splitTasks - 1]} {
	    set page1 [expr $page2 + 1]
	    set page2 $nPages
	} else {
	    set page1 [expr $page2 + 1]
	    set page2 [expr $page2 + $fullFileSize]
	    if {$counter < $remainder} {incr page2}
	    incr counter
	    #------ Only even number of pages - for double orbits:
	    if {[exec rpnl "$page2 $page1 - 1 + 2 / $page2 $page1 - 1 + 2 / int -"] != 0} {
		incr page2
		incr counter
	    }
	    if {$page2 == $nPages} {break}
	}
	exec sddsprocess $filename $tmpRoot.$i -def=para,PageNumber,i_page -filter=para,PageNumber,$page1,$page2
	lappend fileList $tmpRoot.$i
    }
    return $fileList
}

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

proc CalculateDirectRM {args} {

    global tmpDir locoBinDir

    #--- Here for empty variables I need "dummy" because APSParseArguments doesn't work with commandOptions
    set rmDivFactor 1
    set sddsLatticeFile "dummy"
    set nonlin "0"
    set useQsub 0
    set waitInterval 5
    set waitTime 600
    set bRho "dummy"
    set locoSearchString ""
    set fixedOrbitLength "dummy"
    set verbose 0
    set closedOrbit 1
    set optimFile ""
    set kickFileX dummy
    set kickFileY dummy
    APSParseArguments {lteFile beamlineName latticeParamFileList optimFile \
			   sddsLatticeFile hrmFile vrmFile nonlin hCorrList vCorrList workDir useQsub coupledMatrix \
                           fitDispersion dispColumn dispFitWeight twiFile bRho kickX kickY locoSearchString \
			   qsubCommand numberOfQsubTasks waitInterval waitTime accelCode fixedOrbitLength \
			   accelCodeBinDir verbose closedOrbit useDoubleOrbits twissRefFile twissRefElement malignElement \
			   useKickFiles kickFileX kickFileY}

    set refCorr ReferenceCorrector
    set tmpRoot $tmpDir/[APSTmpString]-calcDirectRM
    set counter 0
    set planeList [list X Y]
    set rmFileList [list $hrmFile $vrmFile]
    if !$useDoubleOrbits {
	set corListList [list [concat $refCorr $hCorrList] [concat $refCorr $vCorrList]]
    } else {
	set corListList [list $hCorrList $vCorrList]
    }
    set kickListMain [list [expr $kickX / $rmDivFactor] [expr $kickY / $rmDivFactor]]
    set kickFileList [list $kickFileX $kickFileY]

    switch -exact $accelCode {
	elegant { set toMeters 1.0; set rmFileRoot rm.ele }
	optim { set toMeters 1000.0; set rmFileRoot rm.opt }
	default { return -code error "Wrong accelCode value: $accelCode" }
    }
    set scriptName $locoBinDir/calculateResponseMatrix
    set dqsWorkDir $workDir/dqs/orbit
    set rootJobName orbit
    set totalPathList ""
    set jobNameList ""
    set doneFileList ""
    set commandList ""
    catch {exec /bin/rm -r $dqsWorkDir}
    if ![file exists $workDir/dqs] { exec mkdir $workDir/dqs }
    if ![file exists $dqsWorkDir]  { exec mkdir $dqsWorkDir }
    foreach plane $planeList rmFile $rmFileList corList $corListList kick $kickListMain kickFile $kickFileList {
	if [llength $corList] {
	    set fileList$plane ""
	    if $useKickFiles {
		if [catch {SplitMultipageFile -filename $kickFile -splitTasks $numberOfQsubTasks} listAfterSplitting] {
		    return -code error "Fit_SplitList: $listAfterSplitting"
		}
	    } else {
		if [catch {Fit_SplitList -List $corList -splitTasks $numberOfQsubTasks} listAfterSplitting] {
		    return -code error "Fit_SplitList: $listAfterSplitting"
		}
	    }
	    foreach taskList $listAfterSplitting {
		incr counter
		set totalPath $dqsWorkDir/$counter
		catch {file delete $totalPath} 
		catch {exec mkdir $totalPath}
		set jobName $rootJobName$counter
		set orbitFile $totalPath/orbit.sdds
		set correctorFile $totalPath/rmTemplate.param
		set rmLatticeFile $totalPath/$rmFileRoot
		if [catch {MakeFileForOrbitCalcs -accelCode $accelCode -lteFile $lteFile -beamlineName $beamlineName \
			       -latticeParamFileList $latticeParamFileList -optimFile $optimFile \
			       -rmLatticeFile $rmLatticeFile -closedOrbit $closedOrbit \
			       -correctorFile $correctorFile -locoSearchString $locoSearchString} result] {
		    return -code error "MakeFileForOrbitCalcs: $result"
		}
		set commandOptions "-runMode runCalculateOrbits -accelCode $accelCode -latticeFile $rmLatticeFile -orbitFile $orbitFile "
		append commandOptions "-tmpDir $tmpDir -workDir $totalPath -nonlin $nonlin -correctorFile $correctorFile "
		append commandOptions "-corrList \"$taskList\" -kick $kick -sddsLatticeFile $sddsLatticeFile "
		append commandOptions "-bRho $bRho -locoBinDir $locoBinDir -closedOrbit $closedOrbit "
		append commandOptions "-accelCodeBinDir $accelCodeBinDir -fixedOrbitLength $fixedOrbitLength "
		append commandOptions "-useDoubleOrbits $useDoubleOrbits -refCorr $refCorr -useKickFiles $useKickFiles "
		if $useKickFiles {
		    file copy -force $taskList $correctorFile
		    file delete $taskList
		}
		set command "$scriptName "
		append command $commandOptions
		lappend totalPathList $totalPath
		lappend jobNameList $jobName
		lappend doneFileList $totalPath/task.completed
		lappend commandList $command
		lappend fileList$plane $orbitFile
		#--- If not useQsub - run jobs one by one right here:
		if !$useQsub {
		    if [catch {eval exec $command} result] {
			return -code error "$scriptName: $result"
		    }
		}
	    }
	}
    }

    if $useQsub {
	if [catch {Fit_SubmitJobs -commandList $commandList -jobNameList $jobNameList -doneFileList $doneFileList \
		       -verbose $verbose} returnList] {
	    return -code error "Fit_SubmitJobs: $returnList"
	}
	set pidList [lindex $returnList 0]
	set logFileList [lindex $returnList 1]
	if [catch {Fit_WaitForTasks_New -pidList $pidList -jobNameList $jobNameList -commandList $commandList \
		       -logFileList $logFileList -doneFileList $doneFileList -waitSec $waitTime \
		       -waitInterval $waitInterval -usePopupWindow 0 \
		       -useQsub $useQsub -abortFile [APSTmpString] \
		       -verbose $verbose} result] {
	    return -code error "Fit_WaitForTasks_New: $result"
	}
    }

    set fileListXcrossRM ""
    set fileListYcrossRM ""
    foreach filename $fileListX {lappend fileListXcrossRM $filename.XRM}
    foreach filename $fileListY {lappend fileListYcrossRM $filename.XRM}
    set rmFileListCrossRM [list [lindex $rmFileList 0] [lindex $rmFileList 1] [lindex $rmFileList 0].XRM \
			       [lindex $rmFileList 1].XRM]
    set kickListCrossRM [list [lindex $kickListMain 0] [lindex $kickListMain 1] [lindex $kickListMain 0] \
			     [lindex $kickListMain 1]]
    #------ Next commands to find maximum nonlinearity parameter:
    set tmpList ""
    foreach filename $fileListX { lappend tmpList [lindex [exec sdds2stream $filename -para=MaxNonlinStDev] 0]}
    set maxNonlinStdX [lindex [lsort -real -decreasing $tmpList] 0]
    set tmpList ""
    foreach filename $fileListY { lappend tmpList [lindex [exec sdds2stream $filename -para=MaxNonlinStDev] 0]}
    set maxNonlinStdY [lindex [lsort -real -decreasing $tmpList] 0]
    #------ End of "find maximum nonlinearity parameter".
    foreach fileList [list $fileListX $fileListY $fileListXcrossRM $fileListYcrossRM] \
	rmFile $rmFileListCrossRM kick $kickListCrossRM maxStDev \
	[list $maxNonlinStdX $maxNonlinStdY $maxNonlinStdX $maxNonlinStdY] {
	    if {[llength $fileList] > 1} {
		eval exec sddsxref -nowarning $fileList $tmpRoot.xref -leave=ElementName 
	    } else {
		file copy -force $fileList $tmpRoot.xref
	    }
	    #--- Factor toMeters is 1000 for optim (optim orbit is in mm) and 1 for elegant (elegant orbit is in m).
	    if $useDoubleOrbits {
		#------ divide by additional 2
		if [catch {exec sddsprocess $tmpRoot.xref -pipe=out \
			       "-redef=col,%s,%s $kick / $toMeters / 2 /,select=*,exclude=ElementName,units=mm/mrad" \
			       -redef=para,Kick,$kick -redef=para,MaxNonlinStDev,$maxStDev \
			       | sddsconvert -pipe=in $rmFile -rename=col,ElementName=BPMName} result] {
		    return -code error "Error combining orbit files: $result"
		}
	    } else {
		if [catch {exec sddsconvert $tmpRoot.xref -pipe=out -del=col,ElementName \
			       | sddsprocess -pipe \
			       "-redef=col,%s,%s $refCorr - $kick / $toMeters /,select=*,exclude=$refCorr,units=mm/mrad" \
			       -redef=para,Kick,$kick \
			       | sddsconvert -pipe -del=col,$refCorr \
			       | sddsxref -pipe=in [lindex $fileList 0] $rmFile -take=ElementName \
			       -rename=col,ElementName=BPMName} result] {
		    return -code error "Error combining orbit files: $result"
		}
	    }
	}
    file delete $tmpRoot.xref
    foreach path $totalPathList {
	catch {eval file delete [glob -nocomplain -- $path/*]}
	catch {file delete $path}
    }
    if [catch {Truncate2pageFiles -coupledMatrix $coupledMatrix -hrmFile $hrmFile -vrmFile $vrmFile} result] {
        return -code error "Truncate2pageFiles: $result"
    }

    #--- Adding $dispColumn for dispersion fitting.
    if $fitDispersion {
        if [catch {AddDispersionColumn -hrmFile $hrmFile -vrmFile $vrmFile -hrmXFile $hrmFile.XRM -vrmXFile $vrmFile.XRM \
		       -twiFile $twiFile -dispColumn $dispColumn -closedOrbit $closedOrbit \
                       -dispFitWeight $dispFitWeight -coupledMatrix $coupledMatrix} result] {
            return -code error "AddDispersionColumn: $result"
        }
    }
}

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

proc MakeFileForOrbitCalcs { args } {
    global bRho
    APSParseArguments { accelCode lteFile beamlineName latticeParamFileList optimFile rmLatticeFile correctorFile \
			    locoSearchString closedOrbit }
    switch -exact $accelCode {
	elegant {
	    set energy [format %10.4e [expr $bRho * 299792458e-6]]
	    if $closedOrbit {
		set latticeOption [list "lattice $lteFile use_beamline $beamlineName p_central_mev $energy"]
		set orbitOption [list "output <ORBITFILE> output_monitors_only 1 fixed_length <FIXEDORBITLENGTH>"]
	    } else {
		set latticeOption [list "lattice $lteFile use_beamline $beamlineName centroid <ORBITFILE> p_central_mev $energy"]
		set orbitOption ""
	    }
	    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $rmLatticeFile \
			   -run_setup $latticeOption \
			   -load_parameters [list "filename_list \"$latticeParamFileList\"" \
						 "filename $correctorFile change_defined_values 0"] \
			   -closed_orbit $orbitOption \
			   -run_control [list "n_steps <NSTEPS>"] \
			   -bunched_beam [list "n_particles_per_bunch 1"] \
		       } result] {
		return -code error "Fit_GenerateElegantFileFromLTE: $result"
	    }
	}
	optim {
	    if !$closedOrbit {return -code error "Optim calculations with not-closed orbit are not working."}
	    if [catch {Fit_AddLine -inputFile $optimFile -outputFile $rmLatticeFile -searchString $locoSearchString \
			   -includeString "\#include $correctorFile" -substitute 0} result] {
		return -code error "Fit_AddLine: $result"
	    }
	}
	default { return -code error "Wrong accelCode value: $accelCode" }
    }
}

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

proc MakeSddsLattice { args } {
    global tmpDir bRho
    set tmpRoot $tmpDir/[APSTmpString]-makeSddsLattice
    APSParseArguments { lteFile beamlineName latticeParamFileList optimFile accelCode accelCodeBinDir \
			    workDir sddsLatticeFile }
    switch -regexp -- $accelCode {
        elegant {
	    set eleFile $tmpRoot.ele
	    set twiFile $tmpRoot.twi
	    set paramFile $tmpRoot.param
	    set energy [format %10.4e [expr $bRho * 299792458e-6]]
	    if [catch {Fit_GenerateElegantFileFromLTE1 -eleOutputFile $eleFile \
			   -run_setup [list "lattice $lteFile use_beamline $beamlineName parameters $paramFile p_central_mev $energy"] \
			   -load_parameters [list "filename_list \"$latticeParamFileList\""] \
			   -twiss_output [list "filename $twiFile"] \
			   -run_control [list "n_steps 1"] \
			   -bunched_beam [list "n_particles_per_bunch 1"] \
		       } result] {
                return -code error "Fit_GenerateElegantFileFromLTE1: $result"
	    }
            set elegantOutFile $tmpRoot.log
            file delete $elegantOutFile
            if [catch {exec $accelCodeBinDir/elegant $eleFile > $elegantOutFile} result] {
                return -code error "Error running elegant with file \"$eleFile\" (see $elegantOutFile): $result"
            }
            if [catch {exec sddsprocess $paramFile -pipe=out -match=col,ElementParameter=L \
                           | sddsxref -pipe=in $twiFile $sddsLatticeFile -take=s -match=ElementName -nowarning} result] {
                return -code error "Error taking column s from $twiFile to $paramFile: $result"
            }
	    file delete $elegantOutFile $twiFile $paramFile $eleFile
        }
        optim {
            set optimOutFile $tmpRoot-optim.out
            file delete $optimOutFile
            #--- Run optim in -s mode to get Length column.
            if [catch {exec $accelCodeBinDir/optim32 -s $optimFile $tmpRoot.optOut.s > $optimOutFile} result] {
                set optimOutput [exec cat $optimOutFile]
                return -code error "Error running optim -s: Optim output:\n $optimOutput"
            }
            if [catch {Optim2sdds -optimMode s -inputFile $tmpRoot.optOut.s -outputFile $tmpRoot.sdds.s} result] {
                return -code error "Optim2sdds: $result"
            }
            #--- Run optim in -t mode to get full element names.
            if [catch {exec $accelCodeBinDir/optim32 -t $optimFile $tmpRoot.optOut.t > $optimOutFile} result] {
                return -code error "Error running optim -t: look in $optimOutFile file"
            }
            if [catch {Optim2sdds -optimMode t -inputFile $tmpRoot.optOut.t -outputFile $tmpRoot.sdds.t} result] {
                return -code error "Optim2sdds: $result"
            }
            file delete $tmpRoot.optOut.s $tmpRoot.optOut.t
            
            exec sddsxref -nowarning $tmpRoot.sdds.t $tmpRoot.sdds.s $sddsLatticeFile -take=Length \
                -match=ElementName -fillIn
            file delete $tmpRoot.sdds.t $tmpRoot.sdds.s $optimOutFile
        }
        default {
            return -code error "Accelerator code $accelCode is not recognized."
        }
    }
}

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

proc CalculateOrbits { args } {
    global tmpDir
    APSParseArguments {accelCode latticeFile orbitFile workDir tmpDir nonlin correctorFile corrList kick \
			    sddsLatticeFile bRho accelCodeBinDir fixedOrbitLength closedOrbit refCorr useDoubleOrbits useKickFiles}
    set tmpRoot $tmpDir/[APSTmpString]-orbit
    #------ Make kick list:
    if $useDoubleOrbits {
	set kickList ""
	foreach corr $corrList {lappend kickList $kick -$kick}
	foreach corr $corrList {lappend corrList1 $corr $corr}
	set corrList $corrList1
    } else {
	set kickList ""
	foreach corr $corrList {
	    if {[string compare $corr $refCorr] == 0} {lappend kickList 0} else {lappend kickList $kick}
	}
    }
    switch -exact $accelCode {
	elegant {
	    if !$useKickFiles {
		if [catch {MakeKickFile -correctorFile $correctorFile -corrList $corrList -kickList $kickList \
			       -tmpDir $tmpDir} result] {
		    return -code error "MakeKickFile: $result"
		}
		set Nsteps [llength $corrList]
	    } else {
		set Nsteps [exec sdds2stream $correctorFile -npages=bare]
	    }
	    set elegantOutFile $tmpRoot.out
	    catch {file delete $elegantOutFile}
	    if [catch {exec $accelCodeBinDir/elegant $latticeFile \
			   -macro=NSTEPS=$Nsteps,ORBITFILE=$orbitFile.eleg,FIXEDORBITLENGTH=$fixedOrbitLength \
			   > $elegantOutFile} result] {
		return -code error "Error running elegant with file $latticeFile (look in $elegantOutFile file): $result"
	    } else {
		file delete $elegantOutFile
	    }
	    #------ Check if any particle was lost:

	    if [catch {Make2pageOrbitFileElegant -inputFile $orbitFile.eleg -outputFile $orbitFile \
			   -correctorFile $correctorFile -closedOrbit $closedOrbit \
			   -useDoubleOrbits $useDoubleOrbits} result] {
		return -code error "Make2pageOrbitFileElegant: $result"
	    }
	}
	optim {
	    set orbitFileList1 ""
	    set orbitFileList2 ""
	    foreach corrName $corrList kick $kickList {
		if [catch {SetKick -correctorFile $correctorFile -corrName $corrName -kick $kick \
			       -sddsLatticeFile $sddsLatticeFile -bRho $bRho} result] {
		    return -code error "SetKick: $result"
		}
		if [catch {GetOrbit -latticeFile $latticeFile -orbitFile $tmpRoot.tmp -tmpDir $tmpDir \
			       -accelCodeBinDir $accelCodeBinDir -nonlin $nonlin -workDir $workDir} result] {
		    return -code error "GetOrbit: $result"
		}
		if [catch {Make2pageOrbitFileOptim -inputFile $tmpRoot.tmp -outputFile $tmpRoot.$corrName \
			       -columnName $corrName} result] {
		    return -code error "Make2pageOrbitFileOptim: $result"
		}
		lappend orbitFileList1 $tmpRoot.$corrName
		lappend orbitFileList2 $tmpRoot.$corrName.XRM
		file delete $tmpRoot.tmp $correctorFile
	    }
	    if {[llength $orbitFileList1] == 1} {
		file copy -force $orbitFileList $orbitFile
	    } else {
		eval exec sddsxref $orbitFileList $orbitFile -leave=ElementName
	    }
	    if {[llength $orbitFileList2] == 1} {
		file copy -force $orbitFileList $orbitFile.XRM
	    } else {
		eval exec sddsxref $orbitFileList $orbitFile.XRM -leave=ElementName
	    }
	    eval file delete $orbitFileList1 $orbitFileList2
	}
	default { return -code error "Wrong accelCode value: $accelCode" }
    }
}

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

proc MakeKickFile { args } {
    APSParseArguments { correctorFile corrList kickList }
    exec sddsmakedataset -pipe=out \
	-col=ElementName,type=string -data=[join $corrList ,] \
	-col=ParameterValue,type=double -data=[join $kickList ,] \
	| sddsprocess -pipe -print=col,ElementParameter,KICK -print=col,ParameterMode,differential \
	| sddsbreak -pipe -rowLimit=1 \
	| sddsprocess -pipe=in $correctorFile -process=ElementName,first,ColumnName
}


#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#--- Main program body ------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------

switch -exact $runMode {
    getSDDSLattice {
	if [catch {MakeSddsLattice -lteFile $lteFile -beamlineName $beamlineName -latticeParamFileList $latticeParamFileList \
		       -optimFile $optimFile -accelCode $acceleratorCode -workDir $workDir \
		       -sddsLatticeFile $sddsLatticeFile -accelCodeBinDir $accelCodeBinDir} result] {
	    puts stderr "MakeSddsLattice: $result \n Calling argument: $rememberArgs"; exit
	}
    }
    getBetaFunctions {
	switch -exact $acceleratorCode {
	    elegant {
		if [catch {CalculateElegantBetas -lteFile $lteFile -beamlineName $beamlineName \
			       -latticeParamFileList $latticeParamFileList -twiFile $twiFile -workDir $workDir \
			       -accelCodeBinDir $accelCodeBinDir -closedOrbit $closedOrbit \
			       -twissRefFile $twissRefFile -twissRefElement $twissRefElement \
			       -fixedOrbitLength $fixedOrbitLength} result] {
		    puts stderr "CalculateElegantBetas: $result \n Calling argument: $rememberArgs"; exit
		}
	    }
	    optim {
		if [catch {CalculateOptimBetas -optimFile $optimFile -twiFile $twiFile -workDir $workDir \
			       -fourD 1 -accelCodeBinDir $accelCodeBinDir} result] {
		    puts stderr "CalculateOptimBetas: $result \n Calling argument: $rememberArgs"; exit
		}
	    }
	}
    }
    getResponseMatrix {
	switch -exact $acceleratorCode {
	    elegant {
		if [string length $twiFile] {
		    #------ If not closed orbit, dispersion has to be calculated starting from zero. It requires special attention.
		    #------ Therefore use separate procedure. If not, twiss file is calculated as part of RM for speed.
		    if {!$closedOrbit || $directCalc == 1} {
			if [catch {CalculateElegantBetas -lteFile $lteFile -beamlineName $beamlineName \
				       -latticeParamFileList $latticeParamFileList -twiFile $twiFile -workDir $workDir \
				       -accelCodeBinDir $accelCodeBinDir -closedOrbit $closedOrbit \
				       -twissRefFile $twissRefFile -twissRefElement $twissRefElement \
				       -fixedOrbitLength $fixedOrbitLength} result] {
			    puts stderr "CalculateElegantBetas: $result \n Calling argument: $rememberArgs"; exit
			}
			set includeTwissCalc 0
		    } else {
			set includeTwissCalc 1
		    }
		}
                if [catch {CalculateElegantRM -lteFile $lteFile -beamlineName $beamlineName \
			       -latticeParamFileList $latticeParamFileList -hrmFile $hrmFile -vrmFile $vrmFile \
                               -hCorrList $hCorrList -vCorrList $vCorrList -directCalc $directCalc \
                               -fixedOrbitLength $fixedOrbitLength -kickX $kickX -kickY $kickY \
                               -workDir $workDir -twiFile $twiFile -coupledMatrix $coupledMatrix \
                               -fitDispersion $fitDispersion -dispFitWeight $dispFitWeight -dispColumn $dispColumn \
			       -useQsub $useQsub -numberOfQsubTasks $numberOfQsubTasks \
			       -waitInterval $waitInterval -waitTime $waitTime -qsubCommand $qsubCommand \
			       -accelCodeBinDir $accelCodeBinDir -closedOrbit $closedOrbit \
			       -twissRefFile $twissRefFile -twissRefElement $twissRefElement -malignElement $malignElement \
			       -useKickFiles $useKickFiles -kickFileX $kickFileX -kickFileY $kickFileY \
			       -includeTwissCalc $includeTwissCalc \
			       -useDoubleOrbits $useDoubleOrbits -verbose $verbose} result] { 
		    puts stderr "CalculateElegantRM: $result \n Calling argument: $rememberArgs"; exit
                }
	    }
	    optim {
		set sddsLatticeFile $workDir/[file tail $optimFile].sdds
		if [catch {MakeSddsLattice -optimFile $optimFile -accelCode $acceleratorCode -workDir $workDir \
			       -sddsLatticeFile $sddsLatticeFile -accelCodeBinDir $accelCodeBinDir} result] {
		    puts stderr "MakeSddsLattice: $result \n Calling argument: $rememberArgs"; exit
		}
		if [string length $twiFile] {
		    #--- For now we run beta calculations without nonlin option but with 4D (see procedure). 
		    if [catch {CalculateOptimBetas -optimFile $optimFile -twiFile $twiFile -workDir $workDir \
				   -fourD 1 -accelCodeBinDir $accelCodeBinDir} result] {
			puts stderr "CalculateOptimBetas: $result \n Calling argument: $rememberArgs"; exit
		    }
		}
		if [catch {CalculateOptimRM -optimFile $optimFile -sddsLatticeFile $sddsLatticeFile \
			       -hrmFile $hrmFile -vrmFile $vrmFile -hCorrList $hCorrList -vCorrList $vCorrList \
			       -nonlin $optimNonlin -coupledMatrix $coupledMatrix -workDir $workDir -twiFile $twiFile \
			       -bRho $bRho -kickX $kickX -kickY $kickY -locoSearchString $locoSearchString \
			       -fitDispersion $fitDispersion -dispFitWeight $dispFitWeight -dispColumn $dispColumn \
			       -useQsub $useQsub -numberOfQsubTasks $numberOfQsubTasks \
			       -waitInterval $waitInterval -waitTime $waitTime -qsubCommand $qsubCommand \
			       -accelCodeBinDir $accelCodeBinDir -verbose $verbose} result] {
		    puts stderr "CalculateOptimRM: $result \n Calling argument: $rememberArgs"; exit
		}
		file delete $sddsLatticeFile
	    }
	}
    
	#--- Transfering tunes from twiss file to response files:
	if [string length $twiFile] {
	    set nux [exec sdds2stream $twiFile -para=nux]
	    set nuy [exec sdds2stream $twiFile -para=nuy]
	    if [llength $hCorrList] {
		if {[string length $nux] && [string length $nuy]} {
		    if [catch {exec sddsxref $hrmFile $twiFile $hrmFile.tmp -nowarning -transfer=para,nux,nuy -leave=*} result] {
			return -code error "Error (hrmFile $hrmFile): $result"
		    }
		    file copy -force $hrmFile.tmp $hrmFile
		    file delete $hrmFile.tmp
		} else {
		    puts stderr "optim: Unstable tunes."; exit
		}
	    }
	    if [llength $vCorrList] {
		if {[string length $nux] && [string length $nuy]} {
		    exec sddsxref $vrmFile $twiFile $vrmFile.tmp -nowarning -transfer=para,nux,nuy -leave=*
		    file copy -force $vrmFile.tmp $vrmFile
		    file delete $vrmFile.tmp
		} else {
		    puts stderr "optim: Unstable tunes."; exit
		}
	    }
	}
    }
    runCalculateOrbit {
	if [catch {CalculateOrbits -latticeFile $latticeFile -orbitFile $orbitFile \
		       -workDir $workDir -tmpDir $tmpDir -nonlin $nonlin -correctorFile $correctorFile \
		       -corrList $corrList -kick $kick -sddsLatticeFile $sddsLatticeFile \
		       -bRho $bRho -accelCodeBinDir $accelCodeBinDir -closedOrbit $closedOrbit -refCorr $refCorr \
		       -accelCode $accelCode -fixedOrbitLength $fixedOrbitLength \
		       -useDoubleOrbits $useDoubleOrbits -useKickFiles $useKickFiles} result] {
	    return -code error "CalculateOrbits: $result"
	}
	exec echo END > $workDir/task.completed
    }
}
exit
