def xoppy_calc_undulator_radiation(ELECTRONENERGY=6.04,ELECTRONENERGYSPREAD=0.001,ELECTRONCURRENT=0.2,\
                                       ELECTRONBEAMSIZEH=0.000395,ELECTRONBEAMSIZEV=9.9e-06,\
                                       ELECTRONBEAMDIVERGENCEH=1.05e-05,ELECTRONBEAMDIVERGENCEV=3.9e-06,\
                                       PERIODID=0.018,NPERIODS=222,KV=1.68,DISTANCE=30.0,
                                       SETRESONANCE=0,HARMONICNUMBER=1,
                                       GAPH=0.003,GAPV=0.003,\
                                       HSLITPOINTS=41,VSLITPOINTS=41,METHOD=2,
                                       PHOTONENERGYMIN=7982.2,PHOTONENERGYMAX=7983.2,PHOTONENERGYPOINTS=2,
                                       USEEMITTANCES=1,
                                       h5_file="",h5_entry_name="XOPPY_RADIATION",h5_initialize=True,h5_parameters={}):
    print("Inside xoppy_calc_undulator_radiation. ")

    bl = OrderedDict()
    bl['ElectronBeamDivergenceH'] = ELECTRONBEAMDIVERGENCEH
    bl['ElectronBeamDivergenceV'] = ELECTRONBEAMDIVERGENCEV
    bl['ElectronBeamSizeH'] = ELECTRONBEAMSIZEH
    bl['ElectronBeamSizeV'] = ELECTRONBEAMSIZEV
    bl['ElectronCurrent'] = ELECTRONCURRENT
    bl['ElectronEnergy'] = ELECTRONENERGY
    bl['ElectronEnergySpread'] = ELECTRONENERGYSPREAD
    bl['Kv'] = KV
    bl['NPeriods'] = NPERIODS
    bl['PeriodID'] = PERIODID
    bl['distance'] = DISTANCE
    bl['gapH'] = GAPH
    bl['gapV'] = GAPV

    if USEEMITTANCES:
        zero_emittance = False
    else:
        zero_emittance = True

    gamma = ELECTRONENERGY / (codata_mee * 1e-3)


    resonance_wavelength = (1 + bl['Kv']**2 / 2.0) / 2 / gamma**2 * bl["PeriodID"]
    m2ev = codata.c * codata.h / codata.e      # lambda(m)  = m2eV / energy(eV)
    resonance_energy = m2ev / resonance_wavelength

    resonance_central_cone = 1.0/gamma*numpy.sqrt( (1+0.5*KV**2)/(2*NPERIODS*HARMONICNUMBER) )

    ring_order = 1

    resonance_ring = 1.0/gamma*numpy.sqrt( ring_order / HARMONICNUMBER * (1+0.5*KV**2) )

    # autoset energy
    if SETRESONANCE == 0:
        photonEnergyMin = PHOTONENERGYMIN
        photonEnergyMax = PHOTONENERGYMAX
        photonEnergyPoints = PHOTONENERGYPOINTS
    else:
        # referred to resonance
        photonEnergyMin = resonance_energy
        photonEnergyMax = resonance_energy + 1
        photonEnergyPoints = 2

    # autoset slit

    if SETRESONANCE == 0:
        pass
    elif SETRESONANCE == 1:
        MAXANGLE = 3 * 0.69 * resonance_central_cone
        bl['gapH'] = 2 * MAXANGLE * DISTANCE
        bl['gapV'] = 2 * MAXANGLE * DISTANCE
    elif SETRESONANCE == 2:
        MAXANGLE = 2.1 * resonance_ring
        bl['gapH'] = 2 * MAXANGLE * DISTANCE
        bl['gapV'] = 2 * MAXANGLE * DISTANCE


    #TODO SPEC file can be removed
    outFile = "undulator_radiation.spec"

    # Memorandum:
    # e = array with energy in eV
    # h = array with horizontal positions in mm
    # v = array with vertical positions in mm
    # p = array with photon flux in photons/s/0.1%bw/mm^2 with shape (Ne,Nh.Nv)
    if METHOD == 0:
        code = "US"
        print("Undulator radiation calculation using US. Please wait...")
        e,h,v,p = srundplug.calc3d_us(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                    photonEnergyMin=photonEnergyMin,photonEnergyMax=photonEnergyMax,
                                    photonEnergyPoints=photonEnergyPoints,zero_emittance=zero_emittance)
    if METHOD == 1:
        code = "URGENT"
        print("Undulator radiation calculation using URGENT. Please wait...")
        e,h,v,p = srundplug.calc3d_urgent(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                    photonEnergyMin=photonEnergyMin,photonEnergyMax=photonEnergyMax,
                                    photonEnergyPoints=photonEnergyPoints,zero_emittance=zero_emittance)
    if METHOD == 2:
        code = "SRW"
        print("Undulator radiation calculation using SRW. Please wait...")
        e,h,v,p = srundplug.calc3d_srw(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                    photonEnergyMin=photonEnergyMin,photonEnergyMax=photonEnergyMax,
                                    photonEnergyPoints=photonEnergyPoints,zero_emittance=zero_emittance)
    if METHOD == 3:
        # todo too slow
        code = "pySRU"
        print("Undulator radiation calculation using SRW. Please wait...")
        e,h,v,p = srundplug.calc3d_pysru(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                    photonEnergyMin=photonEnergyMin,photonEnergyMax=photonEnergyMax,
                                    photonEnergyPoints=photonEnergyPoints,zero_emittance=zero_emittance)


    print ("Gamma: %f \n"%(gamma))
    print ("Resonance wavelength (1st harmonic): %g A\n"%(1e10*resonance_wavelength))
    print ("Resonance energy (1st harmonic): %g eV\n"%(resonance_energy))
    if HARMONICNUMBER != 1:
        print ("Resonance wavelength (%d harmonic): %g A\n"%(HARMONICNUMBER,1e10*resonance_wavelength/HARMONICNUMBER))
        print ("Resonance energy (%d harmonic): %g eV\n"%(HARMONICNUMBER,HARMONICNUMBER*resonance_energy))
    print ("Resonance central cone (%d harmonic): %g urad\n"%(HARMONICNUMBER,1e6*resonance_central_cone))


    print ("Resonance first ring (%d harmonic): %g urad\n"%(HARMONICNUMBER,1e6*resonance_ring))

    print("Calculated %d photon energy points from %f to %f."%(photonEnergyPoints,photonEnergyMin,photonEnergyMax))

    if zero_emittance:
        print("No emittance.")

    print("Done")

    ptot = (NPERIODS/6) * codata.value('characteristic impedance of vacuum') * \
           ELECTRONCURRENT * codata.e * 2 * numpy.pi * codata.c * gamma**2 * KV**2 / PERIODID
    print ("\nTotal power radiated by the undulator with fully opened slits [W]: %f \n"%(ptot))


    if SETRESONANCE == 0:
        pcalc =  p.sum() * codata.e * 1e3 * (h[1]-h[0]) * (v[1]-v[0]) * (e[1]-e[0])
        print ("\nTotal power from calculated spectrum (h,v,energy) grid [W]: %f \n"%pcalc)


    # fit
    try:
        print("============= Fitting power density to a 2D Gaussian. ==============\n")
        print("Please use these results with care: check if the original data looks like a Gaussian.\n")
        print("Length units are mm")
        data_to_fit = p.sum(axis=0)*(e[1]-e[0])*codata.e*1e3
        fit_parameters = fit_gaussian2d(data_to_fit,h,v)
        print(info_params(fit_parameters))
        H,V = numpy.meshgrid(h,v)
        data_fitted = twoD_Gaussian( (H,V), *fit_parameters)
        print("  Total power in the fitted data [W]: ",data_fitted.sum()*(h[1]-h[0])*(v[1]-v[0]))
        # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT")
        print("====================================================\n")

    except:
        pass

    if h5_file != "":
        try:
            if h5_initialize:
                h5w = H5SimpleWriter.initialize_file(h5_file,creator="xoppy_undulators.py")
            else:
                h5w = H5SimpleWriter(h5_file,None)
            h5w.create_entry(h5_entry_name,nx_default=None)
            h5w.add_stack(e,h,v,p,stack_name="Radiation",entry_name=h5_entry_name,
                title_0="Photon energy [eV]",
                title_1="X gap [mm]",
                title_2="Y gap [mm]")
            h5w.create_entry("parameters",root_entry=h5_entry_name,nx_default=None)
            for key in h5_parameters.keys():
                h5w.add_key(key,h5_parameters[key], entry_name=h5_entry_name+"/parameters")
            print("File written to disk: %s"%h5_file)
        except:
            print("ERROR initializing h5 file")

    return e, h, v, p, code
