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

#
# 

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath
wm geometry . +10+10

set args $argv
set initialConfig ""
if {[APSStrictParseArguments { initialConfig  }] } {
    APSAlertBox [APSUniqueName .] \
      -errorMessage "Invalid arguments."
}

set hFBConfigStatus ""
set vFBConfigStatus ""
set hKp 0.41301
set hKi 2464.2113 
set vKp 0.39621
set vKi 2365.0398
set randomNoise 0
set withDelay 1
set filterTime 0.05
set delay 0.000088
proc CreateFeedbackSimWidget {args} {
    set plane ""
    set parent ""
    APSParseArguments {plane parent}

    global hFBConfigStatus vFBConfigStatus hlattice vlattice hlatticeDir vlatticeDir hsimulationDir vsimulationDir hcorrDir vcorrDir
    global hCorrConfig vCorrConfig hdataDir vdataDir hturns vturns
    global hmissingList vmissingList bpmDataDir largestSingularValues filterFreq cutoffFreq hFBConfig vFBConfig
    global hrootname vrootname smoothPoints filterFreq  hrfFreq vrefFreq hBPMLabelList hBPMItemList vBPMLabelList vBPMItemList
    global hbpmDataDirList vbpmDataDirList hbpmLatticeList vbpmLatticeList hbpmTurnList vbpmTurnList
    global corrLabelList hCorrItemList vCorrItemList hKp hKi vKp vKi randomNoise withDelay filterTime delay

    APSScrolledStatus .status -parent $parent -textVariable ${plane}FBConfigStatus -width 100 -withButtons 1
    APSFrame .f -parent $parent 
    set w $parent.f.frame
    $w configure -bd 0
    
    set bpmItemList [set ${plane}BPMItemList]
    set bpmLabelList [set ${plane}BPMLabelList]
    set corrItemList [set ${plane}CorrItemList]

    set wList [APSTabFrame .tabs -parent $w -width 1150 -height 400 -labelList "Monitors Correctors" -label ""]
    
    APSSRSectorButtons .bpm -parent [lindex $wList 0] -rootname ${plane}FB \
      -label "" -sectorCount 40 -missingList [set ${plane}missingList] \
      -itemList $bpmItemList -itemLabelList $bpmLabelList -description "bpm" \
      -orientation horizontal -sectorControl 1 -packOption "-side left" 
   
    APSSRSectorButtons .bpm -parent [lindex $wList 1] -rootname ${plane}FB \
      -label "" -sectorCount 40 -missingList [set ${plane}missingList] \
      -itemList $corrItemList -itemLabelList $corrLabelList -description "corrector" \
      -orientation horizontal -sectorControl 1 -packOption "-side left" 
    APSSetSRSectorButtons -mode all-off -rootname  ${plane}FB -sectorCount 40 -itemList $bpmItemList
    APSSetSRSectorButtons -mode all-off -rootname  ${plane}FB -sectorCount 40 -itemList $corrItemList
    
    set width 80
    APSFrameGrid .grid -parent $parent -xList {x1 x2}
    set w1 $parent.grid.x1
    set w2 $parent.grid.x2
    set width 20
    APSFileSelectWidget .lattice -parent $w1 -label "Lattice:" -pathVariableList ${plane}latticeDir -mode directory -variable ${plane}lattice -width $width \
      -incrementButtons 0 -contextHelp \
      "Enter the name of the lattice with which to compute the inverse response matrix."
    APSLabeledEntry .sing -parent $w2 -textVariable largestSingularValues -label "Number of singular values:" -width $width
    APSLabeledEntry .turns -parent $w1 -textVariable ${plane}turns -label "Turns:" -width $width -contextHelp \
      "turns skipped in collecting FPGA bpm data."
    APSLabeledEntry .rootname -parent $w2 -textVariable ${plane}rfFreq -label "RF frequency (Hz):" -width $width -contextHelp \
      "RF frequency at collecting data."
    
    APSLabeledEntry .smooth -parent $w1 -textVariable smoothPoints -label "Smooth points:" -width $width -contextHelp \
      "smooth points for fft signal."
    APSLabeledEntry .cutoff -parent $w2 -textVariable cutoffFreq -label "Cutoff freq(Hz) for reverse PSD:" -width $width -contextHelp \
      "cutoff freq for reverse integrated PSD fft."
    APSLabeledEntry .filterFreq -parent $w1 -textVariable filterFreq -label "Filter frequency (Hz):" -width $width -contextHelp \
      "filter frequency for simulation output files to save disk space, if 0 then keep all data."
    APSLabeledEntry .corrconfig -parent $w2 -textVariable ${plane}CorrConfig -width $width -label "Corrector Noise Config:" 
    APSButton .p -parent $w2.corrconfig -packOption "-side right" -text P -command "SelectCorrNoiseConfig -plane $plane"
    APSButton .view -parent $w2.corrconfig -packOption "-side right" -text View -command "ShowCorrNoiseConfig -plane $plane" \
      -contextHelp "show corrector noise model configuration (bpm and corrector selection" 
    APSLabeledEntry .config -parent $w2 -label "Feedback simulation config:" -textVariable ${plane}FBConfig
    APSButton .p -parent $w2.config -packOption "-side right" -text P -command "PickFBConfig -plane $plane" \
      -contextHelp "pick a feedback simulation config."
    APSButton .g -parent $w2.config -packOption "-side right" -text G -command "GenerateFBConfig -plane $plane" \
      -contextHelp "generate a new config name for FB simulation."
    APSButton .1 -parent $w2.config -packOption "-side right" -text View -command "LoadFBConfig -plane $plane -config 2" \
      -contextHelp "view selected feedback config."
    APSLabeledEntry .kp -parent $w1 -width 80 -label "Regulator parameter Kp:" -textVariable ${plane}Kp -width $width
    APSLabeledEntry .ki -parent $w1 -width 80 -label "Regulator parameter Ki:" -textVariable ${plane}Ki -width $width
    APSLabeledEntry .t -parent $w1 -width $width -label "Feedback turn-on transient time filter (seconds):" -textVariable filterTime 
    APSLabeledEntry .delay -parent $w1 -width $width -label "Corrector delay (s):" -textVariable delay
    APSRadioButtonFrame .noise -parent $w2 -label "run simulation with/without random noise?" -buttonList {With Without} \
        -variable randomNoise -valueList {1 0} -orientation horizontal -contextHelp \
        "run simulation with added random noise or run with original data."
    APSRadioButtonFrame .delay -parent $w2 -label "run simulation with 100us delay or without?" -buttonList {With Without} \
      -variable withDelay -valueList {1 0} -orientation horizontal -contextHelp \
      "chose to use coefficients with/without delay (only 100us delay coefficients is available so far)."
    global runWith
    set runWith matlab
    APSRadioButtonFrame .matlab -parent $w2 -label "run with matlab or with c?" -buttonList {matlab C} -valueList {matlab C} \
      -variable runWith -orientation horizontal

    APSLabeledEntry .desc -parent $parent -width 80 -label "Feedback Simulation Config Description:" -textVariable ${plane}FBConfigDesc
    
   # APSLabeledEntry .dir -parent $parent -textVariable dataDir -label "Feedback simulation data directory:" -width 80
    
    set bpmDataDirList [set ${plane}bpmDataDirList]
    APSComboboxFrame .preset -parent $parent -label "BPM noise data directory" \
      -packOption "-fill x" \
      -textVariable ${plane}dataDir \
      -itemList [join $bpmDataDirList] \
      -width 80 \
      -editable 0 \
      -callback "SelectDataDirectory -plane $plane  -index" \
      -contextHelp "Select a bpm data directory."

    APSButton .load1 -parent $parent -text "Load Orbit Correction Config" -command "LoadOrbitCorrectionConfig -plane $plane"
    APSButton .compute -parent $parent -text "Compute" -command "ComputeMatrix -plane $plane" \
      -contextHelp "compute the inverse response matrix."   
    APSButton .sim -parent $parent -text "Start Feedback Simulation" -command "StartFeedbackSimulation -plane $plane"
    APSButton .proc -parent $parent -text "Postprocess" -command "PostProcess -plane $plane"
    APSButton .ratio -parent $parent -text "PlotFFTRatio" -command "PlotFFTRatio -plane $plane"
    APSButton .fft -parent $parent -text "PlotFFT" -command "PlotFFT -plane $plane"
    APSButton .rfft -parent $parent -text "PlotRFFT" -command "PlotRFFT -plane $plane"
    APSButton .corr -parent $parent -text "PlotCorrTime" -command "PlotCorrTime -plane $plane"
    APSButton .corr1 -parent $parent -text "PlotCorrPSD" -command "PlotCorrectorPSD -plane $plane"
}

