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

proc ComputeLossFactor {args} {
    set sigmaIn ""
    set impedanceFile ""
    APSParseArguments {sigmaIn impedanceFile}
   
    set const [expr 1e-9 / $sigmaIn / 0.0254 / sqrt ( 2 * acos (-1.0) )]
    set startS -100
    set endS 100 
    ### maximum frequency in GHz
    set fMax 10
    ### delta is one 10th of bunch sigma 
    #set delta [expr $sigmaIn / 10]
    set delta 0.05
    ### sqrt 2 factor due to folding negative f to positive
    
    if ![file exist chargeDensity.sdds.$sigmaIn] {
        if [catch {exec sddssequence -define=s \
                     -sequence=begin=$startS,end=$endS,delta=$delta \
                     -pipe=out \
                     | sddsprocess \
                     "-redefine=col,qDensity,s $sigmaIn / 2 pow -1 * 2 / exp $const * " \
                     "-redefine=col,t,s 0.0254 * c_mks / 1.0e9 *,units=ns" \
                     "-redefine=col,qDensity,qDensity 2 sqrt *" \
                     -pipe=in chargeDensity.sdds.$sigmaIn } result] {
            return -code error "Error creating chargeDensity.sdds.$sigmaIn"
        }
    }
    if ![file exist chargeDensity.sdds-fft.$sigmaIn] {
        if [catch {exec sddsfft chargeDensity.sdds.$sigmaIn -col=t,qDensity -padwithzeroes \
                     -pipe=out \
                     |  sddsprocess -pipe \
                     -filter=col,f,0,100 \
                     | sddsprocess \
                     "-redefine=col,FFTqDensity,f 0 == pop pop ? 2.0 FFTqDensity * : FFTqDensity \$" \
                     "-redefine=col,powerDensity,f 0 == pop pop ? 2.0 FFTqDensity * 2 pow : FFTqDensity 2 pow \$" \
                     -pipe=in chargeDensity.sdds-fft.$sigmaIn } result] {
            return -code error "Error create chargeDensity.sdds-fft.$sigmaIn"
        }
    }
    
    if [catch {exec sddsinterp chargeDensity.sdds-fft.$sigmaIn \
                 -col=f -fileValues=$impedanceFile,col=f  \
                 -pipe=out \
                 | sddsxref \
                 -pipe ${impedanceFile} \
                 -equate=f -take=z \
                 | sddsprocess "-redefine=col,y,z powerDensity *" \
                 -pipe \
                 | sddsprocess -process=y,average,yAve \
                 -process=f,spread,fSpread \
                 "-redefine=para,LossF,yAve fSpread * 2 * pi * 1e18 *,units=nJ" \
                 -pipe=in chargeDensity.sdds-fft-xref.$sigmaIn  } result] {
        return -code error "Error compute loss factor: $result"
    }
    set lossFactor [exec sdds2stream -par=LossF chargeDensity.sdds-fft-xref.$sigmaIn]
    exec rm chargeDensity.sdds-fft-xref.$sigmaIn
    return $lossFactor
}

proc SetLossStatus {text} {
    global status
    set status "$text"
    update
}

proc ComputeLossCurve {args} {
    set impedanceFile ""
    set outputFile ""
    set root ""
    APSParseArguments {impedanceFile outputFile root}

    global  sigmaStart sigmaEnd sigmaDelta 
    set sigmaList ""
    set lossList ""
    for {set sigma $sigmaStart} {$sigma<$sigmaEnd} {set sigma [expr $sigma + $sigmaDelta]} {
        set sigma [format %.3f $sigma]
        if [catch {ComputeLossFactor -sigmaIn $sigma -impedanceFile $impedanceFile} result] {
            return -code error "Error processing loss for $root: $result"
        }
        lappend sigmaList $sigma
        lappend lossList $result
    }
    set m_cks 2.99792458e8
    if [catch {exec sddsmakedataset -pipe=out -col=sigma,type=double -data=[join $sigmaList ,] \
                 -par=TypeName,type=string -data=$root \
                 -col=loss,type=double -data=[join $lossList ,]  \
                 | sddsprocess -pipe=in $outputFile \
                 "-redefine=col,sigmaPS,sigma 0.0254 * $m_cks / 1e12 *,units=ps" } result] {
        return -code error "Error making file $outputFile: $result"
    }
    exec sddsplot -grap=symbol,sub=1,connect=1,thick=2,fill,scale=3 -col=sigmaPS,loss $outputFile -topline=@TypeName &
    
}
proc Process {args} {
    global dirs sigmaStart sigmaEnd sigmaDelta outputDir dataDir
    eval global $dirs
    
    cd $outputDir
    foreach dir $dirs {
        if [set $dir] {
            set file $dataDir/$dir/RealZ.sdds
            set root [file root [file tail [file readlink $file]]]
            if ![file exist $file] {
                SetLossStatus "$file does not exist"
                continue
            }
            set outputFile $root.loss
            SetLossStatus "Processing loss for $root..."
            if [catch {ComputeLossCurve -impedanceFile $file -outputFile $outputFile -root $root} result] {
                return -code error "Error computing loss for $root: $result"
            }
        }
    }
}

