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

set CVSRevisionAuthor "\$Revision: 1.4 $ \$Author: lemery $"

APSApplication . -name "Septum Leakage Field Measurement and Correction" \
  -version $CVSRevisionAuthor \
  -overview "Operator Interface to the Septum Leakage Field Measurement and Correction Programs."

bind all <Double-Button-3> { 
    APSInfoWindow .contextHelp -name "Context Help" \
      -infoMessage [APSNearestContextHelp %W] \
      -width 15
}

set ControlStatus "Ready"
set SeptumMainRelAmplitude 0.1
set Title {1A =0.008 mrad}
set Delay 0
set plotDirectory ./

proc MakeSeptumStatus {} {
    global ControlStatus
    
    APSScrolledStatus .status -parent .userFrame -textVariable ControlStatus -width 75 -packOption {-side top}
}

proc MakeSeptumSetupWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent -label "Septum Control and Measurement Functions" \
      -height 30 \
      -packOption {-side top -fill x} 
    set w $parent$widget.frame
    MakeDSPFileSetupWidget .file -parent $w
}

proc MakeDSPFileSetupWidget {widget args} {
    global outputDir root index comment abort

    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent \
      -height 30 \
      -packOption {-side top -fill x} 
    
    set w $parent$widget.frame

    APSLabeledEntry .outputDir -parent $w \
      -label "Output directory:" -textVariable outputDir \
      -contextHelp "Enter a name for the output file directory." -width 55

    APSButton .daily -parent $w.outputDir -packOption "-anchor e" \
      -text "daily" -size small \
      -command {set outputDir [APSGoToDailyDirectory -subdirectory Septum]}

    APSLabeledEntry .root -parent $w -label "Root name of file: " \
      -textVariable root \
      -contextHelp "Enter the root name of the file for the corrector error output <root>-nnn."

    APSLabeledEntry .index -parent $w -label "Index (incremented just before execution): " -textVariable index \
      -contextHelp "Enter the index (minus 1) to be part of the name of the output file. The index is incremented by 1 before execution."

    APSLabeledEntry .comment -parent $w -label "Comment: " -textVariable comment \
      -width 50 \
      -contextHelp "Enter a comment."

}

proc MakeSeptumMeasWidget  {widget args} {

    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent \
      -height 30 \
      -packOption {-side top -fill x} 
    
    set w $parent$widget.frame

    APSButton .dspScopeSetup -parent $w \
      -text "DSP Setup" \
      -command {DSPScopeSetup -statusCallback SetStatus} \
      -packOption {-side left} \
      -contextHelp "This button sets up the DSP scope for data collection."

    APSButton .collectData -parent $w \
      -text "Collect Data" \
      -command {incr index; CollectData -output $outputDir/$root-[format %03ld $index] -comment $comment -statusCallback SetStatus} \
      -packOption {-side left} \
      -contextHelp "This button collect DSP scope data."

    APSButton .abortbutton -parent $w -text "Abort" \
      -packOption "-side left" \
      -command {set abort 1} \
      -contextHelp "Abort data collection."

    APSButton .plotData -parent $w \
      -text "Plot Data" \
      -command {PlotData -file $outputDir/$root-[format %03ld $index]} \
      -packOption {-side left} \
      -contextHelp "This button plots the DSP scope data."

    APSButton .plotDataZ -parent $w \
      -text "Plot Zoomed Data" \
      -command {PlotData -zoomed 1 \
                  -file $outputDir/$root-[format %03ld $index]} \
      -packOption {-side left} \
      -contextHelp "This button plots the zoomed-in DSP scope data."

    APSButton .plotDataSmoothed -parent $w \
      -text "Plot Smoothed Data" \
      -command {PlotData -zoomed 1 \
                  -file $outputDir/$root-[format %03ld $index].smoo} \
      -packOption {-side left} \
      -contextHelp "This button plots the smoothed DSP scope data."

    return
}