def xoppy_calc_undulator_power_density(ELECTRONENERGY=6.04,ELECTRONENERGYSPREAD=0.001,ELECTRONCURRENT=0.2,\
                                       ELECTRONBEAMSIZEH=0.000395,ELECTRONBEAMSIZEV=9.9e-06,\
                                       ELECTRONBEAMDIVERGENCEH=1.05e-05,ELECTRONBEAMDIVERGENCEV=3.9e-06,\
                                       PERIODID=0.018,NPERIODS=222,KV=1.68,DISTANCE=30.0,GAPH=0.001,GAPV=0.001,\
                                       HSLITPOINTS=101,VSLITPOINTS=51,METHOD=2,USEEMITTANCES=1,
                                       MASK_FLAG=0,
                                       MASK_ROT_H_DEG=0.0,MASK_ROT_V_DEG=0.0,
                                       MASK_H_MIN=None,MASK_H_MAX=None,
                                       MASK_V_MIN=None,MASK_V_MAX=None,
                                       h5_file="",h5_entry_name="XOPPY_POWERDENSITY",h5_initialize=True,h5_parameters={},
                                       ):
    print("Inside xoppy_calc_undulator_power_density. ")

    bl = OrderedDict()
    bl['ElectronBeamDivergenceH'] = ELECTRONBEAMDIVERGENCEH
    bl['ElectronBeamDivergenceV'] = ELECTRONBEAMDIVERGENCEV
    bl['ElectronBeamSizeH'] = ELECTRONBEAMSIZEH
    bl['ElectronBeamSizeV'] = ELECTRONBEAMSIZEV
    bl['ElectronCurrent'] = ELECTRONCURRENT
    bl['ElectronEnergy'] = ELECTRONENERGY
    bl['ElectronEnergySpread'] = ELECTRONENERGYSPREAD
    bl['Kv'] = KV
    bl['NPeriods'] = NPERIODS
    bl['PeriodID'] = PERIODID
    bl['distance'] = DISTANCE
    bl['gapH'] = GAPH
    bl['gapV'] = GAPV

    if USEEMITTANCES:
        zero_emittance = False
    else:
        zero_emittance = True

    #TODO remove SPEC file
    outFile = "undulator_power_density.spec"

    if METHOD == 0:
        code = "US"
        print("Undulator power_density calculation using US. Please wait...")
        h,v,p = srundplug.calc2d_us(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                    zero_emittance=zero_emittance)
        print("Done")
    if METHOD == 1:
        code = "URGENT"
        print("Undulator power_density calculation using URGENT. Please wait...")
        h,v,p = srundplug.calc2d_urgent(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                        zero_emittance=zero_emittance)
        print("Done")
    if METHOD == 2:
        code = "SRW"
        print("Undulator power_density calculation using SRW. Please wait...")
        h,v,p = srundplug.calc2d_srw(bl,fileName=outFile,fileAppend=False,hSlitPoints=HSLITPOINTS,vSlitPoints=VSLITPOINTS,
                                     zero_emittance=zero_emittance)
        print("Done")


    if zero_emittance:
        print("No emittance calculation")
    codata_mee = codata.m_e * codata.c**2 / codata.e # electron mass in eV
    gamma = ELECTRONENERGY * 1e9 / codata_mee
    ptot = (NPERIODS/6) * codata.value('characteristic impedance of vacuum') * \
           ELECTRONCURRENT * codata.e * 2 * numpy.pi * codata.c * gamma**2 * KV**2 / PERIODID
    print ("\nTotal power radiated by the undulator with fully opened slits [W]: %g \n"%(ptot))


    if MASK_FLAG:
        #
        # rotation
        #
        v /= numpy.cos(MASK_ROT_H_DEG * numpy.pi / 180)
        h /= numpy.cos(MASK_ROT_V_DEG * numpy.pi / 180)
        # also reduce the power density!!
        p *= numpy.cos(MASK_ROT_H_DEG * numpy.pi / 180)
        p *= numpy.cos(MASK_ROT_V_DEG * numpy.pi / 180)

        #
        # mask
        #
        if MASK_H_MIN is not None:
            lower_window_h = numpy.where(h < MASK_H_MIN)
            if len(lower_window_h) > 0: p[lower_window_h,:] = 0

        if MASK_H_MAX is not None:
            upper_window_h = numpy.where(h > MASK_H_MAX)
            if len(upper_window_h) > 0: p[upper_window_h,:] = 0

        if MASK_V_MIN is not None:
            lower_window_v = numpy.where(v < MASK_V_MIN)
            if len(lower_window_v) > 0: p[:,lower_window_v] = 0

        if MASK_V_MIN is not None:
            upper_window_v = numpy.where(v > MASK_V_MAX)
            if len(upper_window_v) > 0: p[:,upper_window_v] = 0

        txt0 = "============= power density in the modified (masked) screen ==========\n"
    else:
        txt0 = "=================== power density  ======================\n"

    text_info = txt0
    text_info += "  Power density peak: %f W/mm2\n"%p.max()
    text_info += "  Total power: %f W\n"%(p.sum()*(h[1]-h[0])*(v[1]-v[0]))
    text_info += "====================================================\n"
    print(text_info)

    # fit
    fit_ok = False
    try:
        print("============= Fitting power density to a 2D Gaussian. ==============\n")
        print("Please use these results with care: check if the original data looks like a Gaussian.")
        fit_parameters = fit_gaussian2d(p,h,v)
        print(info_params(fit_parameters))
        H,V = numpy.meshgrid(h,v)
        data_fitted = twoD_Gaussian( (H,V), *fit_parameters)
        print("  Total power in the fitted data [W]: ",data_fitted.sum()*(h[1]-h[0])*(v[1]-v[0]))
        # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT")
        print("====================================================\n")
        fit_ok = True
    except:
        pass

    if h5_file != "":
        try:
            if h5_initialize:
                h5w = H5SimpleWriter.initialize_file(h5_file,creator="xoppy_undulators.py")
            else:
                h5w = H5SimpleWriter(h5_file,None)
            h5w.create_entry(h5_entry_name,nx_default="PowerDensity")
            h5w.add_image(p,h,v,image_name="PowerDensity",entry_name=h5_entry_name,title_x="X [mm]",title_y="Y [mm]")
            h5w.add_key("info",text_info, entry_name=h5_entry_name)
            h5w.create_entry("parameters",root_entry=h5_entry_name,nx_default=None)
            for key in h5_parameters.keys():
                h5w.add_key(key,h5_parameters[key], entry_name=h5_entry_name+"/parameters")
            if fit_ok:
                h5w.add_image(data_fitted.reshape(h.size,v.size),h,v,image_name="PowerDensityFit",entry_name=h5_entry_name,title_x="X [mm]",title_y="Y [mm]")
                h5w.add_key("fit_info",info_params(fit_parameters), entry_name=h5_entry_name+"/PowerDensityFit")

            print("File written to disk: %s"%h5_file)
        except:
            print("ERROR initializing h5 file")

    return h, v, p, code