proc Plot {args} {
    global dirs sigmaStart sigmaEnd sigmaDelta outputDir dataDir
    eval global $dirs
    
    cd $outputDir
    foreach dir $dirs {
        if [set $dir] {
            set file [glob -nocomplain $dataDir/$dir/RealZ.sdds]
            set file $dataDir/$dir/RealZ.sdds
            set root [file root [file tail [file readlink $file]]]
            if ![file exist $file] {
                SetLossStatus "$file does not exist"
                continue
            }
            set outputFile $root.loss
            if ![file exist $root.loss] {
                SetLossStatus "Processing loss for $root..."
                if [catch {ComputeLossCurve -impedanceFile $file -outputFile $outputFile -root $root } result] {
                    return -code error "Error computing loss for $root: $result"
                }
            } else {
                exec sddsplot -grap=symbol,sub=1,connect=1,thick=2,fill,scale=3 -col=sigmaPS,loss $outputFile -topline=@TypeName &
            }
        }
    }
}

proc Print {args} {
    global dirs sigmaStart sigmaEnd sigmaDelta outputDir dataDir printSigma
    eval global $dirs
    
    cd $outputDir
    set deviceList0 [exec sdds2stream $dataDir/deviceList -col=device]
    set countsList0 [exec sdds2stream $dataDir/deviceList -col=totalCounts]
    set deviceList ""
    set lossList ""
    set countsList ""
    set deviceLossList ""
    set sumLoss 0
    if ![file exist deviceLossAt$printSigma] {
        foreach device $deviceList0 counts $countsList0 {
            if ![file exist $dataDir/$device] {
                SetLossStatus "$dataDir/$device does not exist!"
                continue
            }
            set file [glob -nocomplain $dataDir/$device/RealZ.sdds]
            set file $dataDir/$device/RealZ.sdds
            set root [file root [file tail [file readlink $file]]]
            if ![file exist $file] {
                SetLossStatus "$file does not exist"
                continue
            }
            if [catch {ComputeLossFactor -sigmaIn $printSigma -impedanceFile $file} loss] {
                return -code error "Error computing loss for $dir: $loss"
            }
            lappend deviceList $device
            lappend lossList $loss
            lappend countsList $counts
            lappend deviceLossList [expr $loss * $counts]
        }
        if [catch {exec sddsmakedataset -pipe=out -col=DeviceName,type=string -data=[join $deviceList ,] \
                     -col=DeviceCounts,type=long -data=[join $countsList ,] \
                     -col=LossFactor,type=double -data=[join $lossList ,] \
                     -col=DeviceLoss,type=double -data=[join $deviceLossList ,] \
                     | sddsprocess -pipe -process=DeviceLoss,sum,TotalLoss \
                     | sddsprocess -pipe=in  \
                     "-define=col,Percentage,DeviceLoss TotalLoss / 100 *" deviceLossAt$printSigma } result] {
            return -code error "Error creating loss file: $result"
        }
        
    }
    if ![file exist  deviceLossAt$printSigma.print] {
        if [catch {exec sddsprintout deviceLossAt$printSigma deviceLossAt$printSigma.print "-title=Loss Factor for all devices" \
                     -col=DeviceName,format=%30s -col=DeviceCounts,format=%20d -col=DeviceLoss,format=%20.1f -col=Percentage,format=%20.2f } result] {
            return -code error "Error creating print file: $result"
        }
    }

    APSFileDisplayWindow [APSUniqueName .] -fileName   deviceLossAt$printSigma.print  -width 120  -height 30 -printCommand "enscript -r"
}