proc ComputeMatrix {args} {
    set plane ""
    APSParseArguments {plane}
    
    global hdataDir vdataDir hFB vFB hItemList vItemList env hFBConfigStatus vFBConfigStatus hFBConfig vFBConfig hFBConfigDesc vFBConfigDesc
    global largestSingularValues refMatrixDir hlatticeDir vlatticeDir hlattice vlattice hCorrConfig vCorrConfig
    global hBPMItemList vBPMItemList hCorrItemList vCorrItemList
    
    set latticeDir [set ${plane}latticeDir]
    set lattice [set ${plane}lattice]
    set dataDir [set ${plane}dataDir]
    if ![file exist $dataDir/CorrData/[set ${plane}CorrConfig]] {
        return -code error "Corrector noise model [set ${plane}CorrConfig] does not exist."
    }
    set configDir [set ${plane}FBConfig]
    if ![string length $configDir] {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] feedback simulation config not provided."
        return
    }
    if ![file exist $dataDir/feedbackSim] {
        exec mkdir $dataDir/feedbackSim
    }
    if ![file exist $dataDir/feedbackSim/$configDir] {
        exec mkdir $dataDir/feedbackSim/$configDir
    }
    cd $dataDir/feedbackSim/$configDir
    
    set config 2
    
    set refMatrixDir $latticeDir/$lattice/refMatrices
    set bpmList ""
    set corrList ""
    set bpmItemList [set ${plane}BPMItemList]
    set corrItemList [set ${plane}CorrItemList]
    
    set itemList [concat $bpmList $corrItemList]
    
    set rootname ${plane}FB
    for {set sector 1} {$sector<=40} {incr sector} {
        foreach pv $bpmItemList {
            set nameflag  ${rootname}S${sector}$pv
            global $nameflag
            if [set $nameflag] {
                lappend bpmList S${sector}$pv
            }
        }
        foreach pv $corrItemList {
            set nameflag  ${rootname}S${sector}$pv
            global $nameflag
            if [set $nameflag] {
                lappend corrList S${sector}$pv
            }
        }
    }
    if {![llength $bpmList]} {
        return -code error "No bpms selected."
    }
    if {![llength $corrList]} {
        return -code error "No correctors selected."
    }
    set matchOpt "-match=col,BPMName=[lindex $bpmList 0]"
    for {set i 1} {$i<[llength $bpmList]} {incr i} {
        append matchOpt ",BPMName=[lindex $bpmList $i],|"
    }
    set tmpRoot /tmp/[APSTmpString]
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] writing config file..."
    if [catch {exec sddsmakedataset $tmpRoot.bpm.$plane -par=NameType,type=string -data=MonitorNames \
                 -col=Name,type=string -data=[join $bpmList ,] \
                 -par=Description,type=string "-data=[APSMakeSafeQualifierString [set ${plane}FBConfigDesc]]" \
                 -par=CorrConfig,type=string -data=[set ${plane}CorrConfig]
        exec sddsmakedataset $tmpRoot.corr.$plane -par=NameType,type=string -data=CorrectorNames \
                 -col=Name,type=string -data=[join $corrList ,]  \
                 -par=Description,type=string "-data=[APSMakeSafeQualifierString [set ${plane}FBConfigDesc]]" \
                 -par=CorrConfig,type=string -data=[set ${plane}CorrConfig]
        exec sddscombine $tmpRoot.bpm.$plane $tmpRoot.corr.$plane -over config$config } result] {
        return -code error "error in creating config: $result"
    }
    APSAddToTempFileList $tmpRoot.bpm.$plane $tmpRoot.corr.$plane
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] computing inverse response matrix..."
    set refMatrix $refMatrixDir/${plane}.default
   
    if [catch {eval exec sddsconvert $refMatrix -pipe=out -retain=col,BPMName,[join $corrList ,] \
                 | sddsprocess -pipe $matchOpt \
                 | tee rm$config \
                 | sddspseudoinverse -pipe=in -oldColumnNames=ControlName irm$config  -largestSingularValues=$largestSingularValues \
                 -economy } result] {
        return -code error "Error in generating inverse response matrix: $result"
    }
    if [catch {exec sdds2headlessdata rm$config rm${config}.dat -col=S* -order=column} result] {
        return -code error $result
    }
    if [catch {exec sdds2headlessdata irm$config irm${config}.dat -col=S* -order=column} result] {
        return -code error $result
    }
    set cond [exec sdds2stream -par=ConditionNumber irm$config]
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] condition number is $cond"
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] done."
    catch {exec rm config3}
    catch {exec rm rm3 rm3.dat}
    catch {exec rm irm3 irm3.dat}
}

set hCorrConfig h.default
set vCorrConfig v.default
set hFBConfig ""
set vFBConfig ""

proc SelectCorrNoiseConfig {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfigStatus vFBConfigStatus hCorrConfig vCorrConfig
    
    set dataDir [set ${plane}dataDir]
    cd $dataDir/CorrData
    set fileList [glob -nocomplain ${plane}.*]
    if ![llength $fileList] {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] no corrector noise data found."
        return
    }
    foreach file $fileList {
        set desc [lindex [exec sdds2stream -par=Description $file/config] 0]
        lappend choiceList "$file --> $desc"
    }
    set value [APSChooseItemFromList -name ChoiceList -height 30 \
                 -itemList $choiceList -returnList $fileList -multiItem 0]
    set ${plane}CorrConfig $value
}

proc ShowCorrNoiseConfig {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir  hCorrCBWidget vCorrCBWidget hCorrConfig vCorrConfig hCorr vCorr
    
    set dataDir [set ${plane}dataDir]
    set bpmItemList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0 ID:P1 ID:P2}
    set bpmLabelList {A0 A1 A2 A3 A4 B5 B4 B3 B2 B1 B0 C0 I1 I2}
    set corrLabelList {A1 A2 A3 A4 B4 B3 B2 B1 C1}
    set itemList  {A:P0 A:H1 A:P1 A:H2 A:P2 A:H3 A:P3 A:P4 A:H4 B:P5 B:H4 B:P4 B:P3 B:H3 B:P2 B:H2 B:P1 B:H1 B:P0 C:H1 C:P0 ID:P1 ID:P2}
    set itemLabelList {AP0 AH1 AP1 AH2 AP2 AH3 AP3 AP4 AH4 BP5 BH4 BP4 BP3 BH3 BP2 BH2 BP1 BH1 BP0 CH1 CP0 ID1 ID2}
    switch $plane {
        h {
            set corrItemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
        }
        v {
            set corrItemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
            set itemLabelList [regsub -all {H} $itemLabelList "V"]
            set itemList [regsub -all {H} $itemList "V"]
        }
    }
    
    
    set config [set ${plane}CorrConfig]
    if ![file exist $dataDir/CorrData/$config] {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] corrector noise model $config does not exist"
        return
    }
    if [catch {exec sddsprocess $dataDir/CorrData/$config/config -pipe=out -match=par,NameType=MonitorNames \
                 | sdds2stream -pipe -col=Name } bpmList] {
        return -code error $bpmList
    }
    if [catch {exec sddsprocess $dataDir/CorrData/$config/config -pipe=out -match=par,NameType=CorrectorNames \
                 | sdds2stream -pipe -col=Name } corrList] {
        return -code error $corrList
    }
    APSDialogBox .corr  -name "$plane corrector noise model"
   
    APSSRSectorButtons .bpmcorr -parent .corr.userFrame -rootname ${plane}Corr -description "$plane corrector noise model" \
      -label "" -sectorCount 40 -missingList ""  \
      -itemList $itemList -itemLabelList $itemLabelList \
      -orientation horizontal -sectorControl 1 -packOption "-side left" -separateCountButton 1
    
    APSSetSRSectorButtons -mode all-off -rootname  ${plane}Corr -sectorCount 40 -itemList $itemList
    set rootname ${plane}Corr
    foreach bpm $bpmList {
        set nameFlag ${rootname}$bpm
        global $nameFlag
        [set ${plane}CorrCBWidget($bpm)] invoke
    }
    foreach corr $corrList {
        set nameFlag ${rootname}$corr
        global $nameFlag
        [set ${plane}CorrCBWidget($corr)] invoke
    }
}