def xoppy_calc_undulator_radiation(ELECTRONENERGY=6.04,ELECTRONENERGYSPREAD=0.001,ELECTRONCURRENT=0.2,\
                                       ELECTRONBEAMSIZEH=0.000395,ELECTRONBEAMSIZEV=9.9e-06,\
                                       ELECTRONBEAMDIVERGENCEH=1.05e-05,ELECTRONBEAMDIVERGENCEV=3.9e-06,\
                                       PERIODID=0.018,NPERIODS=222,KV=1.68,DISTANCE=30.0,
                                       SETRESONANCE=0,HARMONICNUMBER=1,
                                       GAPH=0.003,GAPV=0.003,\
                                       HSLITPOINTS=41,VSLITPOINTS=41,METHOD=2,
                                       PHOTONENERGYMIN=7982.2,PHOTONENERGYMAX=7983.2,PHOTONENERGYPOINTS=2,
                                       USEEMITTANCES=1,
                                       h5_file="",h5_entry_name="XOPPY_RADIATION",h5_initialize=True,h5_parameters={}):
    print("Inside xoppy_calc_undulator_radiation. ")

    bl = OrderedDict()
    bl['ElectronBeamDivergenceH'] = ELECTRONBEAMDIVERGENCEH
    bl['ElectronBeamDivergenceV'] = ELECTRONBEAMDIVERGENCEV
    bl['ElectronBeamSizeH'] = ELECTRONBEAMSIZEH
    bl['ElectronBeamSizeV'] = ELECTRONBEAMSIZEV
    bl['ElectronCurrent'] = ELECTRONCURRENT
    bl['ElectronEnergy'] = ELECTRONENERGY
    bl['ElectronEnergySpread'] = ELECTRONENERGYSPREAD
    bl['Kv'] = KV
    bl['NPeriods'] = NPERIODS
    bl['PeriodID'] = PERIODID
    bl['distance'] = DISTANCE
    bl['gapH'] = GAPH
    bl['gapV'] = GAPV

    if USEEMITTANCES:
        zero_emittance = False
    else:
        zero_emittance = True

    gamma = ELECTRONENERGY / (codata_mee * 1e-3)

    resonance_wavelength = (1 +
                            bl['Kv']**2 / 2.0) / 2 / gamma**2 * bl["PeriodID"]
    m2ev = codata.c * codata.h / codata.e  # lambda(m)  = m2eV / energy(eV)
    resonance_energy = m2ev / resonance_wavelength

    resonance_central_cone = 1.0 / gamma * numpy.sqrt(
        (1 + 0.5 * KV**2) / (2 * NPERIODS * HARMONICNUMBER))

    ring_order = 1

    resonance_ring = 1.0 / gamma * numpy.sqrt(ring_order / HARMONICNUMBER *
                                              (1 + 0.5 * KV**2))

    # autoset energy
    if SETRESONANCE == 0:
        photonEnergyMin = PHOTONENERGYMIN
        photonEnergyMax = PHOTONENERGYMAX
        photonEnergyPoints = PHOTONENERGYPOINTS
    else:
        # referred to resonance
        photonEnergyMin = resonance_energy
        photonEnergyMax = resonance_energy + 1
        photonEnergyPoints = 2

    # autoset slit

    if SETRESONANCE == 0:
        pass
    elif SETRESONANCE == 1:
        MAXANGLE = 3 * 0.69 * resonance_central_cone
        bl['gapH'] = 2 * MAXANGLE * DISTANCE
        bl['gapV'] = 2 * MAXANGLE * DISTANCE
    elif SETRESONANCE == 2:
        MAXANGLE = 2.1 * resonance_ring
        bl['gapH'] = 2 * MAXANGLE * DISTANCE
        bl['gapV'] = 2 * MAXANGLE * DISTANCE

    #TODO SPEC file can be removed
    outFile = "undulator_radiation.spec"

    # Memorandum:
    # e = array with energy in eV
    # h = array with horizontal positions in mm
    # v = array with vertical positions in mm
    # p = array with photon flux in photons/s/0.1%bw/mm^2 with shape (Ne,Nh.Nv)
    if METHOD == 0:
        code = "US"
        print("Undulator radiation calculation using US. Please wait...")
        e, h, v, p = srundplug.calc3d_us(bl,
                                         fileName=outFile,
                                         fileAppend=False,
                                         hSlitPoints=HSLITPOINTS,
                                         vSlitPoints=VSLITPOINTS,
                                         photonEnergyMin=photonEnergyMin,
                                         photonEnergyMax=photonEnergyMax,
                                         photonEnergyPoints=photonEnergyPoints,
                                         zero_emittance=zero_emittance)
    if METHOD == 1:
        code = "URGENT"
        print("Undulator radiation calculation using URGENT. Please wait...")
        e, h, v, p = srundplug.calc3d_urgent(
            bl,
            fileName=outFile,
            fileAppend=False,
            hSlitPoints=HSLITPOINTS,
            vSlitPoints=VSLITPOINTS,
            photonEnergyMin=photonEnergyMin,
            photonEnergyMax=photonEnergyMax,
            photonEnergyPoints=photonEnergyPoints,
            zero_emittance=zero_emittance)
    if METHOD == 2:
        code = "SRW"
        print("Undulator radiation calculation using SRW. Please wait...")
        e, h, v, p = srundplug.calc3d_srw(
            bl,
            fileName=outFile,
            fileAppend=False,
            hSlitPoints=HSLITPOINTS,
            vSlitPoints=VSLITPOINTS,
            photonEnergyMin=photonEnergyMin,
            photonEnergyMax=photonEnergyMax,
            photonEnergyPoints=photonEnergyPoints,
            zero_emittance=zero_emittance)
    if METHOD == 3:
        # todo too slow
        code = "pySRU"
        print("Undulator radiation calculation using SRW. Please wait...")
        e, h, v, p = srundplug.calc3d_pysru(
            bl,
            fileName=outFile,
            fileAppend=False,
            hSlitPoints=HSLITPOINTS,
            vSlitPoints=VSLITPOINTS,
            photonEnergyMin=photonEnergyMin,
            photonEnergyMax=photonEnergyMax,
            photonEnergyPoints=photonEnergyPoints,
            zero_emittance=zero_emittance)

    print("Gamma: %f \n" % (gamma))
    print("Resonance wavelength (1st harmonic): %g A\n" %
          (1e10 * resonance_wavelength))
    print("Resonance energy (1st harmonic): %g eV\n" % (resonance_energy))
    if HARMONICNUMBER != 1:
        print("Resonance wavelength (%d harmonic): %g A\n" %
              (HARMONICNUMBER, 1e10 * resonance_wavelength / HARMONICNUMBER))
        print("Resonance energy (%d harmonic): %g eV\n" %
              (HARMONICNUMBER, HARMONICNUMBER * resonance_energy))
    print("Resonance central cone (%d harmonic): %g urad\n" %
          (HARMONICNUMBER, 1e6 * resonance_central_cone))

    print("Resonance first ring (%d harmonic): %g urad\n" %
          (HARMONICNUMBER, 1e6 * resonance_ring))

    print("Calculated %d photon energy points from %f to %f." %
          (photonEnergyPoints, photonEnergyMin, photonEnergyMax))

    if zero_emittance:
        print("No emittance.")

    print("Done")

    ptot = (NPERIODS/6) * codata.value('characteristic impedance of vacuum') * \
           ELECTRONCURRENT * codata.e * 2 * numpy.pi * codata.c * gamma**2 * KV**2 / PERIODID
    print(
        "\nTotal power radiated by the undulator with fully opened slits [W]: %f \n"
        % (ptot))

    if SETRESONANCE == 0:
        pcalc = p.sum() * codata.e * 1e3 * (h[1] - h[0]) * (v[1] - v[0]) * (
            e[1] - e[0])
        print(
            "\nTotal power from calculated spectrum (h,v,energy) grid [W]: %f \n"
            % pcalc)

    # fit
    try:
        print(
            "============= Fitting power density to a 2D Gaussian. ==============\n"
        )
        print(
            "Please use these results with care: check if the original data looks like a Gaussian.\n"
        )
        print("Length units are mm")
        data_to_fit = p.sum(axis=0) * (e[1] - e[0]) * codata.e * 1e3
        fit_parameters = fit_gaussian2d(data_to_fit, h, v)
        print(info_params(fit_parameters))
        H, V = numpy.meshgrid(h, v)
        data_fitted = twoD_Gaussian((H, V), *fit_parameters)
        print("  Total power in the fitted data [W]: ",
              data_fitted.sum() * (h[1] - h[0]) * (v[1] - v[0]))
        # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT")
        print("====================================================\n")

    except:
        pass

    if h5_file != "":
        try:
            if h5_initialize:
                h5w = H5SimpleWriter.initialize_file(
                    h5_file, creator="xoppy_undulators.py")
            else:
                h5w = H5SimpleWriter(h5_file, None)
            h5w.create_entry(h5_entry_name, nx_default=None)
            h5w.add_stack(e,
                          h,
                          v,
                          p,
                          stack_name="Radiation",
                          entry_name=h5_entry_name,
                          title_0="Photon energy [eV]",
                          title_1="X gap [mm]",
                          title_2="Y gap [mm]")
            h5w.create_entry("parameters",
                             root_entry=h5_entry_name,
                             nx_default=None)
            for key in h5_parameters.keys():
                h5w.add_key(key,
                            h5_parameters[key],
                            entry_name=h5_entry_name + "/parameters")
            print("File written to disk: %s" % h5_file)
        except:
            print("ERROR initializing h5 file")

    return e, h, v, p, code
