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

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

APSApplication . -name "SREmittanceCalc" -version $CVSRevisionAuthor  -overview \
    "This application computes SR emittance from beam size measurements at 35BM."

set status Ready.
APSScrolledStatus .status -parent .userFrame -textVariable status

set tcl_precision 12

set etaX  0.068
set sigmaE 9.6e-4
set sigmaXres  35
set sigmaYres  35
set betaX  1.88
set betaY 19.4
APSFrame .params -parent .userFrame -label "Calculation parameters"
set w .userFrame.params.frame
APSLabeledEntry .betaX -parent $w -label "beta x (m): " \
  -textVariable betaX
APSLabeledEntry .betaY -parent $w -label "beta y (m): " \
  -textVariable betaY
APSLabeledEntry .etaX -parent $w -label "dispersion (m): " \
  -textVariable etaX
APSLabeledEntry .sigmaE -parent $w -label "sigma E/Eo: " \
  -textVariable sigmaE
APSLabeledEntry .sigmaXres -parent $w -label "sigma X resolution (um): " \
  -textVariable sigmaXres
APSLabeledEntry .sigmaYres -parent $w -label "sigma Y resolution (um): " \
  -textVariable sigmaYres
set nAverage 10
APSLabeledEntry .nave -parent $w -label "Number of readings to average: " \
    -textVariable nAverage

APSFrame .result -parent .userFrame -label "Readbacks and results"
set w .userFrame.result.frame
set sigmaX ?
set sigmaY ?
set current ?
set readTime ?
set readTimeSecs 0
APSLabeledOutput .sigmaX -parent $w -label "Raw sigma x (um): " \
  -textVariable sigmaX
APSLabeledOutput .sigmaY -parent $w -label "Raw sigma y (um): " \
  -textVariable sigmaY
APSLabeledOutput .current -parent $w -label "Beam current (mA): " \
  -textVariable current
APSLabeledOutput .readTime -parent $w -label "Time read: " \
  -textVariable readTime

set epsX ?
set epsY ?
set chi ?
APSLabeledOutput .epsX -parent $w -label "x emittance (nm): " \
  -textVariable epsX
APSLabeledOutput .epsY -parent $w -label "y emittance (nm): " \
  -textVariable epsY
APSLabeledOutput .chi -parent $w -label "coupling (%): " \
  -textVariable chi

proc ReadData {} {
    global sigmaX sigmaY nAverage readTime current readTimeSecs
    global epsX epsY chi
    if [catch {exec cavget -list=S:VID1:x:fit:cal:sigmaM,S:VID1:y:fit:cal:sigmaM,S-DCCT:CurrentM \
                    -repeat=num=$nAverage,pause=0.5,average} dataList] {
        APSAlertBox [APSUniqueName .] -errorMessage "$dataList"
    }
    set sigmaX [lindex $dataList 0]
    set sigmaY [lindex $dataList 1]
    set current [lindex $dataList 2]
    set readTimeSecs [exec timeconvert -breakdown=now]
    set readTime [exec timeconvert -seconds=$readTimeSecs -textOutput]
    set epsX ?
    set epsY ?
    set chi ?
}

proc UpdateCalculation {} {
    global sigmaX etaX sigmaXres betaX sigmaY sigmaYres betaY 
    global epsX epsY chi sigmaE readTime
    if [string compare $readTime ?]==0 {
        APSAlertBox [APSUniqueName .] \
          -errorMessage "No valid data for computations!  Try pressing the Read Data button."
        return
    }
    set epsX [expr (pow($sigmaX,2)-pow($etaX*1e6*$sigmaE,2)-pow($sigmaXres,2))/$betaX/1e3]
    set epsY [expr (pow($sigmaY,2)-pow($sigmaYres,2))/$betaY/1e3]
    set chi  [expr 100.0*$epsY/$epsX]
    
}

