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

APSApplication . -name IDEnergyHistory

proc MakeDateTimeFrame {frame} {
    global StartTextDay StartDay StartTextMonth StartYear 
    global StartHour StartMinute StartSecond StartTime
    global EndTextDay EndDay EndTextMonth EndYear 
    global EndHour EndMinute EndSecond EndTime

    set s [clock seconds]

    frame $frame
    pack $frame

    frame $frame.from
    pack $frame.from
    set f $frame.from

    label $f.label -text "From:"
    spinbox $f.textday -values "Mon Tue Wed Thu Fri Sat Sun" \
      -width 3 -wrap true -textvariable StartTextDay \
      -command {TimeAdjusted Start %W %s %d} -bg white
    spinbox $f.day -from 1 -to 31 -width 2 -wrap true \
      -textvariable StartDay \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white
    spinbox $f.month \
      -values "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" \
      -width 3 -wrap true -textvariable StartTextMonth \
      -command {TimeAdjusted Start %W %s %d} -bg white
    spinbox $f.year -from 1900 -to 2100 -width 4 -wrap true \
      -textvariable StartYear \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white
    label $f.space -text " "
    spinbox $f.hour -from 0 -to 23 -width 2 -wrap true \
      -format %02.0f -textvariable StartHour \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white -bg white
    label $f.colon1 -text ":" -padx 0 -bd 0
    spinbox $f.minute -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable StartMinute \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white -bg white
    label $f.colon2 -text ":" -padx 0 -bd 0
    spinbox $f.second -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable StartSecond \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white -bg white

    bind $f.textday <Return> "TimeAdjustedManually"
    bind $f.day <Return> "TimeAdjustedManually"
    bind $f.month <Return> "TimeAdjustedManually"
    bind $f.year <Return> "TimeAdjustedManually"
    bind $f.hour <Return> "TimeAdjustedManually"
    bind $f.minute <Return> "TimeAdjustedManually"
    bind $f.second <Return> "TimeAdjustedManually"

    set StartTextDay [clock format $s -format %a]
    set StartDay [clock format $s -format %d]
    set StartTextMonth [clock format $s -format %b]
    set StartYear [clock format $s -format %Y]
    set StartHour 00
    set StartMinute 00
    set StartSecond 00

    set StartTime [clock scan "$StartTextDay $StartTextMonth $StartDay ${StartHour}:${StartMinute}:${StartSecond} $StartYear"]

    button $f.reset -text "Reset" -pady 0 -command "set StartTextDay $StartTextDay ; set StartDay $StartDay ; set StartTextMonth $StartTextMonth ; set StartYear $StartYear ; set StartHour $StartHour ; set StartMinute $StartMinute ; set StartSecond $StartSecond ; set StartTime $StartTime"

    pack $f.label $f.textday $f.day $f.month \
      $f.year $f.space $f.hour $f.colon1 \
      $f.minute $f.colon2 $f.second $f.reset -side left

    button $f.15min -text "last 15min" -pady 0 -command "TimePreset -minutes 15"
    pack $f.15min -side left
    button $f.30min -text "last 30min" -pady 0 -command "TimePreset -minutes 30"
    pack $f.30min -side left


    frame $frame.to
    pack $frame.to
    set f $frame.to

    label $f.label -text "  To:"
    spinbox $f.textday -values "Mon Tue Wed Thu Fri Sat Sun" \
      -width 3 -wrap true -textvariable EndTextDay \
      -command {TimeAdjusted End %W %s %d} -bg white
    spinbox $f.day -from 1 -to 31 -width 2 -wrap true \
      -textvariable EndDay \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white
    spinbox $f.month \
      -values "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" \
      -width 3 -wrap true -textvariable EndTextMonth \
      -command {TimeAdjusted End %W %s %d} -bg white
    spinbox $f.year -from 1900 -to 2100 -width 4 -wrap true \
      -textvariable EndYear \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white
    label $f.space -text " "
    spinbox $f.hour -from 0 -to 23 -width 2 -wrap true \
      -format %02.0f -textvariable EndHour \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white -bg white
    label $f.colon1 -text ":" -padx 0 -bd 0
    spinbox $f.minute -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable EndMinute \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white -bg white
    label $f.colon2 -text ":" -padx 0 -bd 0
    spinbox $f.second -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable EndSecond \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white -bg white

    bind $f.textday <Return> "TimeAdjustedManually"
    bind $f.day <Return> "TimeAdjustedManually"
    bind $f.month <Return> "TimeAdjustedManually"
    bind $f.year <Return> "TimeAdjustedManually"
    bind $f.hour <Return> "TimeAdjustedManually"
    bind $f.minute <Return> "TimeAdjustedManually"
    bind $f.second <Return> "TimeAdjustedManually"

    set EndTextDay [clock format $s -format %a]
    set EndDay [clock format $s -format %d]
    set EndTextMonth [clock format $s -format %b]
    set EndYear [clock format $s -format %Y]
    set EndHour 23
    set EndMinute 59
    set EndSecond 59

    set EndTime [clock scan "$EndTextDay $EndTextMonth $EndDay ${EndHour}:${EndMinute}:${EndSecond} $EndYear"]

    button $f.reset -text "Reset" -pady 0 -command "set EndTextDay $EndTextDay ; set EndDay $EndDay ; set EndTextMonth $EndTextMonth ; set EndYear $EndYear ; set EndHour $EndHour ; set EndMinute $EndMinute ; set EndSecond $EndSecond ; set EndTime $EndTime"

    pack $f.label $f.textday $f.day $f.month \
      $f.year $f.space $f.hour $f.colon1 \
      $f.minute $f.colon2 $f.second $f.reset -side left

    button $f.45min -text "last 45min" -pady 0 -command "TimePreset -minutes 45"
    pack $f.45min -side left
    button $f.60min -text "last 60min" -pady 0 -command "TimePreset -minutes 60"
    pack $f.60min -side left

}