proc PickFBConfig {args} {
    set plane ""
    APSParseArguments {plane}
    global hFBConfig vFBConfig hFBConfigDesc vFBConfigDesc hdataDir vdataDir withDelay
    
    set dataDir [set ${plane}dataDir]
    cd $dataDir/feedbackSim
    set fileList [glob -nocomplain ${plane}.*]
   
    if ![llength $fileList] {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] no feedback simulation config found."
        return
    }
    foreach file $fileList {
        set desc [lindex [exec sdds2stream -par=Description $file/config2] 0]
        lappend choiceList "$file --> $desc"
    }
    set value [APSChooseItemFromList -name ChoiceList -height 30 \
                 -itemList $choiceList -returnList $fileList -multiItem 0]
    set ${plane}FBConfig $value
    if [file exist $value/config2] {
        set ${plane}FBConfigDesc [lindex [exec sdds2stream -par=Description $value/config2] 0]
    }
    if [file exist $value/feedbacksimulation.m] {
        catch {exec grep "withDelay=1;" $value/feedbacksimulation.m} result
        if [string match "withDelay=1;" $result] {
            set withDelay 1
        } else {
            set withDelay 0
        }
    }
}

proc LoadFBConfig {args} {
    set plane ""
    set config ""
    APSParseArguments {plane config} 
    global hdataDir vdataDir hFBConfig vFBConfig hFBConfigStatus vFBConfigStatus hFBCBWidget  vFBCBWidget hFB vFB hKp hKi vKp vKi
 
    set dataDir [set ${plane}dataDir]
    set simDir $dataDir/feedbackSim/[set ${plane}FBConfig]
    set bpmItemList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0 ID:P1 ID:P2}
    set bpmLabelList {A0 A1 A2 A3 A4 B5 B4 B3 B2 B1 B0 C0 I1 I2}
    set corrLabelList {A1 A2 A3 A4 B4 B3 B2 B1 C1}
    switch $plane {
        h {
            set corrItemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
        }
        v {
            set corrItemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
        }
    }
    if [file exist $simDir/config$config] {
        if [catch {exec sddsprocess $simDir/config$config -pipe=out -match=par,NameType=MonitorNames \
                     | sdds2stream -pipe -col=Name } bpmList] {
            return -code error $bpmList
        }
        if [catch {exec sddsprocess $simDir/config$config -pipe=out -match=par,NameType=CorrectorNames \
                     | sdds2stream -pipe -col=Name } corrList] {
            return -code error $corrList
        }
        APSSetSRSectorButtons -mode all-off -rootname  ${plane}FB -sectorCount 40 -itemList $bpmItemList
        APSSetSRSectorButtons -mode all-off -rootname  ${plane}FB -sectorCount 40 -itemList $corrItemList
        set rootname ${plane}FB
        foreach bpm $bpmList {
            set nameFlag ${rootname}$bpm
            global $nameFlag
            [set ${plane}FBCBWidget($bpm)] invoke
            # if [set $nameFlag]!=1 {
            #    [set ${plane}FBCBWidget($bpm)] invoke
            #}
        }
        foreach corr $corrList {
            set nameFlag ${rootname}$corr
            global $nameFlag
            [set ${plane}FBCBWidget($corr)] invoke
            #if [set $nameFlag]!=1 {
            #    [set ${plane}FBCBWidget($corr)] invoke
            #} else {
            #    [set ${plane}FBCBWidget($corr)] invoke
            #}
        }
        set pars [exec sddsquery -par $simDir/config$config]
        if [lsearch -exact $pars "Kp"]>=0 {
            set ${plane}Kp [format %.8f [lindex [exec sdds2stream -par=Kp $simDir/config$config] 0]]
            set ${plane}Ki [format %.8f [lindex [exec sdds2stream -par=Ki $simDir/config$config] 0]]
        }
    } else {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] $simDir/config$config does not exist"
        
    }
}
proc GenerateFBConfig {args} {
    set plane ""
    APSParseArguments {plane}
    global hFBConfig vFBConfig hFBConfigDesc vFBConfigDesc hdataDir vdataDir

    set dataDir [set ${plane}dataDir]
    set ${plane}FBConfig [APSNextGenerationedName -directory $dataDir/feedbackSim -name ${plane}.[clock format [clock seconds] -format %Y-%m%d].00 -newFile 1 -separator .]
    set ${plane}FBConfigDesc ""
}

proc LoadOrbitCorrectionConfig {args} {
    global hlattice vlattice hlatticeDir vlatticeDir hFBCBWidget  vFBCBWidget hBPMItemList vBPMItemList hCorrItemList vCorrItemList
    set plane ""
    APSParseArguments {plane}
    global hFBConfigStatus vFBConfigStatus 
    
    set lattice [set ${plane}lattice]
    set latticeDir [set ${plane}latticeDir]
    set dir $latticeDir/$lattice
    set itemList [split [exec sdds2stream $dir/${plane}configDesc.sdds -col=Description] \n]
    set choiceList [exec sdds2stream $dir/${plane}configDesc.sdds -col=Filename]
    set value [APSChooseItemFromList -name ChoiceList -height 30 \
                 -itemList $itemList -returnList $choiceList -multiItem 0]
    if ![string length $value] {
        APSSetVarAndUpdate ${plane}FBConfigStatus "no config selected."
        return
    }
    set bpmItemList [set ${plane}BPMItemList]
    set corrItemList [set ${plane}CorrItemList]
    
    if [catch {exec sddsprocess $dir/$value/config -pipe=out -pipe=out -match=par,NameType=MonitorNames \
                 | sdds2stream -pipe -col=Name } bpmList] {
        return -code error $bpmList
    }
    if [catch {exec sddsprocess $dir/$value//config -pipe=out -match=par,NameType=CorrectorNames \
                 | sdds2stream -pipe -col=Name } corrList] {
        return -code error $corrList
    }
    APSSetSRSectorButtons -mode all-off -rootname  ${plane}FB -sectorCount 40 -itemList $bpmItemList
    APSSetSRSectorButtons -mode all-off -rootname  ${plane}FB -sectorCount 40 -itemList $corrItemList
    set rootname ${plane}FB
    foreach bpm $bpmList {
        set nameFlag ${rootname}$bpm
        global $nameFlag
        [set ${plane}FBCBWidget($bpm)] invoke
        # if [set $nameFlag]!=1 {
        #    [set ${plane}FBCBWidget($bpm)] invoke
        #}
    }
    foreach corr $corrList {
        set nameFlag ${rootname}$corr
        global $nameFlag
        [set ${plane}FBCBWidget($corr)] invoke
        #if [set $nameFlag]!=1 {
        #    [set ${plane}FBCBWidget($corr)] invoke
        #} else {
        #    [set ${plane}FBCBWidget($corr)] invoke
        #}
    }
}