proc LogResult {} {
    global sigmaX etaX sigmaXres betaX sigmaY sigmaYres betaY
    global epsX epsY chi sigmaE current
    global readTime readTimeSecs
    if [string compare $readTime ?]==0 {
        APSAlertBox [APSUniqueName .] \
          -errorMessage "No valid data for computations!  Try pressing the Read Data button."
        return
    }
    set secsNow [exec timeconvert -breakdown=now]
    set age [expr ($secsNow-$readTimeSecs)/60.0]
    UpdateCalculation
    if $age>10 {
        if {![APSMultipleChoice [APSUniqueName .] \
                -question "The data for the present calculation is [format %.0lf $age] minutes old.  Do you still want to log it?" \
                -labelList {Yes No} \
                -returnList {1 0} ]} {
            return
        }
    }
    if [catch {exec logMessage -sourceId=SREmittanceCalc \
                 -tag=readTimeString $readTimeSecs \
                 -tag=epsXString $epsX -tag=epsYString $epsY \
                 -tag=couplingString $chi \
                 -tag=rawSigmaXString $sigmaX \
                 -tag=rawSigmaYString $sigmaY \
                 -tag=beamCurrentString [expr abs($current)] } result] {
        APSAlertBox [APSUniqueName .] \
          -errorMessage "Problem logging data: $result"
        return
    }
    APSSetVarAndUpdate status "Data logged."
}

proc SRPlotOpsEmittanceLog {args} {
    set startTimeList ""
    set endTimeList ""
    set quickSDDSplot 0
    set sddsExport 0
    APSStrictParseArguments {startTimeList endTimeList quickSDDSplot sddsExport}
    if [llength $startTimeList]!=4 {
        return -code error "SRPlotOpsEmittanceLog: invalid startTimeList list: expected year, month, day, and hour.  Got $startTimeList"
    }
    if [llength $endTimeList]!=4 {
        return -code error "SRPlotOpsEmittanceLog: invalid endTimeList list: expected year, month, day, and hour.  Got $endTimeList"
    }
    set startYear [lindex $startTimeList 0]
    set startMonth [lindex $startTimeList 1]
    set startDay [lindex $startTimeList 2]
    set startHour [lindex $startTimeList 3]
    set endYear [lindex $endTimeList 0]
    set endMonth [lindex $endTimeList 1]
    set endDay [lindex $endTimeList 2]
    set endHour [lindex $endTimeList 3]

    if [catch {APSConvertTimeToHours $startHour} hour] {
        return -code error "SRPlotOpsEmittanceLog: invalid starting hour."
        return 0
    }
    set startTime [exec timeconvert -breakdown=year=[lindex $startTimeList 0],month=[lindex $startTimeList 1],day=[lindex $startTimeList 2],hour=$hour]

    set endHour [lindex $endTimeList 3]
    if [catch {APSConvertTimeToHours $endHour} hour] {
        return -code error "SRPlotOpsEmittanceLog: invalid ending hour."
        return 0
    }
    set endTime [exec timeconvert -breakdown=year=[lindex $endTimeList 0],month=[lindex $endTimeList 1],day=[lindex $endTimeList 2],hour=$hour]

    if $startTime>=$endTime {
        return -code error "SRPlotOpsEmittanceLog: startTime later than endTime"
    }

    set logDir /home/helios/oagData/logDaemonData/SREmittanceCalc
    set logDaemonFiles \
      [APSFindFilesBetweenDates -tailsOnly 0 -extensionList {"*"}\
         -directory $logDir \
         -startDateList [APSFormatDate -year $startYear -month $startMonth \
                           -day $startDay -dateFormat list] \
         -endDateList [APSFormatDate -year $endYear -month $endMonth \
                         -day $endDay -dateFormat list] ]
    if ![llength $logDaemonFiles] {
        return -code error "No log files found (no date logged)."
    }
    set tmpFile /tmp/[APSTmpString]
    if {!$quickSDDSplot && !$sddsExport} {
        eval exec sddscombine $logDaemonFiles -pipe=out -merge \
          | sddsprocess -pipe=in $tmpFile \
          -scan=column,readTime,readTimeString,%lf,units=s \
          -filter=column,readTime,$startTime,$endTime \
          -numberTest=column,epsXString \
          -numberTest=column,epsYString \
          -numberTest=column,couplingString \
          -scan=column,epsX,epsXString,%lf,units=nm-rad \
          -scan=column,coupling,couplingString,%lf 
        exec sddsplot $tmpFile -ticks=xtime \
          {-title=Operator-logged emittance and coupling data.} \
          -column=readTime,epsX -end \
          -column=readTime,coupling {-ylabel=edit=ei/ \(%\)/} &
    } else {
        eval exec sddscombine $logDaemonFiles -pipe=out -merge \
          -delete=column,Time \
          | sddsprocess -pipe \
          -scan=column,Time,readTimeString,%lf,units=s \
          -filter=column,Time,$startTime,$endTime \
          -numberTest=column,epsXString \
          -numberTest=column,epsYString \
          -numberTest=column,couplingString \
          -scan=column,epsX,epsXString,%lf,units=nm-rad \
          -scan=column,epsY,epsYString,%lf,units=nm-rad \
          -scan=column,coupling,couplingString,%lf \
          -scan=column,rawSigmaX,rawSigmaXString,%lf,units=um \
          -scan=column,rawSigmaY,rawSigmaYString,%lf,units=um \
          -scan=column,beamCurrent,beamCurrentString,%lf,units=mA \
          | sddsconvert -pipe=in $tmpFile \
          -delete=column,*String
        if $quickSDDSplot {
            exec quickSDDSplot -dataFileList $tmpFile \
              -timeFilterStart "$startTimeList" \
              -timeFilterEnd "$endTimeList" &
        } else {
            exec sddsExportData -dataFileList $tmpFile \
              -timeFilterStart "$startTimeList" \
              -timeFilterEnd "$endTimeList" &
        }
    }
}

