"""
Example 7

- run SPECTRA without GUI
- calculate the Wigner function (projected on Y-Y') for different photon energies
- import and analyze the output result to evaluate the light source performance
- the result of analysis is printed in console
- Note: this example does not run in the GUI or interactive mode
"""

import spectra 
import math

ONE_ANGSTROM_eV = 12398.4247

def GetSrcSpecs(ep, xy, data):
    wavel = ONE_ANGSTROM_eV/ep/1.0e+10
    Dxy = [0, 0]
    xymesh = [0, 0]
    for j in range(2):
        Dxy[j] = xy[j][1]-xy[j][0]
        xymesh[j] = len(xy[j])
    
    tf = normxy = size = div = 0
    for n1 in range(xymesh[1]):
        for n0 in range(xymesh[0]):
            index = n1*xymesh[0]+n0
            normxy += data[index]*data[index]*Dxy[0]*Dxy[1]
            tf += data[index]
            size += data[index]*xy[0][n0]*xy[0][n0]
            div += data[index]*xy[1][n1]*xy[1][n1]
    
    size = math.sqrt(size/tf)
    div = math.sqrt(div/tf)
    tf *= Dxy[0]*Dxy[1]

    normxy *= 1.0e+6 # (/mm/mrad) -> (/m/rad)
    cohdeg = wavel*normxy/tf/tf
    return [ep, tf, size, div, cohdeg]

# start without GUI (CLI mode)
spectra.Start(mode="c")

spectra.Open("sample.json") 
spectra.SelectBL("X-ray-BL")

# photon density in the vertical phase space (y,y') by Wigner function
spectra.SelectCalculation("srcpoint", "wigner", "phasespace", "YYpprj")

dataname = "sample7"
irange = range(-15, 5)
specs = []
for i in irange:
    detune = i*0.002
    spectra.Set("config", "detune", detune)
    energy = spectra.Get("config", "efix")
    spectra.StartCalculation(folder="./output", prefix=dataname, serial=-1)
    if i == irange[0]:
        axisvar = spectra.CLI.GetAxis(dataname)
        titles = spectra.CLI.GetTitle(dataname)
        units = spectra.CLI.GetUnit(dataname)
    data = spectra.CLI.GetData(dataname, 0)
    specs.append(GetSrcSpecs(energy, axisvar, data))

print("{0:11} {1:10} {2:10} {3:10} {4:10}".\
    format("Energy", "Flux", "Size", "Divergence", "Coherence"))
for spec in specs:
    print(f"{spec[0]:<11.4e} {spec[1]:<10.3e} {spec[2]:<10.3e} {spec[3]:<10.3e} {spec[4]:<10.3e}")

input("Completed. Press enter to exit. ")

# exit
spectra.Exit()