Exemple #4
0
def xoppy_calc_wiggler_radiation(
    ELECTRONENERGY=3.0,
    ELECTRONCURRENT=0.1,
    PERIODID=0.120,
    NPERIODS=37.0,
    KV=22.416,
    DISTANCE=30.0,
    HSLITPOINTS=500,
    VSLITPOINTS=500,
    PHOTONENERGYMIN=100.0,
    PHOTONENERGYMAX=100100.0,
    PHOTONENERGYPOINTS=101,
    NTRAJPOINTS=1001,
    FIELD=0,
    FILE="/Users/srio/Oasys/Bsin.txt",
    POLARIZATION=0,  # 0=total, 1=parallel (s), 2=perpendicular (p)
    SHIFT_X_FLAG=0,
    SHIFT_X_VALUE=0.0,
    SHIFT_BETAX_FLAG=0,
    SHIFT_BETAX_VALUE=0.0,
    CONVOLUTION=1,
    PASSEPARTOUT=3.0,
    h5_file="wiggler_radiation.h5",
    h5_entry_name="XOPPY_RADIATION",
    h5_initialize=True,
    h5_parameters=None,
    do_plot=False,
):

    # calculate wiggler trajectory
    if FIELD == 0:
        (traj, pars) = srfunc.wiggler_trajectory(
            b_from=0,
            inData="",
            nPer=int(NPERIODS),  #37,
            nTrajPoints=NTRAJPOINTS,
            ener_gev=ELECTRONENERGY,
            per=PERIODID,
            kValue=KV,
            trajFile="",
            shift_x_flag=SHIFT_X_FLAG,
            shift_x_value=SHIFT_X_VALUE,
            shift_betax_flag=SHIFT_BETAX_FLAG,
            shift_betax_value=SHIFT_BETAX_VALUE)
    if FIELD == 1:
        # magnetic field from B(s) map
        (traj,
         pars) = srfunc.wiggler_trajectory(b_from=1,
                                           nPer=1,
                                           nTrajPoints=NTRAJPOINTS,
                                           ener_gev=ELECTRONENERGY,
                                           inData=FILE,
                                           trajFile="",
                                           shift_x_flag=SHIFT_X_FLAG,
                                           shift_x_value=SHIFT_X_VALUE,
                                           shift_betax_flag=SHIFT_BETAX_FLAG,
                                           shift_betax_value=SHIFT_BETAX_FLAG)
    if FIELD == 2:
        raise ("Not implemented")

    energy, flux, power = srfunc.wiggler_spectrum(
        traj,
        enerMin=PHOTONENERGYMIN,
        enerMax=PHOTONENERGYMAX,
        nPoints=PHOTONENERGYPOINTS,
        electronCurrent=ELECTRONCURRENT,
        outFile="",
        elliptical=False,
        polarization=POLARIZATION)

    try:
        cumulated_power = power.cumsum() * numpy.abs(energy[0] - energy[1])
    except:
        cumulated_power = 0.0
    print("\nPower from integral of spectrum (sum rule): %8.3f W" %
          (cumulated_power[-1]))

    try:
        cumulated_power = cumtrapz(power, energy, initial=0)
    except:
        cumulated_power = 0.0
    print("Power from integral of spectrum (trapezoid rule): %8.3f W" %
          (cumulated_power[-1]))

    codata_mee = 1e-6 * codata.m_e * codata.c**2 / codata.e  # electron mass in meV
    gamma = ELECTRONENERGY * 1e3 / codata_mee

    Y = traj[1, :].copy()
    divX = traj[3, :].copy()
    By = traj[7, :].copy()

    # rho = (1e9 / codata.c) * ELECTRONENERGY / By
    # Ec0 = 3 * codata.h * codata.c * gamma**3 / (4 * numpy.pi * rho) / codata.e
    # Ec = 665.0 * ELECTRONENERGY**2 * numpy.abs(By)
    # Ecmax = 665.0 * ELECTRONENERGY** 2 * (numpy.abs(By)).max()
    coeff = 3 / (
        4 *
        numpy.pi) * codata.h * codata.c**2 / codata_mee**3 / codata.e  # ~665.0
    Ec = coeff * ELECTRONENERGY**2 * numpy.abs(By)
    Ecmax = coeff * ELECTRONENERGY**2 * (numpy.abs(By)).max()

    # approx formula for divergence (first formula in pag 43 of Tanaka's paper)
    sigmaBp = 0.597 / gamma * numpy.sqrt(Ecmax / PHOTONENERGYMIN)

    # we use vertical interval 6*sigmaBp and horizontal interval = vertical + trajectory interval

    divXX = numpy.linspace(divX.min() - PASSEPARTOUT * sigmaBp,
                           divX.max() + PASSEPARTOUT * sigmaBp, HSLITPOINTS)

    divZZ = numpy.linspace(-PASSEPARTOUT * sigmaBp, PASSEPARTOUT * sigmaBp,
                           VSLITPOINTS)

    e = numpy.linspace(PHOTONENERGYMIN, PHOTONENERGYMAX, PHOTONENERGYPOINTS)

    p = numpy.zeros((PHOTONENERGYPOINTS, HSLITPOINTS, VSLITPOINTS))

    for i in range(e.size):
        Ephoton = e[i]

        # vertical divergence
        intensity = srfunc.sync_g1(Ephoton / Ec, polarization=POLARIZATION)

        Ecmean = (Ec * intensity).sum() / intensity.sum()

        fluxDivZZ = srfunc.sync_ang(1,
                                    divZZ * 1e3,
                                    polarization=POLARIZATION,
                                    e_gev=ELECTRONENERGY,
                                    i_a=ELECTRONCURRENT,
                                    hdiv_mrad=1.0,
                                    energy=Ephoton,
                                    ec_ev=Ecmean)

        if do_plot:
            from srxraylib.plot.gol import plot
            plot(divZZ,
                 fluxDivZZ,
                 title="min intensity %f" % fluxDivZZ.min(),
                 xtitle="divZ",
                 ytitle="fluxDivZZ",
                 show=1)

        # horizontal divergence after Tanaka
        if False:
            e_over_ec = Ephoton / Ecmax
            uudlim = 1.0 / gamma
            uud = numpy.linspace(-uudlim * 0.99, uudlim * 0.99, divX.size)
            uu = e_over_ec / numpy.sqrt(1 - gamma**2 * uud**2)
            plot(uud, 2 * numpy.pi / numpy.sqrt(3) * srfunc.sync_g1(uu))

        # horizontal divergence
        # intensity = srfunc.sync_g1(Ephoton / Ec, polarization=POLARIZATION)
        intensity_interpolated = interpolate_multivalued_function(
            divX,
            intensity,
            divXX,
            Y,
        )

        if CONVOLUTION:  # do always convolution!
            intensity_interpolated.shape = -1
            divXX_window = divXX[-1] - divXX[0]
            divXXCC = numpy.linspace(-0.5 * divXX_window, 0.5 * divXX_window,
                                     divXX.size)
            fluxDivZZCC = srfunc.sync_ang(1,
                                          divXXCC * 1e3,
                                          polarization=POLARIZATION,
                                          e_gev=ELECTRONENERGY,
                                          i_a=ELECTRONCURRENT,
                                          hdiv_mrad=1.0,
                                          energy=Ephoton,
                                          ec_ev=Ecmax)
            fluxDivZZCC.shape = -1

            intensity_convolved = numpy.convolve(
                intensity_interpolated / intensity_interpolated.max(),
                fluxDivZZCC / fluxDivZZCC.max(),
                mode='same')
        else:
            intensity_convolved = intensity_interpolated

        if i == 0:
            print(
                "\n\n============ sizes vs photon energy ======================="
            )
            print(
                "Photon energy/eV  FWHM X'/urad  FWHM Y'/urad  FWHM X/mm  FWHM Z/mm "
            )

        print("%16.3f  %12.3f  %12.3f  %9.2f  %9.2f" %
              (Ephoton, 1e6 * get_fwhm(intensity_convolved, divXX)[0],
               1e6 * get_fwhm(fluxDivZZ, divZZ)[0],
               1e3 * get_fwhm(intensity_convolved, divXX)[0] * DISTANCE,
               1e3 * get_fwhm(fluxDivZZ, divZZ)[0] * DISTANCE))

        if do_plot:
            plot(divX,
                 intensity / intensity.max(),
                 divXX,
                 intensity_interpolated / intensity_interpolated.max(),
                 divXX,
                 intensity_convolved / intensity_convolved.max(),
                 divXX,
                 fluxDivZZCC / fluxDivZZCC.max(),
                 title="min intensity %f, Ephoton=%6.2f" %
                 (intensity.min(), Ephoton),
                 xtitle="divX",
                 ytitle="intensity",
                 legend=["orig", "interpolated", "convolved", "kernel"],
                 show=1)

        # combine H * V
        INTENSITY = numpy.outer(
            intensity_convolved / intensity_convolved.max(),
            fluxDivZZ / fluxDivZZ.max())
        p[i, :, :] = INTENSITY

        if do_plot:
            from srxraylib.plot.gol import plot_image, plot_surface, plot_show
            plot_image(INTENSITY,
                       divXX,
                       divZZ,
                       aspect='auto',
                       title="E=%6.2f" % Ephoton,
                       show=1)
            # to create oasys icon...
            # plot_surface(INTENSITY, divXX, divZZ, title="", show=0)
            # import matplotlib.pylab as plt
            # plt.xticks([])
            # plt.yticks([])
            # plt.axis('off')
            # plt.tick_params(axis='both', left='off', top='off', right='off', bottom='off', labelleft='off',
            #                 labeltop='off', labelright='off', labelbottom='off')
            #
            # plot_show()
    #

    h = divXX * DISTANCE * 1e3  # in mm for the h5 file
    v = divZZ * DISTANCE * 1e3  # in mm for the h5 file

    print("\nWindow size: %f mm [H] x %f mm [V]" %
          (h[-1] - h[0], v[-1] - v[0]))
    print("Window size: %g rad [H] x %g rad [V]" %
          (divXX[-1] - divXX[0], divZZ[-1] - divZZ[0]))

    # normalization and total flux
    for i in range(e.size):
        INTENSITY = p[i, :, :]
        # norm = INTENSITY.sum() * (h[1] - h[0]) * (v[1] - v[0])
        norm = trapezoidal_rule_2d_1darrays(INTENSITY, h, v)
        p[i, :, :] = INTENSITY / norm * flux[i]

    # fit
    fit_ok = False
    try:
        power = p.sum(axis=0) * (e[1] - e[0]) * codata.e * 1e3
        print(
            "\n\n============= Fitting power density to a 2D Gaussian. ==============\n"
        )
        print(
            "Please use these results with care: check if the original data looks like a Gaussian."
        )
        fit_parameters = fit_gaussian2d(power, h, v)
        print(info_params(fit_parameters))
        H, V = numpy.meshgrid(h, v)
        data_fitted = twoD_Gaussian((H, V), *fit_parameters)
        print("  Total power (sum rule) in the fitted data [W]: ",
              data_fitted.sum() * (h[1] - h[0]) * (v[1] - v[0]))
        # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT")
        print("====================================================\n")
        fit_ok = True
    except:
        pass

    # output file
    if h5_file != "":
        try:
            if h5_initialize:
                h5w = H5SimpleWriter.initialize_file(
                    h5_file, creator="xoppy_wigglers.py")
            else:
                h5w = H5SimpleWriter(h5_file, None)
            h5w.create_entry(h5_entry_name, nx_default=None)
            h5w.add_stack(e,
                          h,
                          v,
                          p,
                          stack_name="Radiation",
                          entry_name=h5_entry_name,
                          title_0="Photon energy [eV]",
                          title_1="X gap [mm]",
                          title_2="Y gap [mm]")
            h5w.create_entry("parameters",
                             root_entry=h5_entry_name,
                             nx_default=None)
            if h5_parameters is not None:
                for key in h5_parameters.keys():
                    h5w.add_key(key,
                                h5_parameters[key],
                                entry_name=h5_entry_name + "/parameters")
            h5w.create_entry("trajectory",
                             root_entry=h5_entry_name,
                             nx_default="transversal trajectory")
            h5w.add_key("traj", traj, entry_name=h5_entry_name + "/trajectory")
            h5w.add_dataset(traj[1, :],
                            traj[0, :],
                            dataset_name="transversal trajectory",
                            entry_name=h5_entry_name + "/trajectory",
                            title_x="s [m]",
                            title_y="X [m]")
            h5w.add_dataset(traj[1, :],
                            traj[3, :],
                            dataset_name="transversal velocity",
                            entry_name=h5_entry_name + "/trajectory",
                            title_x="s [m]",
                            title_y="Vx/c")
            h5w.add_dataset(traj[1, :],
                            traj[7, :],
                            dataset_name="Magnetic field",
                            entry_name=h5_entry_name + "/trajectory",
                            title_x="s [m]",
                            title_y="Bz [T]")
            if fit_ok:
                h5w.add_image(power,
                              h,
                              v,
                              image_name="PowerDensity",
                              entry_name=h5_entry_name,
                              title_x="X [mm]",
                              title_y="Y [mm]")

                h5w.add_image(data_fitted.reshape(h.size, v.size),
                              h,
                              v,
                              image_name="PowerDensityFit",
                              entry_name=h5_entry_name,
                              title_x="X [mm]",
                              title_y="Y [mm]")
                h5w.add_key("fit_info",
                            info_params(fit_parameters),
                            entry_name=h5_entry_name + "/PowerDensityFit")
            print("File written to disk: %s" % h5_file)
        except:
            print("ERROR initializing h5 file")

    return e, h, v, p, traj