proc TimePreset {args} {
    APSStrictParseArguments {minutes}
    foreach var "Start End" {
        global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
        global ${var}Hour ${var}Minute ${var}Second ${var}Time
    }
    set s [clock seconds]
    
    set EndTextDay [clock format $s -format %a]
    set EndDay [clock format $s -format %d]
    set EndTextMonth [clock format $s -format %b]
    set EndYear [clock format $s -format %Y]
    set EndHour 23
    set EndMinute 59
    set EndSecond 59
    set EndTime [clock scan "$EndTextDay $EndTextMonth $EndDay ${EndHour}:${EndMinute}:${EndSecond} $EndYear"]

    set s [expr $s - ($minutes * 60)]
    set StartTextDay [clock format $s -format %a]
    set StartDay [clock format $s -format %d]
    set StartTextMonth [clock format $s -format %b]
    set StartYear [clock format $s -format %Y]
    set StartHour [clock format $s -format %H]
    set StartMinute [clock format $s -format %M]
    set StartSecond [clock format $s -format %S]
    set StartTime [clock scan "$StartTextDay $StartTextMonth $StartDay ${StartHour}:${StartMinute}:${StartSecond} $StartYear"]


}

proc TimeAdjustedManually {args} {
    foreach var "Start End" {
        global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
        global ${var}Hour ${var}Minute ${var}Second ${var}Time
        
        set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]
        set ${var}Minute [clock format [set ${var}Time] -format %M]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    }
}