proc ComputeRealImageZ {args} {
    global dataDir outputDir
    cd $outputDir
    SetLossStatus "compute real and imaginary impedance for all devices..."
    
    set pageList [exec sdds2stream -col=PageNumber $dataDir/deviceList ]
    set deviceList [exec sdds2stream -col=device $dataDir/deviceList ] 
    set totalList [exec sdds2stream -col=totalCounts $dataDir/deviceList ]
    
    set fileList1 ""
    set fileList2 ""
    foreach device $deviceList {
	lappend fileList1 $dataDir/$device/RealZ.sdds
        lappend fileList2 $dataDir/$device/ImagZ.sdds
    }
    if [catch { eval exec sddscombine $fileList1 -pipe=out \
                  | sddsenvelope \
                  -sum=1,zDevice \
                  -copy=f \
                  -pipe \
                  | sddsprocess \
                  "-redefine=col,z,zDeviceSum" \
                  -pipe=in allDeviceRealZ.sdds } result] {
        return -code error "Error creating allDeviceRealZ.sdds : $result"
    }
    if [catch {eval exec sddscombine $fileList2 -pipe=out \
                 | sddsenvelope \
                 -sum=1,zDevice \
                 -copy=f \
                 -pipe \
                 | sddsprocess \
                 "-redefine=col,z,zDeviceSum" \
                 -pipe=in allDeviceImagZ.sdds } result] {
        return -code error "Error creating allDeviceImagZ.sdds : $result"
    }
    
    SetLossStatus "allDeviceRealZ.sdds and allDeviceImagZ.sdds are created at the output directory."
}

proc ComputeOneDevice {args} {
    global dirs sigmaStart sigmaEnd sigmaDelta outputDir dataDir printSigma
    set dir ""
    APSParseArguments {dir}
    cd $outputDir
    set file $dataDir/$dir/RealZ.sdds
    set root [file root [file tail [file readlink $file]]]
    if ![file exist $file] {
        SetLossStatus "$file does not exist"
        continue
    }
    set outputFile $root.loss
    SetLossStatus "Processing loss for $root..."
    if [catch {ComputeLossCurve -impedanceFile $file -outputFile $outputFile -root $root} result] {
        return -code error "Error computing loss for $root: $result"
    }
    exec sddsplot -grap=symbol,sub=1,connect=1,thick=2,fill,scale=3 -col=sigmaPS,loss $outputFile -topline=@TypeName &
    
}