def xoppy_calc_undulator_power_density(ELECTRONENERGY=6.04,ELECTRONENERGYSPREAD=0.001,ELECTRONCURRENT=0.2,\
                                       ELECTRONBEAMSIZEH=0.000395,ELECTRONBEAMSIZEV=9.9e-06,\
                                       ELECTRONBEAMDIVERGENCEH=1.05e-05,ELECTRONBEAMDIVERGENCEV=3.9e-06,\
                                       PERIODID=0.018,NPERIODS=222,KV=1.68,DISTANCE=30.0,GAPH=0.001,GAPV=0.001,\
                                       HSLITPOINTS=101,VSLITPOINTS=51,METHOD=2,USEEMITTANCES=1,
                                       MASK_FLAG=0,
                                       MASK_ROT_H_DEG=0.0,MASK_ROT_V_DEG=0.0,
                                       MASK_H_MIN=None,MASK_H_MAX=None,
                                       MASK_V_MIN=None,MASK_V_MAX=None,
                                       h5_file="",h5_entry_name="XOPPY_POWERDENSITY",h5_initialize=True,h5_parameters={},
                                       ):
    print("Inside xoppy_calc_undulator_power_density. ")

    bl = OrderedDict()
    bl['ElectronBeamDivergenceH'] = ELECTRONBEAMDIVERGENCEH
    bl['ElectronBeamDivergenceV'] = ELECTRONBEAMDIVERGENCEV
    bl['ElectronBeamSizeH'] = ELECTRONBEAMSIZEH
    bl['ElectronBeamSizeV'] = ELECTRONBEAMSIZEV
    bl['ElectronCurrent'] = ELECTRONCURRENT
    bl['ElectronEnergy'] = ELECTRONENERGY
    bl['ElectronEnergySpread'] = ELECTRONENERGYSPREAD
    bl['Kv'] = KV
    bl['NPeriods'] = NPERIODS
    bl['PeriodID'] = PERIODID
    bl['distance'] = DISTANCE
    bl['gapH'] = GAPH
    bl['gapV'] = GAPV

    if USEEMITTANCES:
        zero_emittance = False
    else:
        zero_emittance = True

    #TODO remove SPEC file
    outFile = "undulator_power_density.spec"

    if METHOD == 0:
        code = "US"
        print("Undulator power_density calculation using US. Please wait...")
        h, v, p = srundplug.calc2d_us(bl,
                                      fileName=outFile,
                                      fileAppend=False,
                                      hSlitPoints=HSLITPOINTS,
                                      vSlitPoints=VSLITPOINTS,
                                      zero_emittance=zero_emittance)
        print("Done")
    if METHOD == 1:
        code = "URGENT"
        print(
            "Undulator power_density calculation using URGENT. Please wait...")
        h, v, p = srundplug.calc2d_urgent(bl,
                                          fileName=outFile,
                                          fileAppend=False,
                                          hSlitPoints=HSLITPOINTS,
                                          vSlitPoints=VSLITPOINTS,
                                          zero_emittance=zero_emittance)
        print("Done")
    if METHOD == 2:
        code = "SRW"
        print("Undulator power_density calculation using SRW. Please wait...")
        h, v, p = srundplug.calc2d_srw(bl,
                                       fileName=outFile,
                                       fileAppend=False,
                                       hSlitPoints=HSLITPOINTS,
                                       vSlitPoints=VSLITPOINTS,
                                       zero_emittance=zero_emittance)
        print("Done")

    if zero_emittance:
        print("No emittance calculation")
    codata_mee = codata.m_e * codata.c**2 / codata.e  # electron mass in eV
    gamma = ELECTRONENERGY * 1e9 / codata_mee
    ptot = (NPERIODS/6) * codata.value('characteristic impedance of vacuum') * \
           ELECTRONCURRENT * codata.e * 2 * numpy.pi * codata.c * gamma**2 * KV**2 / PERIODID
    print(
        "\nTotal power radiated by the undulator with fully opened slits [W]: %g \n"
        % (ptot))

    if MASK_FLAG:
        #
        # rotation
        #
        v /= numpy.cos(MASK_ROT_H_DEG * numpy.pi / 180)
        h /= numpy.cos(MASK_ROT_V_DEG * numpy.pi / 180)
        # also reduce the power density!!
        p *= numpy.cos(MASK_ROT_H_DEG * numpy.pi / 180)
        p *= numpy.cos(MASK_ROT_V_DEG * numpy.pi / 180)

        #
        # mask
        #
        if MASK_H_MIN is not None:
            lower_window_h = numpy.where(h < MASK_H_MIN)
            if len(lower_window_h) > 0: p[lower_window_h, :] = 0

        if MASK_H_MAX is not None:
            upper_window_h = numpy.where(h > MASK_H_MAX)
            if len(upper_window_h) > 0: p[upper_window_h, :] = 0

        if MASK_V_MIN is not None:
            lower_window_v = numpy.where(v < MASK_V_MIN)
            if len(lower_window_v) > 0: p[:, lower_window_v] = 0

        if MASK_V_MIN is not None:
            upper_window_v = numpy.where(v > MASK_V_MAX)
            if len(upper_window_v) > 0: p[:, upper_window_v] = 0

        txt0 = "============= power density in the modified (masked) screen ==========\n"
    else:
        txt0 = "=================== power density  ======================\n"

    text_info = txt0
    text_info += "  Power density peak: %f W/mm2\n" % p.max()
    text_info += "  Total power: %f W\n" % (p.sum() * (h[1] - h[0]) *
                                            (v[1] - v[0]))
    text_info += "====================================================\n"
    print(text_info)

    # fit
    fit_ok = False
    try:
        print(
            "============= Fitting power density to a 2D Gaussian. ==============\n"
        )
        print(
            "Please use these results with care: check if the original data looks like a Gaussian."
        )
        fit_parameters = fit_gaussian2d(p, h, v)
        print(info_params(fit_parameters))
        H, V = numpy.meshgrid(h, v)
        data_fitted = twoD_Gaussian((H, V), *fit_parameters)
        print("  Total power in the fitted data [W]: ",
              data_fitted.sum() * (h[1] - h[0]) * (v[1] - v[0]))
        # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT")
        print("====================================================\n")
        fit_ok = True
    except:
        pass

    if h5_file != "":
        try:
            if h5_initialize:
                h5w = H5SimpleWriter.initialize_file(
                    h5_file, creator="xoppy_undulators.py")
            else:
                h5w = H5SimpleWriter(h5_file, None)
            h5w.create_entry(h5_entry_name, nx_default="PowerDensity")
            h5w.add_image(p,
                          h,
                          v,
                          image_name="PowerDensity",
                          entry_name=h5_entry_name,
                          title_x="X [mm]",
                          title_y="Y [mm]")
            h5w.add_key("info", text_info, entry_name=h5_entry_name)
            h5w.create_entry("parameters",
                             root_entry=h5_entry_name,
                             nx_default=None)
            for key in h5_parameters.keys():
                h5w.add_key(key,
                            h5_parameters[key],
                            entry_name=h5_entry_name + "/parameters")
            if fit_ok:
                h5w.add_image(data_fitted.reshape(h.size, v.size),
                              h,
                              v,
                              image_name="PowerDensityFit",
                              entry_name=h5_entry_name,
                              title_x="X [mm]",
                              title_y="Y [mm]")
                h5w.add_key("fit_info",
                            info_params(fit_parameters),
                            entry_name=h5_entry_name + "/PowerDensityFit")

            print("File written to disk: %s" % h5_file)
        except:
            print("ERROR initializing h5 file")

    return h, v, p, code