proc TimeAdjusted {var widget value direction} {
    global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
    global ${var}Hour ${var}Minute ${var}Second ${var}Time

    if {[lindex [split $widget .] end] == "second"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (1)"]
        set ${var}Second [clock format [set ${var}Time] -format %S]
        set ${var}Minute [clock format [set ${var}Time] -format %M]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "minute"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (60)"]
        set ${var}Minute [clock format [set ${var}Time] -format %M]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "hour"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (60 * 60)"]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "textday"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (24 * 60 * 60)"]
        set initTextDay [set ${var}TextDay]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        if {$initTextDay != [set ${var}TextDay]} {
            #This is needed for the transition to daylight savings time.
            set ${var}Time [expr "[set ${var}Time] $direction (1 * 60 * 60)"]
            set ${var}TextDay [clock format [set ${var}Time] -format %a]
        }
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "day"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (24 * 60 * 60)"]
        set initTextDay [set ${var}TextDay]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        if {$initTextDay == [set ${var}TextDay]} {
            #This is needed for the transition to daylight savings time.
            set ${var}Time [expr "[set ${var}Time] $direction (1 * 60 * 60)"]
            set ${var}TextDay [clock format [set ${var}Time] -format %a]
        }
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "month"} {
        set month [clock format [set ${var}Time] -format %b]
        set year [clock format [set ${var}Time] -format %Y]
        set s1 [clock scan "$month 01 00:00:00 $year"]
        if {$direction == "up"} {
            if {$month == "Dec"} {
                incr year
            }
        } else {
            if {$month == "Jan"} {
                incr year -1
            }
        }
        set s2 [clock scan "[set ${var}TextMonth] 01 00:00:00 $year"]
        set s [expr {$s2 - $s1 + (60 * 60)}]
        set ${var}Time [expr "[set ${var}Time] + $s"]
        while {[set ${var}TextMonth] != [clock format [set ${var}Time] -format %b]} {
            if {$month == [clock format [set ${var}Time] -format %b]} {
                if {$direction == "up"} {
                    set ${var}Time [expr "[set ${var}Time] + (12 * 60 * 60)"]
                } else {
                    set ${var}Time [expr "[set ${var}Time] - (12 * 60 * 60)"]
                }
            } else {
                if {$direction == "up"} {
                    set ${var}Time [expr "[set ${var}Time] - (12 * 60 * 60)"]
                } else {
                    set ${var}Time [expr "[set ${var}Time] + (12 * 60 * 60)"]
                }
            }
        }
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "year"} {
        if {([set ${var}Day] == "29") && ([set ${var}TextMonth] == "Feb")} {
            set ${var}Day 28
        }
        set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
    }
    set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]

}

proc CalcTime {} {
    foreach var "Start End" {
        global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
        global ${var}Hour ${var}Minute ${var}Second ${var}Time
        global dateEntryStyle ${var}Month
        if {$dateEntryStyle == "old"} {
            if [catch {APSConvertTimeToHours [set ${var}Hour]} hour] {
                APSSetVarAndUpdate status "Invalid ${var}ing hour: [set ${var}Hour]"
                return
            }
            set ${var}Time \
              [expr int([exec timeconvert \
                           -breakDown=year=[set ${var}Year],day=[set ${var}Day],month=[set ${var}Month],hour=$hour])]
        } else {
            set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]
        }
    }
}

proc LoadIDInfo {args} {
    global idInfo hn
    set hn 1
    if {[catch {exec sdds2stream /home/helios/oagData/sr/IDs/IDPeriodLength.sdds -col=ID,GapSetpointName,PeriodLength,Material,EnergyName} results]} {
        bell
        APSSetVarAndUpdate status "Error: $results"
        return
    }
    foreach "id gsn pl m phen" $results {
        lappend nl "$id (period = [format %2.1f ${pl}]mm, $m)"
        lappend idInfo "\"$id\" $gsn $pl $m $phen"
    }
    APSScrolledList .pVList -parent .userFrame -name "ID List" -itemList $nl -packOption "-fill both"
    APSLabeledEntry .harmonicNumber -parent .userFrame -label "Harmonic Number:" -packOption "-anchor w" -textVariable hn -type integer
}