proc Sum {args} {
    global dirs sigmaStart sigmaEnd sigmaDelta outputDir dataDir printSigma
    eval global $dirs
    cd $outputDir
    set deviceList ""
    foreach dir $dirs {
        if {$dir=="allDevices"} {
            continue
        }
        if [set $dir] {
            lappend deviceList $dir
        }
    }
    if [llength $deviceList]==1 {
        ComputeOneDevice -dir $deviceList
        return
    }
    #sum device and do computation
    set deviceLossList ""
    set countList ""
    set lossList ""
    set fileList1 ""
    set fileList2 ""
    foreach device $deviceList {
        set file  $dataDir/$device/RealZ.sdds
        lappend fileList1 $file
        lappend fileList2  $dataDir/$device/ImagZ.sdds
        set count [exec sdds2stream -par=deviceCounts $file]
        if [catch {ComputeLossFactor -sigmaIn $printSigma -impedanceFile $file} loss] {
            return -code error "Error computing loss for $device: $loss"
        }
        lappend deviceLossList [expr $count * $loss]
        lappend countList [format %.0f $count]
        lappend lossList $loss
    }
    if [catch {eval exec sddscombine $fileList1 -pipe=out \
                 | sddsenvelope \
                 -sum=1,zDevice \
                 -copy=f \
                 -pipe \
                 | sddsprocess \
                 "-redefine=col,z,zDeviceSum" \
                 -pipe=in $outputDir/sumDeviceRealZ.sdds } result] {
        return -code error "Error for compute sum Real: $result"
    }
    if [catch {eval exec sddscombine  $fileList2 -pipe=out \
                | sddsenvelope \
                -sum=1,zDevice \
                -copy=f \
                -pipe \
                | sddsprocess \
                "-redefine=col,z,zDeviceSum" \
                -pipe=in sumDeviceImagZ.sdds } result] {
        return -code error "Error for compute sum imag: $result"
    }
    if [catch {exec sddsmakedataset -pipe=out -col=DeviceName,type=string -data=[join $deviceList ,] \
                     -col=DeviceCounts,type=long -data=[join $countList ,] \
                 -col=LossFactor,type=double -data=[join $lossList ,] \
                 -col=DeviceLoss,type=double -data=[join $deviceLossList ,] \
                 | sddsprocess -pipe -process=DeviceLoss,sum,TotalLoss \
                 | sddsprocess -pipe=in  \
                 "-define=col,Percentage,DeviceLoss TotalLoss / 100 *" sumLossAt$printSigma } result] {
        return -code error "Error creating loss file: $result"
    }
    if [catch {exec sddsprintout sumLossAt$printSigma sumLossAt$printSigma.print "-title=Loss Factor for all devices" \
                 -par=TotalLoss,format=%.2f \
                 -col=DeviceName,format=%30s -col=DeviceCounts,format=%20d -col=DeviceLoss,format=%20.1f -col=Percentage,format=%20.2f } result] {
        return -code error "Error creating print file for sum loss: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -fileName sumLossAt$printSigma.print  -width 120  -height 30 -printCommand "enscript -r"
    
    return
    set fileList1 ""
    set fileList2 ""
    
    foreach device $deviceList {
        set count [exec sdds2stream -par=deviceCounts $dataDir/$device/RealZ.sdds]
        
        lappend fileList1 $dataDir/$device/RealZ.sdds
        lappend fileList2 $dataDir/$device/ImagZ.sdds
    }
    if [catch {eval exec sddscombine $fileList1 -pipe=out \
                 | sddsenvelope \
                 -sum=1,zDevice \
                 -copy=f \
                 -pipe \
                 | sddsprocess \
                 "-redefine=col,z,zDeviceSum" \
                 -pipe=in $outputDir/sumDeviceRealZ.sdds } result] {
        return -code error "Error for compute sum Real: $result"
    }
    if [catch {eval exec sddscombine  $fileList2 -pipe=out \
                | sddsenvelope \
                -sum=1,zDevice \
                -copy=f \
                -pipe \
                | sddsprocess \
                "-redefine=col,z,zDeviceSum" \
                -pipe=in sumDeviceImagZ.sdds } result] {
        return -code error "Error for compute sum imag: $result"
    }
    if [catch {ComputeLossCurve -impedanceFile $outputDir/sumDeviceRealZ.sdds -outputFile $outputDir/sumDeviceLoss.sdds  } result] {
        return -code error "Error compute sum loss; $result"
    }
}

set CVSRevisionAuthor "\$Revision: 1.0 $ \$Author: shang $"

APSApplication . -name "computeLossFactor" -version $CVSRevisionAuthor \
  -overview "compute pass loss factor."

set status ""
APSScrolledStatus .status -parent .userFrame -width 60 \
  -textVariable status -packOption "-fill both -expand true"

set dataDir /home/helios/oagData/par/chamberImpedance
set outputDir [APSGoToDailyDirectory -subdirectory parImpedance]
set oldDir [pwd]
cd $dataDir
set dirs [lsort [glob -type d *]]
set iall [lsearch -exact $dirs "allDevices"]
if {$iall>=0} {
    set dirs [lreplace $dirs $iall $iall]
    lappend dirs allDevices
}
set buttons ""
set maxLen 0
foreach dir $dirs {
    set $dir 0
    set len [string length $dir]
    if {$len>$maxLen} {
        set maxLen $len
    }
}
foreach dir $dirs {
    set len [string length $dir]
    if {$len<$maxLen} {
        set name $dir
        for {set i 0} {$i<[expr $maxLen-$len]} {incr i} {
            append name " "
        }
        lappend buttons $name
    } else {
        lappend buttons $dir
    }
}



APSCheckButtonFrame .check -parent .userFrame -buttonList $buttons -variableList $dirs \
  -allNone 1 -orientation vertical -limitPerRow 4 -label "Select type:"

set sigmaStart 0.59
set sigmaEnd 11
set sigmaDelta 0.59
set printSigma 0.59
APSLabeledEntryFrame .scan -parent .userFrame  -label "Sigma scan start/stop/delta" -variableList {sigmaStart sigmaEnd sigmaDelta} \
  -width 15 -orientation horizontal
APSLabeledEntry .dir -parent .userFrame -label "Output directory:" -textVariable outputDir -width 75
APSLabeledEntry .sig -parent .userFrame -label "Sigma for print loss of all devices:" -textVariable printSigma -width 50
APSButton .proc -parent .userFrame -text "Process" -command "Process"
APSButton .plot -parent .userFrame -text "Plot" -command "Plot"
APSButton .print -parent .userFrame -text "Print" -command "Print"
APSButton .compute -parent .userFrame -text "Compute Real/Imag Impedance" -command "ComputeRealImageZ"
APSButton .sum -parent .userFrame -text "Sum of selected devices" -command "Sum"