APSFrame .readwrite -parent .userFrame
APSButton .read -parent .userFrame.readwrite.frame -text "Read Data" -command ReadData \
    -contextHelp "Reads beam size data and current from EPICS."
APSButton .update -parent .userFrame.readwrite.frame -text "Compute" -command UpdateCalculation \
    -contextHelp "Computes emittances and coupling from beam size data and other parameters."
APSButton .readupdate -parent .userFrame.readwrite.frame -text "Read/Compute" -command \
    "ReadData; UpdateCalculation" \
    -contextHelp "Reads beam size data and current from EPICS, then computes emittances and coupling from beam size data and other parameters."

set logResultAllowedUsers [list asdops sr borland]
if [lsearch -exact $logResultAllowedUsers $env(LOGNAME)]!=-1 {
    APSButton .logreading -parent .userFrame.readwrite.frame -text "Log Result" -command \
        "LogResult" \
        -contextHelp "Logs the data shown on this screen."
}

APSFrame .plots -parent .userFrame -label "History Plot"  
set w .userFrame.plots.frame 
APSDateTimeAdjEntry .startDate -parent $w \
  -yearVariable StartYear -monthVariable StartMonth \
  -dayVariable StartDay -hourVariable StartHour \
  -label "Starting date/time (year, month, day, hour): " -defaultHour 0
APSDateTimeAdjEntry .endDate -parent $w \
  -yearVariable EndYear -monthVariable EndMonth \
  -dayVariable EndDay -hourVariable EndHour \
  -label "Ending date/time (year, month, day, hour):   " -defaultHour 24
APSIncrementDateVariables -offset -30 -unit day \
  -dayVariable StartDay -yearVariable StartYear \
  -monthVariable StartMonth
set StartHour 0
set EndHour 24
APSButton .plot -parent $w -text Plot -command \
  {SRPlotOpsEmittanceLog \
     -startTimeList [list $StartYear $StartMonth $StartDay $StartHour] \
     -endTimeList [list $EndYear $EndMonth $EndDay $EndHour]}
APSButton .qplot -parent $w -text "quickSDDSplot..." -command \
  {SRPlotOpsEmittanceLog -quickSDDSplot 1 \
     -startTimeList [list $StartYear $StartMonth $StartDay $StartHour] \
     -endTimeList [list $EndYear $EndMonth $EndDay $EndHour]}
APSButton .export -parent $w -text "Export..." -command \
  {SRPlotOpsEmittanceLog -sddsExport 1 \
     -startTimeList [list $StartYear $StartMonth $StartDay $StartHour] \
     -endTimeList [list $EndYear $EndMonth $EndDay $EndHour]}