proc PlotData {args} {
    set file ""
    set zoomed 0
    APSParseArguments {file zoomed}
    if {![file exists $file]} {
        return -code error "PlotData: File $file doesn't exist"
    }
    if $zoomed {
        set options -filter=col,t,0,0.04
    } else {
        set options "-filter=col,t,0,0.08"
		  }
		  if [catch {eval exec sddsplot $options -grap=sym,conn=sub,vary=sub \
				-col=t,S38A:H* $file -topline=@Comment \
				-leg \
                 -mode=y=offset \
                 -col=t,S37FB:S38A:H* FFdrives \
                 \"-leg=spec=S38 Command\" \
                 -end \
                 -col=t,S39A:H* $file -topline=@Comment \
				-leg \
                 -mode=y=offset \
                 -col=t,S39FB:S39A:H* FFdrives \
                 \"-leg=spec=S39 Command\" \
                 -end \
                 & \
             } result] {
        return -code error $result
    }
    if [catch {exec sddsprocess $file -pipe=out \
                 "-def=col,tMod,t 0.5 mod" \
                 | sddsbreak -pipe=in $file.break \
                 -decreaseof=tMod \
             } result] {
        return -code error $result
    }

    
    if [catch {exec sddsplot -col=tMod,S3*A:H3:Error $file.break  \
                 -split=pages -grap=sym,conn=sub,vary=sub \
                 -group=nameindex -sep=nameindex \
                 -filter=col,tMod,0,0.04 &\
             } result] {
        return -code error $result
    }
    return
}

proc MakeSeptumProcessWidget {widget args} {
    global outputDir root index comment abort startTime tau

    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent \
      -height 30 \
      -packOption {-side top -fill x} 
    
    set w $parent$widget.frame


    APSLabeledEntry .start -parent $w -label "Start time (ms): " -textVariable startTime \
      -width 40 \
      -contextHelp "Start time of first waveform as it appears on the RTFB corrector error signal triggered on P0."

    APSLabeledEntry .tau -parent $w -label "Time constant (s):" \
      -textVariable tau \
      -width 40 \
      -contextHelp "Time constant for deconvolving." 
    
    APSButton .processData -parent $w \
      -text "Process Data" \
      -command {ProcessData -input $outputDir/$root-[format %03ld $index].smoo \
                  -outputRoot $outputDir/$root-[format %03ld $index] \
                  -startTime $startTime \
                  -tau $tau \
                  -gain $gain \
                  -statusCallback SetStatus} \
      -packOption {-side left} \
      -contextHelp "This button processes the DSP scope data and creates 4 corrector waveform files."

    APSButton .plotAdjustment -parent $w \
      -text "Plot Adjustment Data" \
      -command {PlotAdjustmentData -input $outputDir/$root-[format %03ld $index] \
                  -statusCallback SetStatus} \
      -packOption {-side left} \
      -contextHelp "This button plots the adjustment waveform calculated."

}

proc MakeSeptumModWaveformWidget {widget args} {
    global outputDir root index comment abort firstWaveform startTime period

    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent \
      -height 30 \
      -packOption {-side top -fill x} 
    
    set w $parent$widget.frame
    APSLabeledEntry .gain -parent $w -label "Gain:" \
      -textVariable gain \
      -width 40 \
      -contextHelp "Gain to apply to correction." 
    
    APSButton .apply -parent $w \
      -text "Apply Data" \
      -command {Apply -root $outputDir/$root-[format %03ld $index].smoo \
                  -gain $gain \
                  -statusCallback SetStatus} \
      -packOption {-side left} \
      -contextHelp "This button processes the DSP scope data and creates 4 corrector waveform files."
    
}

proc Apply {args} {
    set root ""
    set gain 1.0
    set statusCallback ""
    APSParseArguments {root gain statusCallback}

    set wfmList {S37FB:S38A:H3:feedForwardC S39FB:S39A:H3:feedForwardC}
    set corrList {S38A:H3 S39A:H3}

    set tmpfile /tmp/[APSTmpString]
    # read drives, add correction, then set drives.
    foreach corr $corrList wfm $wfmList {
        if [catch {exec sddswget -PV=$wfm $tmpfile.$corr.drive \
                 } result ] {
            return -code error "Apply(0): $result" 
        }
        if [catch {exec sddsxref $tmpfile.$corr.drive $root.$corr.adj \
                     -pipe=out \
                     -take=Adjustment \
                     | sddsprocess -pipe=in $root.$corr.command \
                     "-redef=col,Waveform,Waveform Adjustment $gain * +" \
                 } result ] {
            return -code error "Apply(1): $result" 
        }
        if [catch {exec sddswput $root.$corr.command \
                 } result ] {
            return -code error "Apply(2): $result" 
        }
    }
    
    if [catch {exec cavput -list=SRFB:GBLM:DSPLoadParamsBO=1 -pen=15 \
             } result ] {
        return -code error "Apply(2): $result" 
    }
    
    #load in the files
    if [string length $statusCallback] {
        $statusCallback "Application of correction done."
    }
}

proc MakeTransferSeptumCorrFrameWidget {widget args} {

    set parent ""
    APSParseArguments {parent}

    APSFrame $widget -parent $parent \
      -height 30 \
      -packOption {-side top} 

    set w $parent$widget.frame
    APSButton .swap -parent $w \
      -text "TransferSeptumCorrectors" \
      -command {transferSeptumCorrectors -statusCallback SetStatus} \
      -packOption {-side left -expand 1} \
      -contextHelp "This button is used to transfer Septum correctors."

}

proc MakeSeptumPlotFrameWidget {widget args} {

    global Title Delay plotDirectory
    set parent ""
    APSParseArguments {parent statusCallback}
    
    APSFrame $widget -parent $parent -label "Plot Septum Data" \
      -height 30 \
      -packOption {-side top} 
    
    set w $parent$widget.frame
    
    APSFrame .septumPlotFrame -parent $w \
      -height 30 \
      -packOption {-side top}

    APSLabeledEntry .plotDirEntry -parent $w.septumPlotFrame.frame -width 30 \
      -textVariable plotDirectory \
      -packOption {-side top -fill x} \
      -label "Working Directory: "

    APSLabeledEntry .titleEntry -parent $w.septumPlotFrame.frame -width 30 \
      -textVariable Title \
      -packOption {-side top -fill x} \
      -label "Septum plot title:  "

    APSLabeledEntry .delayEntry -parent $w.septumPlotFrame.frame -width 4 \
      -textVariable Delay \
      -packOption {-side top -fill x} \
      -label "Delay (ms):  " \
      -contextHelp "Delay in ms for Septum"

    APSFrame .plotMostRecentFrame -parent $w.septumPlotFrame.frame \
      -height 30 \
      -packOption {-side top -fill x} 

    APSButton .plotSeptumMostRecentFrame -parent $w.septumPlotFrame.frame.plotMostRecentFrame.frame \
      -text "Plot Most Recent Septum Data" \
      -command "PlotMostRecentSeptumData -statusCallback SetStatus" \
      -contextHelp "This button plots the most recent Septum data." \
      -packOption "-side top"
    
    APSButton .plotSeptumSelectedDataFrame -parent $w.septumPlotFrame.frame \
      -text "Plot Selected Septum Data" \
      -command "PlotSeptumData -statusCallback SetStatus" \
      -packOption "-side top" \
      -contextHelp "This is used to select a Septum data file for plotting."
    
}

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

# Sets the relative Septum amplitude factor and toggles the Septum main supply current.


# Transfers Septum corrector values.

proc transferSeptumCorrectors {args} {
        
    global ControlStatus

    APSParseArguments {statusCallback}

    set valueList [exec cavget -list=ID04b:ai542_ -range=beg=16,end=23 ]
    set i 0
    set j 1
    foreach item $valueList {
        lappend argList ID04b:set_corr_$j=[lindex $valueList $i]
        incr i
        incr j
    }
    catch {exec cavput -list=[join $argList ,]}
    if {$statusCallback!=""} {
        $statusCallback "Septum corrector values transferred."
    }
}


proc DSPScopeSetup {args} {

    global ControlStatus configFile
    
    APSParseArguments {statusCallback}

    APSRestoreSRFBDspScope -filename $configFile -timing 1 \
      -channels 1 -clearMode 1 
    
    if {$statusCallback!=""} {
        $statusCallback "DSP scope setup complete."
    }
}

proc CollectData {args} {
    global configFile scalarsFile abort

    APSParseArguments {statusCallback output comment}

    if ![string length $output] {
        return -code error "CollectData: No output file specified."
    }
    if [file exists $output] {
        return -code error "CollectData: File $output already exists!"
    }
    if {[exec cavget -pend=15 -list=SRFB:DS:SampleBO] == "Off"} {
        armDSPscope -statusCallback $statusCallback
    }
    set abort 0

	 #turn on septum
	 exec cavput -list=Mt:Ddg3chan0.GATE=1

    waitForTrigger -statusCallback $statusCallback
    if {$statusCallback!=""} {
        $statusCallback "Collecting data from DSPscope...[exec date +%H:%M:%S]"
    }
    update
	 #turn off septum
	 exec cavput -list=Mt:Ddg3chan0.GATE=0

    if [catch {exec sddswmonitor $configFile $output \
                 -comment=Comment,[APSMakeSafeQualifierString $comment] \
                 -ezca=0.01,2000 -scalars=$scalarsFile \
             } result] {
        if {$statusCallback!=""} {
            $statusCallback "CollectData: Error with sddswmonitor: $result"
            $statusCallback "Continuing anyway..."
        }
    }
    if [catch {exec sddswmonitor -PV=S37FB:S38A:H3:feedForwardC,S39FB:S39A:H3:feedForwardC \
                 FFdrives \
                 -erase \
                 -comment=Comment,[APSMakeSafeQualifierString $comment] \
                 -ezca=0.01,2000 -scalars=$scalarsFile \
             } result] {
        if {$statusCallback!=""} {
            $statusCallback "CollectData: Error with sddswmonitor: $result"
            $statusCallback "Continuing anyway..."
        }
    }
    if [catch {exec sddsprocess $output -nowarn \
                 "-def=para,TickTime,SRFB:fsAO rec,units=sec" \
                 "-redef=col,t,Index TickTime *,units=sec" \
             } result] {
        return -code error "CollectData: Error with sddsprocess: $result"
    }

    if [catch {AverageCorrectorErrorData -inputFile $output\
             } result ] {
        return -code error "CollectData: $result"
    }
 
    if [catch {exec sddssmooth $output $output.smoo \
                 -savitzkyGolay=6,6,2 -col=S* \
             } result] {
        return -code error "CollectData: Error with sddssmooth: $result"
    }
    
    file delete -force ${output}~

    if [catch {exec sddsprocess FFdrives -nowarn \
                 "-def=para,TickTime,SRFB:fsAO rec,units=sec" \
                 "-redef=col,t,Index TickTime *,units=sec" \
             } result] {
        return -code error "CollectData: Error with sddsprocess: $result"
    }
    if {$statusCallback!=""} {
        $statusCallback "Collecting done."
    }
}

proc armDSPscope {args} {
    global abort
    
    APSParseArguments {statusCallback}
    set dum 1
    while {[exec cavget -pend=15 -list=SRFB:GBL:FeedbackBlockedBI] == "Blocked"} {
        if {$dum == 1} {
            set status "Waiting for feedback block to clear... [exec date +%H:%M:%S]"
            set dum 0
        }
        APSWaitWithUpdate -waitSeconds 1 -updateInterval 0.5
    }
    
    set dum 1
    while {(([exec cavget -pend=15 -list=SRFB:GBL:HorzTripBI] == "Trip") || \
              ([exec cavget -pend=15 -list=SRFB:GBL:VertTripBI] == "Trip")) && \
             ($abort == 0) } {
        if {$dum == 1} {
            if {$statusCallback!=""} {
                $statusCallback "Waiting for trips to be reset... [exec date +%H:%M:%S]"
            }
            set dum 0
        }
        APSWaitWithUpdate -waitSeconds 1 -updateInterval 0.5
    }

    if {$abort == 0} {
        if {$statusCallback!=""} {
            $statusCallback "Arming DSPscope... [exec date +%H:%M:%S]"; update
        }
        exec cavput -pend=15 -list=SRFB:DS:SampleBO=1
        while {[exec cavget -pend=15 -list=SRFB:DS:SampleBO] == "Off"} {
            APSWaitWithUpdate -waitSeconds 1 -updateInterval 0.5
        }
    }
}

proc waitForTrigger {args} {
    global abort

    APSParseArguments {statusCallback}

    if {$abort == 0} {
        set triggered 0
        if {$statusCallback!=""} {
            $statusCallback "Waiting for dspscope to trigger... [exec date +%H:%M:%S]"; update
        }
        while {($triggered == 0) && ($abort == 0)} {
            if {[exec cavget -pend=15 -list=SRFB:DS:SampleBO] == "Off" } {
                set triggered 1
            }
            APSWaitWithUpdate -waitSeconds 1 -updateInterval 1
        }
        
        if {$triggered == 1} {
            if {$statusCallback!=""} {
            $statusCallback "Triggered [exec date +%H:%M:%S]"
            }
            update
        } else {
            if {$statusCallback!=""} {
                $statusCallback "Aborted... [exec date +%H:%M:%S]"
            }
            update
            set triggered 0
        }
    }
}

proc ProcessData {args} {
    set outputRoot ""
    set startTime 0.012
    set tau 0.001
    APSParseArguments {input outputRoot startTime tau}

    if ![file exists $input] {
        return -code error "ProcessData: Can't find file $input" 
    }

    set timeLimit 0.100
    # create a response file for with time step equal to the
    # signal file. (Whatever the tick time in RTFB is).
    set tickTime [lindex [exec sdds2stream -para=TickTime $input] 0]
    exec sddssequence -pipe=out \
      -define=t -sequence=begin=0,end=$timeLimit,delta=$tickTime  \
      | sddsprocess -pipe=in response \
      -def=para,tau,$tau \
      "-def=col,response,t tau / chs exp tau /"


    # 128 tics is the limit for FF correction waveforms in the RTFB
    # system but we can analyze more than that. We keep the first 127
    # ms of the deconvolved waveform for interpolation of the afg
    # waveform.
    # use response to do a deconvolution
    set tmpfile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $input $tmpfile.1 \
                 "-redef=col,t,t $startTime -" \
                 -proc=t,first,tOffset \
                 "-redef=col,t,t tOffset -" \
                 -filter=col,t,0,$timeLimit \
             } result ] {
        return -code error "ProcessData: $result" 
    }
    # remove last page which is an incomplete waveform
    set numPages [llength [exec sdds2stream -rows=bare  $tmpfile.1]]

    if [catch {exec sddsprocess $tmpfile.1 $tmpfile.2 \
                 -proc=S*A:H3:Error,average,%sBaseline,tail=20 \
                 -proc=S*A:V3:Error,average,%sBaseline,tail=20 \
                 "-redef=col,%s,%s %sBaseline -,select=S*A:H3:Error" \
                 "-redef=col,%s,%s %sBaseline -,select=S*A:V3:Error" \
             } result ] {
        return -code error "ProcessData: $result" 
    }
    set corrList {S38A:H3 S39A:H3}
    foreach corr $corrList {
        if [catch {exec sddsconvolve $tmpfile.2 \
                     response $input.${corr}.adj \
                     -deconvolve \
                     -signalColumns=t,${corr}:Error \
                     -responseColumns=t,response \
                     -outputColumns=t,Adjustment \
                 } result ] {
            return -code error "ProcessData: $result" 
        }
        if [catch {exec sddsprocess $input.${corr}.adj \
                     -def=col,Index,i_row -noWarning \
                 } result ] {
            return -code error "ProcessData: $result" 
        }
        catch {file delete $input.${corr}.adj~}
        
    }

    # create file for reading into feedback ioc
    exec sddsplot -leg -grap=line,vary -axes=x \
      -col=t,S38A:H3:Error $tmpfile.2 \
      -col=t,Adjustment $input.S38A:H3.adj \
      -end \
      -col=t,S39A:H3:Error $tmpfile.2 \
      -col=t,Adjustment $input.S39A:H3.adj \
      -end \
      &
    
    return

}