proc ComputeMatrix3 {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfigStatus vFBConfigStatus hrootname vrootname deltaT filterFreq hFBConfig vFBConfig hCorrConfig vCorrConfig
    global largestSingularValues refMatrixDir hlatticeDir vlatticeDir hlattice vlattice

    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] creating matrix3 with the correctors of matrix2 (feedback correction matrix) and all bpms..."
    
    set latticeDir [set ${plane}latticeDir]
    set lattice [set ${plane}lattice]
    set dataDir [set ${plane}dataDir]
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set simDir $dataDir/feedbackSim/$config
    set corrList [exec sdds2stream -col=ControlName $simDir/irm2]
    set bpmList [exec sdds2stream -col=BPMName $corrDir/rm1]
    set tmpRoot /tmp/[APSTmpString]
    set refMatrixDir $latticeDir/$lattice/refMatrices
    set refMatrix $refMatrixDir/${plane}.default
    set monitorNameMatchOption ""
    set IDBPMList ""
    set BMBPMList ""
    foreach item $bpmList {
        switch -regexp $item {
            ID {
                lappend IDBPMList $item
            }
            BM {
                lappend BMBPMList $item
            }
        }
        if [string length $monitorNameMatchOption] {
            append monitorNameMatchOption ",BPMName=$item,|"
        } else {
            set monitorNameMatchOption "-match=column,BPMName=$item"
        }
    }
    set equationCmd ""
    if [llength $IDBPMList] {
        set IDBPMsKnownList [APSGetIDXRayBPMList -plane $plane]
        set IDBPMEqnList    [APSGetIDXRayEqnList -plane $plane]
        lappend equationCmd sddsprocess -pipe
        foreach item $IDBPMList {
            set index [lsearch -exact $IDBPMsKnownList $item]
            if $index==-1 {
                return -code error "ComputeMatrix1(error1): no information on $item"
            }
            set equation [lindex $IDBPMEqnList $index]
            if ![string length $equation] {
                return -code error "ComputeMatrix1(error2): no equation defined for $item."
            }
            lappend equationCmd "-define=column,$item,$equation"
        }
    }
    if [llength $BMBPMList] {
        set BMBPMsKnownList [APSGetBMXRayBPMList -plane $plane]
        set BMBPMEqnList    [APSGetBMXRayEqnList -plane $plane]
        if ![string length $equationCmd] {
            lappend equationCmd sddsprocess -pipe
        }
        foreach item $BMBPMList {
            set index [lsearch -exact $BMBPMsKnownList $item]
            if $index==-1 {
                return -code error "ComputeMatrix1(error3): no information on $item"
            }
            set equation [lindex $BMBPMEqnList $index]
            if ![string length $equation] {
                return -code error "ComputeMatrix1(error4): no equation defined for $item."
            }
            lappend equationCmd "-define=column,$item,$equation"
        }
    }
    if { [llength $IDBPMList] || [llength $BMBPMList] } {
        set tmpMatrix /tmp/[APSTmpString]
        if [catch {eval exec sddstranspose $refMatrix -pipe=out  \
                     | $equationCmd \
                     | sddstranspose -pipe=in $tmpMatrix \
                     -newColumnNames=OldColumnNames -oldColumnNames=BPMName} result] {
            return -code error "ComputeMatrix1(error5): $result"
        }
        set refMatrix $tmpMatrix
        APSAddToTempFileList $tmpMatrix
    }
    
    if [catch {eval exec sddsconvert $refMatrix -pipe=out -retain=col,BPMName,[join $corrList ,] \
                 | sddsprocess -pipe $monitorNameMatchOption \
                 | tee $simDir/rm3 \
                 | sddspseudoinverse -pipe=in -oldColumnNames=ControlName $simDir/irm3  -largestSingularValues=$largestSingularValues \
                 -economy } result] {
        return -code error "Error in generating inverse response matrix1: $result"
    }
    set cond [exec sdds2stream -par=ConditionNumber $simDir/irm3]
    if [catch {exec sdds2headlessdata $simDir/rm3 -col=S* -order=column $simDir/rm3.dat
        exec sdds2headlessdata $simDir/irm3 -col=S* -order=column $simDir/irm3.dat } result] {
        return -code error "Error in generating inverse response matrix1a: $result"
    }
    APSSetVarAndUpdate ${plane}fbConfigStatus "[exec date] condition number is $cond"
    APSSetVarAndUpdate ${plane}fbConfigStatus "[exec date] done."
}