proc CalcEnergy {args} {
    global StartTime EndTime idInfo hn
    if {$StartTime >= $EndTime} {
        bell
        APSSetVarAndUpdate status "The date/time range is invalid"
        return
    }
    APSSetVarAndUpdate status "Working..."

    set dcctfiles [APSFindPVDataFiles -ReadbackName S35DCCT -StartTime $StartTime -EndTime $EndTime -SampleIntervals 64]
    if {[llength $dcctfiles] == 0} {
        APSSetVarAndUpdate status "No files for S35DCCT in this date range"
        continue
    }
    set dcctFileName /tmp/[APSTmpString]
    APSAddToTempFileList $dcctFileName
    if {[catch {eval exec sddscombine $dcctfiles -pipe=out -merge | sddsprocess -pipe=in $dcctFileName \"-filter=column,S35DCCT,-9e99,10,!\"} results]} {
        bell
        APSSetVarAndUpdate status "$results"
        return
    }

    set selection [.userFrame.pVList.listbox curselection]
    foreach sel $selection {
        set id [lindex [lindex $idInfo $sel] 0]
        APSSetVarAndUpdate status $id
        set rbn [lindex [lindex $idInfo $sel] 1]
        set period [lindex [lindex $idInfo $sel] 2]
        set material [lindex [lindex $idInfo $sel] 3]
        set phen [lindex [lindex $idInfo $sel] 4]
        set files [APSFindPVDataFiles -ReadbackName $rbn -StartTime $StartTime -EndTime $EndTime -SampleIntervals 64]
        if {[llength $files] == 0} {
            APSSetVarAndUpdate status "No files for $rbn in this date range"
            continue
        }
        set fileName /tmp/[APSTmpString]
        APSAddToTempFileList $fileName $fileName.1 $fileName.2
        if {$material == "SmCo"} {
            if {[catch {eval exec sddscombine $files -pipe=out -merge | sddsprocess -pipe -filter=column,Time,${StartTime},${EndTime} \"-define=column,r,$rbn $period /\" \"-define=column,beff,-4.62 r * 1.37 r * r * + exp 2.94 *\" \"-define=column,k,$period beff * 10.709766549530093 /\" \"-define=column,PhotonEnergy,$hn 465378119.72227436 * .000001 * $period 1 k k * 2.0 / + * /\" \"-print=parameter,ID,$id\" \"-define=parameter,Period,$period,type=short\" | sddsprocess -pipe -delete=column,r,beff,k \"-filter=column,PhotonEnergy,-.001,.001,!\" | sddsxref -pipe $dcctFileName -equate=Time -take=S35DCCT -nowarn | sddsconvert -pipe -retain=column,Time,PhotonEnergy -retain=parameter,ID,Period | sddsprocess -pipe=in $fileName -filter=column,Time,0,1339256127.5} results]} {
                bell
                APSSetVarAndUpdate status "$results"
                return
            }
        } else {
            if {[catch {eval exec sddscombine $files -pipe=out -merge | sddsprocess -pipe -filter=column,Time,${StartTime},${EndTime} \"-define=column,r,$rbn $period /\" \"-define=column,beff,-4.51 r * 1.2 r * r * + exp 3.276 *\" \"-define=column,k,$period beff * 10.709766549530093 /\" \"-define=column,PhotonEnergy,$hn 465378119.72227436 * .000001 * $period 1 k k * 2.0 / + * /\" \"-print=parameter,ID,$id\" \"-define=parameter,Period,$period,type=short\" | sddsprocess -pipe -delete=column,r,beff,k \"-filter=column,PhotonEnergy,-.01,.01,!\" | sddsxref -pipe $dcctFileName -equate=Time -take=S35DCCT -nowarn | sddsconvert -pipe -retain=column,Time,PhotonEnergy -retain=parameter,ID,Period | sddsprocess -pipe=in $fileName -filter=column,Time,0,1339256127.5 -nowarn} results]} {
                bell
                APSSetVarAndUpdate status "$results"
                return
            }
        }
        #Note that we now have a photon energy PV starting at stardate 1339256128
        if {$EndTime > 1339256128} {
            set files [APSFindPVDataFiles -ReadbackName $phen -StartTime $StartTime -EndTime $EndTime -SampleIntervals 64]
            if {[llength $files] == 0} {
                APSSetVarAndUpdate status "No files for $phen in this date range"
                continue
            }
            if {[catch {eval exec sddscombine $files -pipe=out -merge | sddsprocess -pipe -filter=column,Time,${StartTime},${EndTime} \"-filter=column,$phen,-.001,.001,!\" | sddsconvert -pipe -rename=column,${phen}=PhotonEnergy -delete=column,CAerrors | sddsxref -pipe=in $dcctFileName $fileName.1 -equate=Time -take=S35DCCT -nowarn} results]} {
                bell
                APSSetVarAndUpdate status "$results"
                return
            }
            if {[catch {exec sddscombine $fileName $fileName.1 $fileName.2 -merge} results]} {
                bell
                APSSetVarAndUpdate status "$results"
                return
            }
            lappend fileList $fileName.2
        } else {
            lappend fileList $fileName
        }
    }
    set fileName /tmp/[APSTmpString]
    APSAddToTempFileList $fileName $fileName.1 $fileName.2
    if {[catch {eval exec sddscombine $fileList $fileName} results]} {
        bell
        APSSetVarAndUpdate status "$results"
        return
    }

    if {[catch {exec sddshist $fileName -pipe=out -dataColumn=PhotonEnergy -bins=50 | sddsprocess -pipe "-define=column,Hours,frequency 56.25 /" | sddsprocess -pipe=in $fileName.1 -delete=column,frequency} results]} {
        bell
        APSSetVarAndUpdate status "$results"
        return  
    }

    APSSetVarAndUpdate status "Plotting"
    exec sddsplot -sep=page -split=page -graph=dot,vary $fileName "-col=Time,(PhotonEnergy)" -tick=xtime "-ylabel=Photon Energy (keV)" -topline=@ID &
    exec sddsplot -axes=x -sep=page -split=page -graph=bar,thickness=2 "-column=PhotonEnergy,(Hours)" $fileName.1 "-xlabel=Photon Energy (keV)" "-ylabel=Hours" -topline=@ID &

    if {[catch {exec sddsconvert $fileName.1 -pipe=out -rename=parameter,sddshistBins=Bins,sddshistBinSize=BinSize -delete=parameter,sddshistInput,sddshistBinned,sddshistNormMode,Filename,NumberCombined | sddsprocess -pipe=in $fileName.2 -filter=column,Hours,1,99e99} results]} {
        bell
        APSSetVarAndUpdate status "$results"
        return  
    }
    if {[catch {exec sdds2spreadsheet $fileName.2 /tmp/IDEnergyHistory.xls -excel} results]} {
        bell
        APSSetVarAndUpdate status "$results"
        return  
    }
    APSSetVarAndUpdate status "Excel spreadsheet created at /tmp/IDEnergyHistory.xls"
    APSSetVarAndUpdate status "Only energies that lasted more than 1 hour were transfered to the spreadsheet."
    APSSetVarAndUpdate status "Done"


}

set idInfo ""

set sec [file mtime /home/helios/oagData/sr/IDs/IDPeriodLength.sdds]

set status "ID period lengths updated [clock format $sec]
The Harmonic Number is only used for date ranges 
prior to Sat Jun 09 10:35:27 CDT 2012.
The ID Energy PVs are used after that."
APSScrolledStatus .status \
  -parent .userFrame \
  -textVariable status \
  -packOption "-fill both -expand true" \
  -height 8

LoadIDInfo

MakeDateTimeFrame .userFrame.date

APSButton .calc -parent .userFrame -command CalcEnergy -text "Calculate Photon Energy"