proc AverageCorrectorErrorData {args} {
    set inputFile ""
    APSStrictParseArguments {inputFile}
    if [catch {exec sddsprocess $inputFile  -pipe=out \
                 "-def=col,Period,t 0.5 / int,type=long" \
                 | sddsbreak -pipe \
                 -increaseof=Period \
                 | sddsconvert -pipe \
                 -keeppages=5 \
                 | sddsenvelope -pipe \
                 -mean=S*\[HV\]* -copy=Index,t \
                 | sddsprocess -pipe \
                 -process=t,first,tFirst \
                 -process=Index,first,IndexFirst \
                 "-redef=col,Index,Index IndexFirst -" \
                 "-redef=col,t,t tFirst -" \
                 | sddsxref -pipe $inputFile \
                 -transfer=para,Comment,TickTime,MainCurrent \
                 -leave=* \
                 | sddsconvert -pipe=in $inputFile.ave \
                 -edit=col,*Mean*,%/Mean// \
             } result ] {
        return -code error "AverageCorrectorErrorData: $result"
    }
    return
}

# Procedure to plot the most recent Septum data.
# this is probably copied from another GUI. Needs
# work since I don't know anything about a $root-s4s5-2.4s.sdds  file.
proc PlotMostRecentSeptumData {args} {

    global ControlStatus Title Delay

    APSStrictParseArguments {statusCallback}
    set mostRecentFile [lindex [lsort [glob ??????-s*s*-*s.sdds]] end]
    
    catch {regexp {(......)-s.*s.*-.*s.sdds} $mostRecentFile {} root}

    if ![string length $root] {
        if {$statusCallback!=""} {
            $statusCallback "You must give a valid rootname."
        }
        APSAlertBox .alert -errorMessage "You must give a valid rootname."
        return 0
    }

    catch {exec sddsplot -lay=2,2 -title= \
             -limit=xmin=[expr 0.0 + $Delay],xmax=[expr 0.4 + $Delay]\
             -topline=$root \
             -col=t,(S*H*Error,S*V*Error) -sep -mode=y=offset \
             -same $root-s4s5-2.4s.sdds \
             -title=[APSMakeSafeQualifier $Title] -end \
             -col=t,(S*H3,S*V3) -sep -mode=y=offset \
             -same $root-s4s5-2.4s.sdds \
             "-title=$Title" -end &}
}