proc StartFeedbackSimulation {args} {
    set plane ""
    APSParseArguments {plane}
    
    global hdataDir vdataDir hFBConfigStatus vFBConfigStatus hrootname vrootname deltaT filterFreq hFBConfig vFBConfig hCorrConfig vCorrConfig
    global largestSingularValues refMatrixDir hlatticeDir vlatticeDir hlattice vlattice hKp hKi vKp vKi randomNoise withDelay delay runWith
    
    set latticeDir [set ${plane}latticeDir]
    set lattice [set ${plane}lattice]
    set dataDir [set ${plane}dataDir]
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set kp [set ${plane}Kp]
    set ki [set ${plane}Ki]
    
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    set simDir $dataDir/feedbackSim/$config
    if [catch {exec sddsprocess $simDir/config2 -redefine=par,Kp,$kp -redefine=par,Ki,$ki -nowarnings} result] {
        return -code error $result
    }
    if ![file exist $corrDir] {
        return -code error "Corrector noise model does not exist $corrDir."
    }
    if ![file exist $corrDir/rm1] {
        return -code error "Matrix1 not created in corrector data directory."
    }
    if ![file exist $corrDir/rm1.dat] {
        if [catch {exec sdds2headlessdata $corrDir/rm1 $corrDir/rm1.dat -col=S* -order=column
            exec sdds2headlessdata $corrDir/irm1 $corrDir/irm1.dat -col=S* -order=column } result] {
            return -code error $result
        }
    }
    if {![file exist $simDir/irm2]} {
        return -code error "Feedback correction matrix not generated yet."
    }
    if {![file exist $simDir/rm3] || ![file exist $simDir/irm3]} {
       ComputeMatrix3 -plane $plane
    }
    
    set bpms [exec sdds2stream -col=BPMName $simDir/rm3]
    if $randomNoise {
        set columm ReconsWithNoise
    } else {
        set column Reconstructed
    }
    foreach bpm $bpms {
        if ![file exist $corrDir/${bpm}_computed.sdds] {
            return -code error "$bpm data not generated yet, run corrector noise model to generate it first."
        }
        set mtime [file mtime $corrDir/${bpm}_computed.sdds]
        if [file exist $corrDir/${bpm}.dat] {
            set mtime1 [file mtime $corrDir/${bpm}.dat]
        } else {
            set mtime1 0
        }
        if {$mtime1<$mtime} {
            if [catch {exec sdds2headlessdata $corrDir/${bpm}_computed.sdds $corrDir/${bpm}.dat -col=$column } result] {
                return -code error $result
            }
        }
        
    }
    if ![file exist $corrDir/time.dat] {
        if [catch {exec sdds2headlessdata $corrDir/${bpm}_computed.sdds $corrDir/time.dat -col=Time} result] {
            return -code error $result
        }
    }
    if ![file exist $simDir/irm2.dat] {
        if [catch {exec sdds2headlessdata $simDir/irm2 $simDir/irm2.dat -col=S* -order=column} result] {
            return -code error $result
        }
    }
    if ![file exist $simDir/rm3.dat] {
        if [catch {exec sdds2headlessdata $simDir/rm3 $simDir/rm3.dat -col=S* -order=column} result] {
            return -code error $result
        }
    }
    #check matrix1 and matrix3 bpm if they are the same
    if [catch {exec sddsdiff $corrDir/rm1 $simDir/rm3 -col=BPMName } result] {
        return -code error "The bpms in Matrix1 and Matrix3 are different."
    }
    if [catch {exec sddsdiff $simDir/irm2 $simDir/irm3 -col=ControlName} result] {
        return -code error "The correctors in Matrix2 and Matrix3 are different."
    }
    if [catch {exec sdds2stream $simDir/irm2 -col=ControlName } fbcorrList] {
        return -code error "Error reading corrector names from $simDir/config1: $fbcorrList]"
    }
    set bpmList [exec sdds2stream -col=BPMName $simDir/rm2]
    set allBpmList [exec sdds2stream -col=BPMName $simDir/rm3]
    foreach bpm $bpmList {
        if [lsearch -exact $allBpmList $bpm]<0 {
            return -code error "Error: feedback correction bpm -- $bpm not found in the initial matrix"
        }
    }
    set rows [exec sdds2stream -rows=bar [lindex [glob $corrDir/*_computed.sdds] 0]]
    set outputDir $simDir
    cd $simDir 
    if {$runWith=="C"} {
        set coefFile coef.${delay}Ticks
        puts "deltaT = $deltaT"
        if [catch {exec /usr/local/octave-3.6.4/bin/octave /home/oxygen/SHANG/oag/apps/src/feedbackSimulation/computeCoeffs.m \
                     $plane [set ${plane}Kp] [set ${plane}Ki] $delay $coefFile } result] {
            return -code error "Error in compute regulator coefficients: $result"
        }
        set aCoefs [join [exec sddsprocess $coefFile -match=par,CoefName=corrAcoef -pipe=out | sdds2stream -pipe -col=Coefficient]]
        set bCoefs [join [exec sddsprocess $coefFile -match=par,CoefName=corrBcoef -pipe=out | sdds2stream -pipe -col=Coefficient]]
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] starting feedback simulation..."
        
        if [catch {exec feedbackSimulation \
                     $corrDir $simDir -responseMatrix=rm1 -feedbackCorrectionMatrix=irm2 -reconstructMatrix=rm3 \
                     -acoef=[join $aCoefs ,] -bcoef=[join $bCoefs ,] \
                     -deltaT=$deltaT } result] {
           #  return -code error $result
        }
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] done."
        return
    }
    if [catch {exec replaceText /home/oxygen/SHANG/oag/apps/src/feedbackSimulation/feedbacksim.template.m $simDir/feedbacksimulation.m \
                 -orig=<feedbackSimDir>,<corrDataDir>,<outputDir>,<plane>,<Kp>,<Ki>,<withDelay>,<delay> \
                 -repl=$simDir,$corrDir,$simDir,$plane,[set ${plane}Kp],[set ${plane}Ki],$withDelay,$delay  } result] {
         APSSetVarAndUpdate ${plane}FBConfigStatus  "Error in creating matlab script: $result"
        return
    }
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] starting feedback simulation..."
    APSSetVarAndUpdate ${plane}FBConfigStatus "Please run following commands on a terminal to run feedback simulation."
    APSSetVarAndUpdate ${plane}FBConfigStatus "1) cd $simDir"
    APSSetVarAndUpdate ${plane}FBConfigStatus "2) matlab -nodesktop -nosplash -r  feedbacksimulation"
}

proc PostProcessRFFT {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfig vFBConfig hrootname hrootname smoothPoints cutoffFreq hFBConfigStatus vFBConfigStatus
    global hCorrConfig vCorrConfig filterTime

    set dataDir [set ${plane}dataDir]
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set simDir $dataDir/feedbackSim/$config
    
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] Post-processing $plane data, it may take a while ..."
    update
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    
    cd $simDir
    set bpms [exec sdds2stream -col=BPMName $corrDir/rm1]
    set corrs [exec sdds2stream -col=ControlName $simDir/irm2]
    
    
    foreach bpm $bpms {
        set file ${bpm}.sdds
        if ![file exist $file] {
            return -code error "$bpm date not generated!"
        }
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] Post-processing reverse integrated PSD of $bpm..."
       
        if $cutoffFreq {
            set psdOpt -psdoutput=rintegrated=$cutoffFreq 
        } else {
            set psdOpt -psdoutput=rintegrated
        }
        if [catch {eval exec  sddsprocess -majorOrder=column \
                     $file  -pipe=out -filter=col,Time,$filterTime,50 \
                     | sddsfft  \
                     -pipe=in $file.rfft1 -col=Time,Output -suppressAverage $psdOpt -truncate } result] {
            return -code error "RFFT1: $result"
        }
        if [catch {exec sddsprocess $file.rfft1 -majorOrder=column \
                     -nowarnings -define=par,CutoffFreq,$cutoffFreq } result] {
             return -code error "RTTF2: $result"
        }
        if [catch {exec sddsprocess -majorOrder=column \
                     $corrDir/${bpm}_computed.sdds -pipe=out -filter=col,Time,$filterTime,15 \
                     | sddsfft  -col=Time,Recon* \
                     -pipe=in $bpm.input.rfft -suppressAverage $psdOpt -truncate } result] {
            return -code error "RFFT3: $result"
        }
    }
    APSSetVarAndUpdate ${plane}FBConfigStatus "done."
}

proc PostProcess {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfig vFBConfig hrootname hrootname smoothPoints cutoffFreq hFBConfigStatus vFBConfigStatus
    global hCorrConfig vCorrConfig randomNoise filterTime
    #the output file created by matlab (simulation) are written in column-major order

    set dataDir [set ${plane}dataDir]
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set simDir $dataDir/feedbackSim/$config
    
    APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] Post-processing $plane data, it may take a while ..."
    update
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    
    cd $simDir
    set bpms [exec sdds2stream -col=BPMName $corrDir/rm1]
    set corrs [exec sdds2stream -col=ControlName $simDir/irm2]
    
    set fileList ""
    if $randomNoise {
        set columm ReconsWithNoise
    } else {
        set column Reconstructed
    }
    puts $filterTime
    foreach bpm $bpms {
        set file ${bpm}.sdds
        if ![file exist $file] {
            return -code error "$bpm date not generated!"
        }
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] Post-processing $bpm..."
        if [catch {exec  sddsprocess  $file  -pipe=out -filter=col,Time,$filterTime,50 -majorOrder=column  \
                     | sddsfft \
                     -pipe=in $file.ifft -col=Time,Output -suppressAverage -psdoutput=plain,integrated -truncate } result] {
            return -code error "Error in filtering and doing forward PSD FFT: $result"
        }
        
        if [catch {eval exec sddsprocess -majorOrder=column \
                     $file  -pipe=out -filter=col,Time,$filterTime,50 \
                     | sddsfft \
                     -pipe=in $file.rfft -col=Time,Output -suppressAverage  -psdoutput=rintegrated -truncate } result] {
            return -code error "Error in filtering and doing reverse PSD: $result"
        }
        if [catch {exec sddsprocess $file.rfft -majorOrder=column \
                     -nowarnings -define=par,CutoffFreq,$cutoffFreq } result] {
             return -code error "Error in defining cutoff Freq: $result"
        }
        lappend fileList $file.rfft
        set file0 $corrDir/${bpm}_computed.sdds.ifft
        set file1 ${bpm}.sdds.ifft
        #changed to reprocess fft in corrector model (recontructed bpm error) to make them consistenet
        if [catch {exec sddsprocess $corrDir/${bpm}_computed.sdds -majorOrder=column  -pipe=out -filter=col,Time,$filterTime,50 \
                     | sddsfft -pipe=in $file0 -col=Time,$column -suppressAverage  -psdoutput=plain,integrated -truncate } result] {
            return -code error "Error in filtering and doing reverse PSD: $result"
        }
        
        if {$smoothPoints>1} {
            if [expr $smoothPoints%2]==0 {
                APSSetVarAndUpdate ${plane}FBConfigStatus  "Error: smooth points has to be an odd number."
                return
            }
            if [catch {exec sddssmooth -majorOrder=column \
                         $corrDir/${bpm}_computed.sdds.ifft -col=FFT$column -points=$smoothPoints \
                         $corrDir/${bpm}_computed.sdds.ifft.smooth
                exec sddssmooth -majorOrder=column \
                         ${bpm}.sdds.ifft -col=FFT$column -points=$smoothPoints \
                         ${bpm}.ifft.smooth } result] {
                APSSetVarAndUpdate ${plane}FBConfigStatus "Error in smoothing fft data: $result"
                return
            }
            set file0 $corrDir/${bpm}_computed.sdds.ifft.smooth
            set file1 ${bpm}.ifft.smooth
        } 
        
        if [catch {exec sddsxref $file0 $file1 -majorOrder=column \
                     -take=FFTOutput -pipe=out \
                     | sddsprocess  \
                     -pipe "-redefine=col,Ratio,FFT$column FFTOutput /" \
                     | sddsconvert \
                     -pipe=in $bpm.ratio -retain=col,f,Ratio } result] {
            APSSetVarAndUpdate ${plane}FBConfigStatus "Error in fft ratio data: $result"
            return
        }
    }
    eval file delete -force $fileList
    foreach corr $corrs {
        set file ${corr}.sdds
         APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] Post-processing $corr..."
        if [catch {exec sddsfft -majorOrder=column $file $file.ifft \
                     -col=Time,Corr* -psdoutput=plain,integrated -truncate 
            exec sddsfft $file $file.rfft -majorOrder=column \
                     -col=Time,Corr* -psdoutput=rintegrated -truncate } result] {
            APSSetVarAndUpdate ${plane}FBConfigStatus "Error in fft corrector data: $result"
            return
        }
    }
    APSSetVarAndUpdate ${plane}FBConfigStatus "done."
}



set sectorList [exec sddssequence -define=sector,type=long -sequence=begin=1,end=40,delta=1 -pipe=out | sdds2stream -pipe -col=sector]
foreach sector $sectorList {
    set S$sector 0
    lappend varList S$sector
}
set ratioType BPM
set allbpmList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0 ID:P1 ID:P2 BM:P1 BM:P2}
foreach bpm $allbpmList {
    set $bpm 0
}
proc PlotFFTRatio {args} {
    set plane ""
    APSParseArguments {plane}
    
    global allbpmList varList sectorList
    eval global $allbpmList
    eval global $varList
    APSDialogBox .ratio -name "choose plots" -okCommand "PlotRatio -plane $plane"
    APSCheckButtonFrame .s -parent .ratio.userFrame -orientation horizontal -buttonList $sectorList -variableList $varList \
        -limitPerRow 10 -label "Select sectors for plot FFT ratio:" -allNone 1
    APSCheckButtonFrame .bpm -parent .ratio.userFrame -orientation horizontal -buttonList $allbpmList -variableList $allbpmList \
        -limitPerRow 7 -label "Select bpm type for plot FFT ratio:" -allNone 1
    
    APSRadioButtonFrame .type -parent .ratio.userFrame -orientation horizontal -label "Plot FFT ratio by:"  -variable ratioType\
        -buttonList {Sector BPM_Type All_bpms} -valueList {Sector BPM ALL} -contextHelp "select which type to plot FFT ratio."
}

proc PlotRatio {args} {
    set plane ""
    APSParseArguments {plane}
    
    global sectorList varList allbpmList ratioType  hrootname vrootname smoothPoints hFBConfig vFBConfig hdataDir vdataDir hCorrConfig vCorrConfig
    eval global $varList
    eval global $allbpmList

    set dataDir [set ${plane}dataDir]
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "Simulation config not provided."
    }
    set simulationDir $dataDir/feedbackSim/$config
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    cd $simulationDir
    
    switch $ratioType {
        Sector {
            set fileList ""
            foreach sector $sectorList {
                if [set S$sector] {
                    foreach bpm $allbpmList {
                        if [set $bpm] {
                            if [file exist S${sector}$bpm.ratio] {
                                lappend fileList S${sector}$bpm.ratio
                            }
                        }
                    }
                }
            }
            if ![llength $fileList] {
                APSSetVarAndUpdate ${plane}FBConfigStatus "no sectors selected."
                return
            }
            eval exec sddsplot -topT -same -split=page \
              -graphic=line,vary -order=spectral -legend=file,edit=%/.ratio// \
              -mode=x=log,x=spec -mode=y=log,y=spec \
              -col=f,Ratio $fileList & 
            
        }
        BPM {
            foreach bpm $allbpmList {
                set files ""
                if [set $bpm] {
                    foreach  sector $sectorList {
                        if [set S$sector] {
                            if [file exist S${sector}$bpm.ratio] {
                                lappend files S${sector}$bpm.ratio
                            }
                        }
                    }
                    if ![llength $files] {
                        continue
                    }
                    eval exec  sddsplot $files  -topT -same \
                      -split=page -legend=file,edit=%/.ratio// \
                      -graphic=line,vary -order=spectral \
                      -mode=x=log,x=spec -mode=y=log,y=spec \
                      -col=f,Ratio &
                }
            }
        }
        ALL {
            set opt ""
            foreach bpm $allbpmList {
                set files ""
                foreach  sector $sectorList {
                    if [file exist S${sector}$bpm.ratio] {
                        lappend files S${sector}$bpm.ratio
                    }
                }
                if [llength $files] {
                    set opt [concat $opt -col=f,Ratio -title=$bpm $files -endp]
                }
            }
            catch {eval exec sddsplot \
                     -layout=4,4 -topT -same \
                     -graphic=line,vary -order=spectral -legend=file,edit=%/.ratio//  \
                     -mode=x=log,x=spec -mode=y=log,y=spec -split=page $opt & }
        }
        
    }
}

proc PlotFFT {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hrootname vrootname cutoffFreq hFBConfig vFBConfig hCorrConfig vCorrConfig randomNoise
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set dataDir [set ${plane}dataDir]
    set simulationDir $dataDir/feedbackSim/$config
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    cd $simulationDir
    if $randomNoise {
        set columm ReconsWithNoise
    } else {
        set column Reconstructed
    }
    foreach item {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 ID:P1 ID:P2 BM:P1 BM:P2} {
        set files [glob -nocomplain S*${item}.sdds.ifft]
        set opt ""
        set opt1 ""
        for {set sector 1} {$sector<=40} {incr sector} {
            set bpm S${sector}$item
            if {[file exist ${bpm}.sdds.ifft] && [file exist $corrDir/${bpm}_computed.sdds.ifft]} {
                lappend opt -col=f,FFT$column -title=@bpmString -leg=spec=Input $corrDir/${bpm}_computed.sdds.ifft -col=f,FFTOutput -leg=spec=Output  ${bpm}.sdds.ifft
                
                lappend opt1 -col=f,SqrtIntegPSD$column -title=@bpmString -leg=spec=Input $corrDir/${bpm}_computed.sdds.ifft -col=f,SqrtIntegPSDOutput -leg=spec=Output ${bpm}.sdds.ifft
                
            }
            
        }
        if [llength $opt] {
            catch {eval exec sddsplot \
                     \"-topline=FFT of BPM input and output after simulation\" \
                     -mode=x=log,x=spec -mode=y=log,y=spec   \
                     -sep=2 -layout=1,3 -graph=line,vary $opt 2>/dev/null & }
            
            catch {eval exec sddsplot \
                     \"-topline=Forward integrated PSD of BPM input and output after simulation\" \
                     -mode=x=log,x=spec -mode=y=log,y=spec   \
                     -sep=2 -layout=1,3 -graph=line,vary $opt1 2>/dev/null & }
        }
    }
}


proc PlotRFFTDiag {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hrootname vrootname cutoffFreq hFBConfig vFBConfig
    
    set dataDir [set ${plane}dataDir]
    APSDialogBox .freq -name "choose plots" -cancelCommand "set cutoffFreq -1"
    APSLabeledEntry .freq -parent .freq.userFrame -label "cutoff freqeuncy:" -textVariable cutoffFreq -width 25
    tkwait window .freq
    return $cutoffFreq
}

set cutoffFreq 0
set filterFreq 2.5e3
proc PlotRFFT {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfig vFBConfig cutoffFreq hFBConfigStatus vFBConfigStatus hCorrConfig vCorrConfig randomNoise
   
    set dataDir [set ${plane}dataDir]
    set cutoffFreq [PlotRFFTDiag]
    if {$cutoffFreq==-1} {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] plotRFFT was cancelled."
        return
    }
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set simulationDir $dataDir/feedbackSim/$config
    set corrDir $dataDir/CorrData/[set ${plane}CorrConfig]
    
   # SetStatus "doing reverse integrated PSD fft with cutoff frequency - $cutoffFreq..."
    cd $simulationDir
    set files [glob -nocomplain S*P*.rfft1]
    if [llength $files] {
        set cutoff [exec sdds2stream [lindex $files end] -par=CutoffFreq]
        if {$cutoff!=$cutoffFreq} {
            PostProcessRFFT -plane $plane
        }
    } else {
        PostProcessRFFT -plane $plane
    }
    if $randomNoise {
        set columm ReconsWithNoise
    } else {
        set column Reconstructed
    }
    foreach item {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 ID:P1 ID:P2 BM:P1 BM:P2} {
        set opt2 ""
        for {set sector 1} {$sector<=40} {incr sector} {
            set bpm S${sector}$item
            if {[file exist ${bpm}.sdds.rfft1]} {
                lappend opt2  -col=f,SqrtIntegPSD$column -title=@bpmString -leg=spec=Input ${bpm}.input.rfft -col=f,SqrtIntegPSDOutput -leg=spec=Output ${bpm}.sdds.rfft1
            }
        }
       
        if [llength $opt2] {
            catch {eval exec sddsplot \
                     \"-topline=Reverse integrated PSD of BPM input and output after simulation\" \
                      -mode=x=log,x=spec -mode=y=log,y=spec   \
                     -sep=2 -layout=1,3 -graph=line,vary $opt2  2>/dev/null & }
        }
    }
}


proc SelectDataDirectory {args} {
    global hdataDir vdataDir outputDir hturns vturns hlattice vlattice hrfFreq vrfFreq
    global hbpmDataDirList vbpmDataDirList hbpmTurnsList vbpmTurnsList hbpmLatticeList vbpmLatticeList
    set index ""
    set plane ""
    APSParseArguments {index plane}

    if {$index == ""} {
        return -code error " No index value passed."
    }
    set bpmDataDirList [set ${plane}bpmDataDirList]
    set bpmTurnsList [set ${plane}bpmTurnsList]
    set bpmLatticeList [set ${plane}bpmLatticeList]
    set ${plane}dataDir [lindex $bpmDataDirList $index]
    set dataDir [set ${plane}dataDir]
    set outputDir [set ${plane}dataDir]/CorrData
    set ${plane}turns [lindex $bpmTurnsList $index]
    set ${plane}lattice [lindex $bpmLatticeList $index]
    set file [lindex [glob -nocomplain $dataDir/S*P*.sdds] end]
    if [string length $file] {
        set pars [exec sddsquery -par $file]
        if [lsearch -exact $pars RFFreq]>=0 {
            set ${plane}rfFreq [exec sdds2stream -par=RFFreq $file]
        }
    }
    update
}

proc PlotCorrTime {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfig vFBConfig cutoffFreq hFBConfigStatus vFBConfigStatus hCorrConfig vCorrConfig

    set dataDir [set ${plane}dataDir]    
    set config [set ${plane}FBConfig]
    if ![string length $config] {
        return -code error "no config provided."
    }
    set simulationDir $dataDir/feedbackSim/$config
    cd $simulationDir
    set files [glob -nocomplain S*[string toupper $plane]*.sdds]
    if ![llength $files] {
        APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] no corrector data found."
        return
    }
    eval exec sddsplot -leg -col=Time,Corr* -grap=line,vary -sep=2 -split=page $files -file=edit=%/.sdds// "-ylabel=Corrector(A)" &
}

set Forward_Integrated_PSD 1
set Reverse_Integrated_PSD 0
set Plain_PSD 0
set FFT 0
proc PlotCorrectorPSD {args} {
    set plane ""
    APSParseArguments {plane}
    global outputDir deltaT hturns vturns hrfFreq vrfFreq corrType hnoiseModelConfigStatus vnoiseModelConfigStatus hconfig vconfig
   
    set turns [set ${plane}turns]
    set rfFreq [set ${plane}rfFreq]
    
    switch $plane {
        h {
            set corrList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
        }
        v {
            set corrList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
        }
    }
    foreach corr $corrList {
        global $corr
        set $corr 0
    }
    global Forward_Integrated_PSD Reverse_Integrated_PSD Plain_PSD FFT
   
    APSDialogBox .corr -name "choose plots" -okCommand "PlotCorrPSD -plane $plane"
    APSCheckButtonFrame .bpm -parent .corr.userFrame -orientation horizontal -buttonList $corrList -variableList $corrList \
        -limitPerRow 7 -label "Select bpm type for plot FFT ratio:" -allNone 1
    APSCheckButtonFrame .fft -parent .corr.userFrame -orientation horizontaol -buttonList "Forward_Integrated_PSD Reverse_Integrated_PSD Plain_PSD FFT" \
      -variableList "Forward_Integrated_PSD Reverse_Integrated_PSD Plain_PSD FFT" -allNone 1
    tkwait window .corr
}

proc PlotCorrPSD {args} {
    set plane ""
    APSParseArguments {plane}
    global hdataDir vdataDir hFBConfig vFBConfig Forward_Integrated_PSD Reverse_Integrated_PSD Plain_PSD FFT

    set dataDir [set ${plane}dataDir]
    set config [set ${plane}FBConfig]
    switch $plane {
        h {
            set corrList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
        }
        v {
            set corrList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
        }
    }
    eval global $corrList
    cd $dataDir/feedbackSim/[set ${plane}FBConfig]
    foreach corr $corrList {
        if [set $corr] {
            set files ""
            for {set sector 1} {$sector<=40} {incr sector} {
                set file S${sector}${corr}.sdds
                if [file exist $file] {
                    lappend files $file
                }
            }
            if ![llength $files] {
                APSSetVarAndUpdate ${plane}FBConfigStatus "[exec date] $corr data not found."
                continue
            }
            if $Forward_Integrated_PSD {
                set ifiles [regsub -all {.sdds} $files ".sdds.ifft"]
                catch { eval exec sddsplot $ifiles -split=page -sep=2 -file=edit=%/.sdds.ifft//  \
                          \"-title=Forward Integrated PSD\" \
                          -graphic=line,vary -order=spectral -legend=yname,edit=%/SqrtIntegPSD//  \
                          -mode=x=log,x=spec -mode=y=log,y=spec \
                          -col=f,SqrtIntegPSD*   2>/dev/null & } result
            }
            if $Reverse_Integrated_PSD {
                set rfiles [regsub -all {.sdds} $files ".sdds.rfft"]
                catch { eval exec sddsplot $rfiles -split=page -sep=2 -file=edit=%/.sdds.ifft//  \
                          \"-title=Reverse Integrated PSD\" \
                          -graphic=line,vary -order=spectral -legend=yname,edit=%/SqrtIntegPSD//  \
                          -mode=x=log,x=spec -mode=y=log,y=spec \
                          -col=f,SqrtIntegPSD*   2>/dev/null & } result
            }
            if $FFT {
                set ifiles [regsub -all {.sdds} $files ".sdds.ifft"]
                
                catch {eval exec sddsplot $ifiles  -split=page -sep=2 -file=edit=%/.sdds.ifft//  \
                          \"-title=FFT of corrector error and drive\" -mode=x=log,x=spec -mode=y=log,y=spec  \
                          -graphic=line,vary -order=spectral -legend=yname,edit=%/FFT// \
                          -col=f,FFT*  2>/dev/null & } result
            }
            if $Plain_PSD {
                set ifiles [regsub -all {.sdds} $files ".sdds.ifft"]
                catch {eval exec sddsplot  $ifiles -split=page -sep=2 -file=edit=%/.sdds.ifft// \
                         \"-title=Plain PSD\"  -mode=x=log,x=spec -mode=y=log,y=spec  \
                         -graphic=line,vary -order=spectral -legend=yname,edit=%/PSD// \
                         -col=f,PSD*   2>/dev/null & } result
            }
        }
    }
}


if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -filter=col,NonexistentH,0,0 -pipe=out \
             -match=col,DeviceName=S1ID*,! \
             | sdds2stream -pipe -col=DeviceName } hAllBPMList] {
    puts stderr "$hAllBPMList"
}
if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -filter=col,NonexistentV,0,0 -pipe=out \
             -match=col,DeviceName=S1ID*,! \
             | sdds2stream -pipe -col=DeviceName } vAllBPMList] {
    puts stderr "$vAllBPMList"
}

set fpgaSectorList [exec sdds2stream -col=Sector /home/helios/oagData/sr/FPGAbpm/sectors.sdds]
set bpmList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 C:P0 ID:P1 ID:P2 BM:P1 BM:P2}
set rfFreq 351934968.0
set turns 12
set deltaT [expr 1.0/$rfFreq * 1296.0 * $turns]

set latticeDir  /home/helios/oagData/sr/orbitControllaw/lattices
set hlatticeDir /home/helios/oagData/sr/orbitControllaw/lattices
set vlatticeDir /home/helios/oagData/sr/orbitControllaw/lattices
set lattice sigmax120um-S32
set refMatrixDir /home/helios/oagData/sr/orbitControllaw/lattices/default/refMatrices
set largestSingularValues 320

set hItemLabelList {AP0 AH1 AP1 AH2 AP2 AH3 AP3 AP4 AH4 BP5 BH4 BP4 BP3 BH3 BP2 BH2 BP1 BH1 BP0 CH1 CP0 ID1 ID2}
set hItemList {A:P0 A:H1 A:P1 A:H2 A:P2 A:H3 A:P3 A:P4 A:H4 B:P5 B:H4 B:P4 B:P3 B:H3 B:P2 B:H2 B:P1 B:H1 B:P0 C:H1 C:P0 ID:P1 ID:P2}
set vItemLabelList [regsub -all {H} $hItemLabelList "V"]
set vItemList [regsub -all {H} $hItemList "V"]
set hnoiseModelConfigStatus ""
set vnoiseModelConfigStatus ""
set tabs {"Horizontal" "Vertical"}
set dataDir /home/helios/SR/daily/2012/10/30/2/fpga_12sec
set corrDir  $dataDir/CorrData
if ![file exist $corrDir] {
    exec mkdir $corrDir
}
set simulationDir $dataDir/feedbackSim
if ![file exist $simulationDir] {
    exec mkdir $simulationDir
}

set smoothPoints 1
#set outputDir /home/oxygen/SHANG/daily/1211/19/2/CorrData
#set simulationDir /home/oxygen/SHANG/daily/1211/19/2/feedbackSim
set hrootname h
set vrootname v

set hmissingBpms [exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -filter=col,NonexistentH,1,1 -pipe=out \
    | sdds2stream -pipe -col=DeviceName]
set vmissingBpms [exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -filter=col,NonexistentV,1,1 -pipe=out \
    | sdds2stream -pipe -col=DeviceName]

set hmissingCorrs [exec sddsprocess /home/helios/oagData/sr/HCorrectorStatus/config.sdds -filter=col,Nonexistent,1,1 -pipe=out \
    | sdds2stream -pipe -col=DeviceName]
set vmissingCorrs [exec sddsprocess /home/helios/oagData/sr/VCorrectorStatus/config.sdds -filter=col,Nonexistent,1,1 -pipe=out \
    | sdds2stream -pipe -col=DeviceName]

set hmissingList [concat $hmissingBpms S7A:P0 $hmissingCorrs]
set vmissingList [concat $vmissingBpms S7A:P0 $vmissingCorrs]

set tmpRoot /tmp/[APSTmpString]
foreach plane {Horizontal Vertical} pl {h v} {
    if [catch {exec sddsprocess /home/helios/oagData/sr/feedbackSimulation/bpmDataConfig.sdds $tmpRoot.$pl \
                 -match=col,Directory=*${plane}* } result] {
        puts stderr $result
        exit 1
    }
    set ${pl}bpmDataDirList [exec sdds2stream -col=Directory $tmpRoot.$pl]
    set ${pl}bpmLatticeList [exec sdds2stream -col=Lattice $tmpRoot.$pl]
    set ${pl}bpmTurnsList [exec sdds2stream -col=Turns $tmpRoot.$pl]
}
file delete -force $tmpRoot.h $tmpRoot.v
#set bpmDataDirList [exec sdds2stream -col=Directory /home/helios/oagData/sr/feedbackSimulation/bpmDataConfig.sdds]
#set bpmLatticeList [exec sdds2stream -col=Lattice /home/helios/oagData/sr/feedbackSimulation/bpmDataConfig.sdds]
#set bpmTurnsList  [exec sdds2stream -col=Turns /home/helios/oagData/sr/feedbackSimulation/bpmDataConfig.sdds]

set hBPMLabelList {A0 A1 A2 A3 A4 B5 B4 B3 B2 B1 B0 C0 I1 I2}
set hBPMItemList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0 ID:P1 ID:P2}
set vBPMLabelList {A0 A1 A2 A3 A4 B5 B4 B3 B2 B1 B0 C0 D1 D2 I1 I2}
set vBPMItemList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0 BM:P1 BM:P2 ID:P1 ID:P2}
set corrLabelList {A1 A2 A3 A4 B4 B3 B2 B1 C1}
set hCorrItemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
set vCorrItemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}

#SelectDataDirectory -plane h -index 0

#set status ""
APSApplication . -name SRFeedbackSimulation -version 1 \
  -overview {This application generates corrector noise data from collected FPGA bpm data.}
# APSScrolledStatus .status -parent .userFrame -textVariable status -width 100 \
#      -withButtons 1

set w2List [APSTabFrame .tabs -parent .userFrame -width 1150 -height 720 -labelList "Horizontal Vertical" -label ""]

CreateFeedbackSimWidget -plane h -parent [lindex $w2List 0]
CreateFeedbackSimWidget -plane v -parent [lindex $w2List 1]

#CreateBPMCorrWidget -plane h -parent [lindex $widgetList 0]
#CreateBPMCorrWidget -plane v -parent [lindex $widgetList 1]
#bpm date for 10/30/2012 is in /home/oxygen/SHANG/daily/1211/15/2/CorrData
#GenerateFBConfig -plane h
#GenerateFBConfig -plane v
set hFBConfig h.test1
set vFBConfig v.test1