proc PlotSeptumData {args} {

    global ControlStatus Title Delay plotDirectory
    
    APSParseArguments {title delay statusCallback}
    
    set fileList [glob ??????-s*s*-*s.sdds]
    set itemList ""
    foreach file $fileList {
        catch {regexp {(......)-s.*s.*-.*s.sdds} $file {} root}
        lappend itemList $root
    }

    set selectFile [APSChooseItemFromList \
                      -name "Raw Data Selection" \
                      -itemList $itemList \
                      -returnList $fileList \
                      -returnIndices 0 \
                      -multiItem 0 \
                      -contextHelp "Select a Septum data file to plot"]

    catch {regexp {(......)-s.*s.*-.*s.sdds} $selectFile {} root}

    exec sddsplot -lay=2,2 -title= \
      -limit=xmin=[expr 0.0 + $Delay],xmax=[expr 0.4 + $Delay]\
      -topline=$root \
      -col=t,(S*H*Error,S*V*Error) -sep -mode=y=offset \
      -same ${selectFile} \
      -title=$Title -end \
      -col=t,(S*H3,S*V3) -sep -mode=y=offset \
      -same ${selectFile} \
      "-title=$Title" -end \
      &
}


# Build Application

MakeSeptumStatus
MakeSeptumSetupWidget .setup -parent .userFrame
MakeSeptumMeasWidget .meas -parent .userFrame
MakeSeptumProcessWidget .proc -parent .userFrame
MakeSeptumModWaveformWidget .mod -parent .userFrame

set configFile /home/helios/oagData/sr/RTFB/monitorFiles/S38S39CorrError.dspscope
set scalarsFile /home/helios/oagData/sr/RTFB/monitorFiles/SRFBTrigReadStatus.monitor

set index -1
set root septumLeakage
set comment test

set startTime 0.000
set tau 0.001
set outputDir .
set index -1
set abort 0
set gain 1.0

