class UndulatorFull(ow_source.Source, WidgetDecorator):

    name = "Full Undulator"
    description = "Shadow Source: Full Undulator"
    icon = "icons/undulator.png"
    priority = 4

    K = Setting(0.25)
    period_length = Setting(0.032)
    periods_number = Setting(50)

    energy_in_GeV = Setting(6.04)
    current = Setting(0.2)
    use_emittances_combo = Setting(1)
    sigma_x = Setting(400e-6)
    sigma_z = Setting(10e-6)
    sigma_divergence_x = Setting(10e-06)
    sigma_divergence_z = Setting(4e-06)

    number_of_rays = Setting(5000)
    seed = Setting(6775431)
    photon_energy = Setting(10500.0)
    harmonic = Setting(1.0)
    set_at_resonance = Setting(0)
    delta_e = Setting(1000.0)
    maxangle_urad = Setting(15)

    # advanced setting
    ng_t = Setting(51)
    ng_p = Setting(11)
    ng_j = Setting(20)
    ng_e = Setting(11)
    code_undul_phot = Setting(0)  # 0=internal 1=pySRU 2=SRW
    flag_size = Setting(1)  # 0=Point 1=Gaussian 2=backpropagate divergences
    coherent = Setting(0)  # 0=No 1=Yes

    # aux
    file_to_write_out = 0
    plot_aux_graph = 1
    sourceundulator = None

    add_power = False
    power_step = None

    inputs = [("Trigger", TriggerOut, "sendNewBeam2")]
    WidgetDecorator.append_syned_input_data(inputs)

    def __init__(self):
        super().__init__()

        self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)

        tabs_setting = oasysgui.tabWidget(self.controlArea)
        tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT)
        tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5)

        tab_bas = oasysgui.createTabPage(tabs_setting, "Basic Setting")
        tab_sou = oasysgui.createTabPage(tabs_setting, "Source Setting")
        tab_grid = oasysgui.createTabPage(tabs_setting, "Advanced Settings")

        left_box_1 = oasysgui.widgetBox(tab_bas,
                                        "Monte Carlo",
                                        addSpace=True,
                                        orientation="vertical")

        oasysgui.lineEdit(left_box_1,
                          self,
                          "number_of_rays",
                          "Number of rays",
                          tooltip="Number of Rays",
                          labelWidth=250,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "seed",
                          "Seed",
                          tooltip="Seed (0=clock)",
                          labelWidth=250,
                          valueType=int,
                          orientation="horizontal")

        left_box_2 = oasysgui.widgetBox(tab_sou,
                                        "Machine Parameters",
                                        addSpace=True,
                                        orientation="vertical")

        oasysgui.lineEdit(left_box_2,
                          self,
                          "energy_in_GeV",
                          "Energy [GeV]",
                          labelWidth=250,
                          tooltip="Energy [GeV]",
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_2,
                          self,
                          "current",
                          "Current [A]",
                          labelWidth=250,
                          tooltip="Current [A]",
                          valueType=float,
                          orientation="horizontal")

        gui.comboBox(left_box_2,
                     self,
                     "use_emittances_combo",
                     label="Use Emittances?",
                     items=["No", "Yes"],
                     callback=self.set_UseEmittances,
                     labelWidth=260,
                     orientation="horizontal")

        self.box_use_emittances = oasysgui.widgetBox(left_box_2,
                                                     "",
                                                     addSpace=False,
                                                     orientation="vertical")

        self.le_sigma_x = oasysgui.lineEdit(self.box_use_emittances,
                                            self,
                                            "sigma_x",
                                            "Size RMS H [m]",
                                            labelWidth=250,
                                            tooltip="Size RMS H [m]",
                                            valueType=float,
                                            orientation="horizontal")
        self.le_sigma_z = oasysgui.lineEdit(self.box_use_emittances,
                                            self,
                                            "sigma_z",
                                            "Size RMS V [m]",
                                            labelWidth=250,
                                            tooltip="Size RMS V [m]",
                                            valueType=float,
                                            orientation="horizontal")

        oasysgui.lineEdit(self.box_use_emittances,
                          self,
                          "sigma_divergence_x",
                          "Divergence RMS H [rad]",
                          labelWidth=250,
                          tooltip="Divergence RMS H [rad]",
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.box_use_emittances,
                          self,
                          "sigma_divergence_z",
                          "Divergence RMS V [rad]",
                          labelWidth=250,
                          tooltip="Divergence RMS V [rad]",
                          valueType=float,
                          orientation="horizontal")

        self.set_UseEmittances()

        left_box_3 = oasysgui.widgetBox(tab_sou,
                                        "Undulator Parameters",
                                        addSpace=True,
                                        orientation="vertical")

        oasysgui.lineEdit(left_box_3,
                          self,
                          "K",
                          "K",
                          labelWidth=250,
                          tooltip="Undulator Deflection Parameter K",
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_3,
                          self,
                          "period_length",
                          "period Length [m]",
                          labelWidth=250,
                          tooltip="Undulator Period Length [m]",
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_3,
                          self,
                          "periods_number",
                          "Number of periods",
                          labelWidth=250,
                          tooltip="Number of periods",
                          valueType=int,
                          orientation="horizontal")

        left_box_4 = oasysgui.widgetBox(tab_sou,
                                        "Photon energy",
                                        addSpace=True,
                                        orientation="vertical")

        #
        gui.comboBox(left_box_4,
                     self,
                     "set_at_resonance",
                     label="Set photon energy",
                     addSpace=False,
                     items=['User defined', 'Set to resonance'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250,
                     callback=self.set_UseResonance)

        self.box_photon_energy = gui.widgetBox(left_box_4)
        oasysgui.lineEdit(self.box_photon_energy,
                          self,
                          "photon_energy",
                          "Photon energy [eV] (center)",
                          tooltip="Photon energy [eV]",
                          labelWidth=250,
                          valueType=float,
                          orientation="horizontal")

        self.box_harmonic = gui.widgetBox(left_box_4)
        oasysgui.lineEdit(self.box_harmonic,
                          self,
                          "harmonic",
                          "Photon energy [N x Resonance]; N: ",
                          tooltip="Photon energy [N x Resonance]; N: ",
                          labelWidth=250,
                          valueType=float,
                          orientation="horizontal")

        self.box_maxangle_urad = gui.widgetBox(left_box_4)
        oasysgui.lineEdit(
            self.box_maxangle_urad,
            self,
            "maxangle_urad",
            "Max elevation angle for radiation [urad]",
            tooltip="Max elevation angle for radiation theta [urad]",
            labelWidth=250,
            valueType=float,
            orientation="horizontal")

        self.set_UseResonance()

        #self.box_photon_energy.setEnabled(False)

        oasysgui.lineEdit(
            left_box_4,
            self,
            "delta_e",
            "Photon energy width [eV] (0=monochr.)",
            tooltip="Photon energy interval [eV] (0=monochromatic)",
            labelWidth=250,
            valueType=float,
            orientation="horizontal")

        adv_other_box = oasysgui.widgetBox(tab_bas,
                                           "Optional file output",
                                           addSpace=False,
                                           orientation="vertical")

        gui.comboBox(adv_other_box,
                     self,
                     "file_to_write_out",
                     label="Files to write out",
                     labelWidth=120,
                     items=["None", "begin.dat", "begin.dat+radiation.h5"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        # advanced
        left_box_5 = oasysgui.widgetBox(tab_grid,
                                        "Advanced Settings",
                                        addSpace=True,
                                        orientation="vertical")
        # ng_t = 51
        # ng_p = 11
        # ng_j = 20
        # ng_e = 11
        # code_undul_phot = 0
        # flag_size = 0
        oasysgui.lineEdit(left_box_5,
                          self,
                          "ng_e",
                          "Points in Photon energy (if polychromatic)",
                          tooltip="Points in Photon energy",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_5,
                          self,
                          "ng_t",
                          "Points in theta [elevation]",
                          tooltip="Points in theta [elevation]",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_5,
                          self,
                          "ng_p",
                          "Points in phi [azimuthal]",
                          tooltip="Points in phi [azimuthal]",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_5,
                          self,
                          "ng_j",
                          "Points in electron trajectory",
                          tooltip="Points in electron trajectory",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")

        gui.comboBox(left_box_5,
                     self,
                     "code_undul_phot",
                     label="Calculation method",
                     labelWidth=120,
                     items=["internal", "pySRU", "SRW"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.comboBox(left_box_5,
                     self,
                     "flag_size",
                     label="Radiation Size",
                     labelWidth=120,
                     items=["point", "Gaussian", "Far field backpropagated"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.comboBox(left_box_5,
                     self,
                     "coherent",
                     label="Coherent beam",
                     labelWidth=120,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.rubber(self.controlArea)

        undulator_plot_tab = oasysgui.widgetBox(self.main_tabs,
                                                addToLayout=0,
                                                margin=4)

        self.main_tabs.insertTab(1, undulator_plot_tab, "Undulator Plots")

        view_box = oasysgui.widgetBox(undulator_plot_tab,
                                      "Plotting Style",
                                      addSpace=False,
                                      orientation="horizontal")
        view_box_1 = oasysgui.widgetBox(view_box,
                                        "",
                                        addSpace=False,
                                        orientation="vertical",
                                        width=350)

        self.undulator_view_type_combo = gui.comboBox(
            view_box_1,
            self,
            "plot_aux_graph",
            label="Plot Graphs?",
            labelWidth=220,
            items=["No", "Yes"],
            callback=self.set_PlotAuxGraphs,
            sendSelectedValue=False,
            orientation="horizontal")

        self.undulator_tab = []
        self.undulator_tabs = oasysgui.tabWidget(undulator_plot_tab)

        self.initializeUndulatorTabs()

        gui.rubber(self.mainArea)

    def sendNewBeam2(self, trigger):
        self.power_step = None
        self.add_power = False

        try:
            if trigger and trigger.new_object == True:
                if trigger.has_additional_parameter("seed_increment"):
                    self.seed += trigger.get_additional_parameter(
                        "seed_increment")

                if trigger.has_additional_parameter(
                        "energy_value") and trigger.has_additional_parameter(
                            "energy_step"):
                    self.set_at_resonance = 0
                    self.photon_energy = trigger.get_additional_parameter(
                        "energy_value")
                    self.delta_e = trigger.get_additional_parameter(
                        "energy_step")
                    self.power_step = trigger.get_additional_parameter(
                        "power_step")

                    self.set_UseResonance()

                    self.add_power = True

                self.runShadowSource()
        except:
            pass

    def set_UseEmittances(self):
        self.box_use_emittances.setVisible(self.use_emittances_combo == 1)

    def set_UseResonance(self):
        self.box_photon_energy.setVisible(self.set_at_resonance == 0)
        self.box_maxangle_urad.setVisible(self.set_at_resonance == 0)
        self.box_harmonic.setVisible(self.set_at_resonance > 0)

    def set_PlotAuxGraphs(self):
        # self.progressBarInit()

        self.initializeUndulatorTabs(
        )  # update number of tabs if monochromatic/polychromatic

        if self.sourceundulator is not None:
            try:
                self.initializeUndulatorTabs()

                self.plot_undulator_results()
            except Exception as exception:
                QtWidgets.QMessageBox.critical(self, "Error", str(exception),
                                               QtWidgets.QMessageBox.Ok)

        # self.progressBarFinished()

    def plot_undulator_results(self):
        if self.plot_aux_graph == 1:
            try:

                radiation, photon_energy, theta, phi = self.sourceundulator.get_radiation_polar(
                )

                tabs_canvas_index = 0
                plot_canvas_index = 0
                polarization = self.sourceundulator.get_result_polarization()

                if self.delta_e == 0.0:
                    self.plot_data2D(radiation[0],
                                     1e6 * theta,
                                     phi,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="radiation (photons/s/eV/rad2)",
                                     xtitle="theta [urad]",
                                     ytitle="phi [rad]")

                    tabs_canvas_index += 1
                    self.plot_data2D(polarization[0],
                                     1e6 * theta,
                                     phi,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="polarization |Es|/(|Es|+|Ep|)",
                                     xtitle="theta [urad]",
                                     ytitle="phi [rad]")

                    tabs_canvas_index += 1
                    radiation_interpolated, photon_energy, vx, vz = self.sourceundulator.get_radiation_interpolated_cartesian(
                    )
                    self.plot_data2D(radiation_interpolated[0],
                                     1e6 * vx,
                                     1e6 * vz,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="radiation",
                                     xtitle="vx [urad]",
                                     ytitle="vz [rad]")

                    tabs_canvas_index += 1
                    x, y = self.sourceundulator.get_photon_size_distribution()
                    self.plot_data1D(x * 1e6,
                                     y,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="Photon emission size distribution",
                                     xtitle="Distance [um]",
                                     ytitle="Intensity [arbitrary units]")

                else:
                    self.plot_data3D(
                        radiation,
                        photon_energy,
                        1e6 * theta,
                        phi,
                        tabs_canvas_index,
                        plot_canvas_index,
                        title="radiation (photons/s/eV/rad2)",
                        xtitle="theta [urad]",
                        ytitle="phi [rad]",
                        callback_for_title=self.get_title_for_stack_view_flux)

                    tabs_canvas_index += 1
                    self.plot_data3D(polarization,
                                     photon_energy,
                                     1e6 * theta,
                                     phi,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="polarization |Es|/(|Es|+|Ep|)",
                                     xtitle="theta [urad]",
                                     ytitle="phi [rad]",
                                     callback_for_title=self.
                                     get_title_for_stack_view_polarization)

                    tabs_canvas_index += 1
                    radiation_interpolated, photon_energy, vx, vz = self.sourceundulator.get_radiation_interpolated_cartesian(
                    )
                    self.plot_data3D(
                        radiation_interpolated,
                        photon_energy,
                        1e6 * vx,
                        1e6 * vz,
                        tabs_canvas_index,
                        plot_canvas_index,
                        title="radiation",
                        xtitle="vx [urad]",
                        ytitle="vz [rad]",
                        callback_for_title=self.get_title_for_stack_view_flux)

                    tabs_canvas_index += 1
                    x, y = self.sourceundulator.get_photon_size_distribution()
                    self.plot_data1D(x * 1e6,
                                     y,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="Photon emission size distribution",
                                     xtitle="Distance [um]",
                                     ytitle="Intensity [arbitrary units]")
                    #
                    # if polychromatic, plot power density
                    #

                    intens_xy, vx, vz = self.sourceundulator.get_power_density_interpolated_cartesian(
                    )

                    tabs_canvas_index += 1
                    self.plot_data2D(1e-6 * intens_xy,
                                     1e6 * vx,
                                     1e6 * vz,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="power density W/mrad2",
                                     xtitle="vx [urad]",
                                     ytitle="vz [rad]")

                    #
                    # if polychromatic, plot flux(energy)
                    #

                    flux, spectral_power, photon_energy = self.sourceundulator.get_flux_and_spectral_power(
                    )

                    tabs_canvas_index += 1
                    self.plot_data1D(photon_energy,
                                     flux,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="Flux",
                                     xtitle="Photon Energy [eV]",
                                     ytitle="Flux [photons/s/0.1%bw]")

                    tabs_canvas_index += 1
                    self.plot_data1D(photon_energy,
                                     spectral_power,
                                     tabs_canvas_index,
                                     plot_canvas_index,
                                     title="Spectral Power",
                                     xtitle="Photon Energy [eV]",
                                     ytitle="Spectral Power [W/eV]")

                    print("\n\n")
                    # print("Total power (integral [sum] of spectral power) [W]: ",spectral_power.sum()*(photon_energy[1]-photon_energy[0]))
                    print(
                        "Total power (integral [trapz] of spectral power) [W]: ",
                        numpy.trapz(spectral_power, photon_energy))
                    print(
                        "Total number of photons (integral [trapz] of flux): ",
                        numpy.trapz(flux / (1e-3 * photon_energy),
                                    photon_energy))
                    print("\n\n")

            except Exception as exception:
                QtWidgets.QMessageBox.critical(self, "Error", str(exception),
                                               QtWidgets.QMessageBox.Ok)

    def get_title_for_stack_view_flux(self, idx):
        photon_energy = self.sourceundulator.get_result_photon_energy()
        return "Units: Photons/s/eV/rad2; Photon energy: %8.3f eV" % (
            photon_energy[idx])

    #
    # these are plottting routines hacked from xoppy code TODO: promote to higher level/superclass ?
    #
    def get_title_for_stack_view_polarization(self, idx):
        photon_energy = self.sourceundulator.get_result_photon_energy()
        return "|Es| / (|Es|+|Ep|); Photon energy: %8.3f eV" % (
            photon_energy[idx])

    def plot_data3D(self,
                    data3D,
                    dataE,
                    dataX,
                    dataY,
                    tabs_canvas_index,
                    plot_canvas_index,
                    title="",
                    xtitle="",
                    ytitle="",
                    callback_for_title=(lambda idx: "")):

        for i in range(1 +
                       self.undulator_tab[tabs_canvas_index].layout().count()):
            self.undulator_tab[tabs_canvas_index].layout().removeItem(
                self.undulator_tab[tabs_canvas_index].layout().itemAt(i))

        ##self.tab[tabs_canvas_index].layout().removeItem(self.tab[tabs_canvas_index].layout().itemAt(0))

        xmin = numpy.min(dataX)
        xmax = numpy.max(dataX)
        ymin = numpy.min(dataY)
        ymax = numpy.max(dataY)

        stepX = dataX[1] - dataX[0]
        stepY = dataY[1] - dataY[0]
        if len(dataE) > 1: stepE = dataE[1] - dataE[0]
        else: stepE = 1.0

        if stepE == 0.0: stepE = 1.0
        if stepX == 0.0: stepX = 1.0
        if stepY == 0.0: stepY = 1.0

        dim0_calib = (dataE[0], stepE)
        dim1_calib = (ymin, stepY)
        dim2_calib = (xmin, stepX)

        data_to_plot = numpy.swapaxes(data3D, 1, 2)

        colormap = {
            "name": "temperature",
            "normalization": "linear",
            "autoscale": True,
            "vmin": 0,
            "vmax": 0,
            "colors": 256
        }

        self.und_plot_canvas[plot_canvas_index] = StackViewMainWindow()
        self.und_plot_canvas[plot_canvas_index].setGraphTitle(title)
        self.und_plot_canvas[plot_canvas_index].setLabels(
            ["Photon Energy [eV]", ytitle, xtitle])
        self.und_plot_canvas[plot_canvas_index].setColormap(colormap=colormap)
        self.und_plot_canvas[plot_canvas_index].setStack(
            numpy.array(data_to_plot),
            calibrations=[dim0_calib, dim1_calib, dim2_calib])

        self.und_plot_canvas[plot_canvas_index].setTitleCallback(
            callback_for_title)
        self.undulator_tab[tabs_canvas_index].layout().addWidget(
            self.und_plot_canvas[plot_canvas_index])

    def plot_data2D(self,
                    data2D,
                    dataX,
                    dataY,
                    tabs_canvas_index,
                    plot_canvas_index,
                    title="",
                    xtitle="",
                    ytitle=""):

        for i in range(1 +
                       self.undulator_tab[tabs_canvas_index].layout().count()):
            self.undulator_tab[tabs_canvas_index].layout().removeItem(
                self.undulator_tab[tabs_canvas_index].layout().itemAt(i))

        origin = (dataX[0], dataY[0])
        scale = (dataX[1] - dataX[0], dataY[1] - dataY[0])

        data_to_plot = data2D.T

        colormap = {
            "name": "temperature",
            "normalization": "linear",
            "autoscale": True,
            "vmin": 0,
            "vmax": 0,
            "colors": 256
        }

        self.und_plot_canvas[plot_canvas_index] = Plot2D()
        self.und_plot_canvas[plot_canvas_index].resetZoom()
        self.und_plot_canvas[plot_canvas_index].setXAxisAutoScale(True)
        self.und_plot_canvas[plot_canvas_index].setYAxisAutoScale(True)
        self.und_plot_canvas[plot_canvas_index].setGraphGrid(False)
        self.und_plot_canvas[plot_canvas_index].setKeepDataAspectRatio(True)
        self.und_plot_canvas[plot_canvas_index].yAxisInvertedAction.setVisible(
            False)
        self.und_plot_canvas[plot_canvas_index].setXAxisLogarithmic(False)
        self.und_plot_canvas[plot_canvas_index].setYAxisLogarithmic(False)
        self.und_plot_canvas[plot_canvas_index].getMaskAction().setVisible(
            False)
        self.und_plot_canvas[plot_canvas_index].getRoiAction().setVisible(
            False)
        self.und_plot_canvas[plot_canvas_index].getColormapAction().setVisible(
            False)
        self.und_plot_canvas[plot_canvas_index].setKeepDataAspectRatio(False)

        self.und_plot_canvas[plot_canvas_index].addImage(
            numpy.array(data_to_plot),
            legend="",
            scale=scale,
            origin=origin,
            colormap=colormap,
            replace=True)

        self.und_plot_canvas[plot_canvas_index].setActiveImage("")
        self.und_plot_canvas[plot_canvas_index].setGraphXLabel(xtitle)
        self.und_plot_canvas[plot_canvas_index].setGraphYLabel(ytitle)
        self.und_plot_canvas[plot_canvas_index].setGraphTitle(title)

        self.undulator_tab[tabs_canvas_index].layout().addWidget(
            self.und_plot_canvas[plot_canvas_index])

    def plot_data1D(self,
                    dataX,
                    dataY,
                    tabs_canvas_index,
                    plot_canvas_index,
                    title="",
                    xtitle="",
                    ytitle=""):

        self.undulator_tab[tabs_canvas_index].layout().removeItem(
            self.undulator_tab[tabs_canvas_index].layout().itemAt(0))

        self.und_plot_canvas[plot_canvas_index] = oasysgui.plotWindow()

        self.und_plot_canvas[plot_canvas_index].addCurve(
            dataX,
            dataY,
        )

        self.und_plot_canvas[plot_canvas_index].resetZoom()
        self.und_plot_canvas[plot_canvas_index].setXAxisAutoScale(True)
        self.und_plot_canvas[plot_canvas_index].setYAxisAutoScale(True)
        self.und_plot_canvas[plot_canvas_index].setGraphGrid(False)

        self.und_plot_canvas[plot_canvas_index].setXAxisLogarithmic(False)
        self.und_plot_canvas[plot_canvas_index].setYAxisLogarithmic(False)
        self.und_plot_canvas[plot_canvas_index].setGraphXLabel(xtitle)
        self.und_plot_canvas[plot_canvas_index].setGraphYLabel(ytitle)
        self.und_plot_canvas[plot_canvas_index].setGraphTitle(title)

        self.undulator_tab[tabs_canvas_index].layout().addWidget(
            self.und_plot_canvas[plot_canvas_index])

    #
    # end plotting routines
    #

    def initializeUndulatorTabs(self):
        current_tab = self.undulator_tabs.currentIndex()

        size = len(self.undulator_tab)
        indexes = range(0, size)
        for index in indexes:
            self.undulator_tabs.removeTab(size - 1 - index)

        if self.delta_e == 0.0:
            self.undulator_tab = [
                gui.createTabPage(self.undulator_tabs,
                                  "Radiation intensity (polar)"),
                gui.createTabPage(self.undulator_tabs, "Polarization (polar)"),
                gui.createTabPage(
                    self.undulator_tabs,
                    "Radiation intensity (cartesian - interpolated)"),
                gui.createTabPage(self.undulator_tabs, "Photon source size"),
            ]

            self.und_plot_canvas = [
                None,
                None,
                None,
                None,
            ]
        else:
            self.undulator_tab = [
                gui.createTabPage(self.undulator_tabs, "Radiation (polar)"),
                gui.createTabPage(self.undulator_tabs, "Polarization (polar)"),
                gui.createTabPage(self.undulator_tabs,
                                  "Radiation (interpolated)"),
                gui.createTabPage(self.undulator_tabs, "Photon source size"),
                gui.createTabPage(self.undulator_tabs,
                                  "Power Density (interpolated)"),
                gui.createTabPage(self.undulator_tabs, "Flux"),
                gui.createTabPage(self.undulator_tabs, "Spectral Power"),
            ]

            self.und_plot_canvas = [
                None,
                None,
                None,
                None,
                None,
                None,
                None,
            ]

        for tab in self.undulator_tab:
            tab.setFixedHeight(self.IMAGE_HEIGHT)
            tab.setFixedWidth(self.IMAGE_WIDTH)

        # self.undulator_plot_canvas = [None, None, None]

        self.undulator_tabs.setCurrentIndex(current_tab)

    def runShadowSource(self):

        self.setStatusMessage("")
        self.progressBarInit()

        # this is to be able to start the widget out of Oasys
        try:
            tmp = self.workspace_units
        except:
            self.workspace_units = 'm'
            self.workspace_units_label = 'm'
            self.workspace_units_to_m = 1.0
            self.workspace_units_to_cm = 1e2
            self.workspace_units_to_mm = 1e3

        self.checkFields()

        self.progressBarSet(10)

        self.setStatusMessage("Running SHADOW")

        sys.stdout = EmittingStream(textWritten=self.writeStdOut)
        if self.trace_shadow:
            grabber = TTYGrabber()
            grabber.start()

        self.progressBarSet(50)

        try:
            self.shadow_output.setText("")
            su = Undulator.initialize_as_vertical_undulator(
                K=self.K,
                period_length=self.period_length,
                periods_number=int(self.periods_number))

            ebeam = ElectronBeam(energy_in_GeV=self.energy_in_GeV,
                                 energy_spread=0.0,
                                 current=self.current,
                                 number_of_bunches=1,
                                 moment_xx=(self.sigma_x)**2,
                                 moment_xxp=0.0,
                                 moment_xpxp=(self.sigma_divergence_x)**2,
                                 moment_yy=(self.sigma_z)**2,
                                 moment_yyp=0.0,
                                 moment_ypyp=(self.sigma_divergence_z)**2)

            print(ebeam.info())

            codes = ["internal", "pySRU", "SRW"]
            selected_code = codes[self.code_undul_phot]

            self.sourceundulator = SourceUndulator(
                name="shadowOui-Full-Undulator",
                syned_electron_beam=ebeam,
                syned_undulator=su,
                flag_emittance=self.use_emittances_combo,
                flag_size=self.flag_size,
                emin=1000,  # to be set later
                emax=1001,  # to be set later
                ng_e=2,  # to be set later
                maxangle=self.maxangle_urad * 1e-6,
                ng_t=self.ng_t,
                ng_p=self.ng_p,
                ng_j=self.ng_j,
                code_undul_phot=selected_code)

            if self.set_at_resonance == 0:
                if self.delta_e == 0:
                    self.sourceundulator.set_energy_box(
                        self.photon_energy, self.photon_energy, 1)
                else:
                    self.sourceundulator.set_energy_box(
                        self.photon_energy - 0.5 * self.delta_e,
                        self.photon_energy + 0.5 * self.delta_e, self.ng_e)
            else:
                self.sourceundulator.set_energy_monochromatic_at_resonance(
                    self.harmonic)
                if self.delta_e > 0.0:
                    e0, e1, ne = self.sourceundulator.get_energy_box()
                    self.sourceundulator.set_energy_box(
                        e0 - 0.5 * self.delta_e, e0 + 0.5 * self.delta_e,
                        self.ng_e)

            rays = self.sourceundulator.calculate_rays(
                user_unit_to_m=self.workspace_units_to_m,
                F_COHER=self.coherent,
                SEED=self.seed,
                NRAYS=self.number_of_rays)

            if self.plot_aux_graph:
                self.set_PlotAuxGraphs()

            print(self.sourceundulator.info())

            shadow3_beam = Shadow3Beam(N=rays.shape[0])
            shadow3_beam.rays = rays

            if self.file_to_write_out >= 1:
                shadow3_beam.write("begin.dat")
                print("File written to disk: begin.dat")

            if self.file_to_write_out >= 2:
                SourceUndulatorInputOutput.write_file_undul_phot_h5(
                    self.sourceundulator.get_result_dictionary(),
                    file_out="radiation.h5",
                    mode="w",
                    entry_name="radiation")

            beam_out = ShadowBeam(beam=shadow3_beam)
            beam_out.getOEHistory().append(ShadowOEHistoryItem())

            if self.add_power:
                additional_parameters = {}

                pd, vx, vy = self.sourceundulator.get_power_density_interpolated_cartesian(
                )

                total_power = self.power_step if self.power_step > 0 else pd.sum(
                ) * (vx[1] - vx[0]) * (vy[1] - vy[0])

                additional_parameters["total_power"] = total_power
                additional_parameters["photon_energy_step"] = self.delta_e

                beam_out.setScanningData(
                    ShadowBeam.ScanningData("photon_energy",
                                            self.photon_energy,
                                            "Energy for Power Calculation",
                                            "eV", additional_parameters))

            if self.delta_e == 0.0:
                beam_out.set_initial_flux(self.sourceundulator.get_flux()[0])

            self.progressBarSet(80)
            self.plot_results(beam_out)

            #
            # create python script for creating the shadow3 beam and display the script in the standard output
            #
            dict_parameters = {
                "K": self.K,
                "period_length": self.period_length,
                "periods_number": self.periods_number,
                "energy_in_GeV": self.energy_in_GeV,
                "energy_spread": 0.0,
                "current": self.current,
                "number_of_bunches": 1,
                "moment_xx": (self.sigma_x)**2,
                "moment_xxp": 0.0,
                "moment_xpxp": (self.sigma_divergence_x)**2,
                "moment_yy": (self.sigma_z)**2,
                "moment_yyp": 0.0,
                "moment_ypyp": (self.sigma_divergence_z)**2,
                "name": "shadowOui-Full-Undulator",
                "flag_emittance": self.use_emittances_combo,
                "flag_size": self.flag_size,
                "emin": 1000,  # to be set later
                "emax": 1001,  # to be set later
                "ng_e": 2,  # to be set later
                "maxangle": self.maxangle_urad * 1e-6,
                "ng_t": self.ng_t,
                "ng_p": self.ng_p,
                "ng_j": self.ng_j,
                "code_undul_phot": selected_code,
                "user_unit_to_m": self.workspace_units_to_m,
                "F_COHER": self.coherent,
                "SEED": self.seed,
                "NRAYS": self.number_of_rays,
                "EMIN": self.sourceundulator._EMIN,
                "EMAX": self.sourceundulator._EMAX,
                "NG_E": self.sourceundulator._NG_E,
                "MAXANGLE": self.sourceundulator._MAXANGLE,
            }

            # write python script in standard output
            print(self.script_template().format_map(dict_parameters))

            self.setStatusMessage("")
            self.send("Beam", beam_out)

        except Exception as exception:
            QtWidgets.QMessageBox.critical(self, "Error", str(exception),
                                           QtWidgets.QMessageBox.Ok)

            if self.IS_DEVELOP: raise exception

        self.progressBarFinished()

    def script_template(self):
        return """
#
# script to calculate the shadow3 beam for the full undulator (created by ShadowOui:UndulatorFull\)
#
from syned.storage_ring.electron_beam import ElectronBeam
from syned.storage_ring.magnetic_structures.undulator import Undulator
from orangecontrib.shadow.util.undulator.source_undulator import SourceUndulator
import Shadow
from Shadow import Beam as Shadow3Beam

su = Undulator.initialize_as_vertical_undulator(
    K={K},
    period_length={period_length},
    periods_number={periods_number})


ebeam = ElectronBeam(
    energy_in_GeV={energy_in_GeV},
    energy_spread = {energy_spread},
    current = {current},
    number_of_bunches = {number_of_bunches},
    moment_xx   ={moment_xx},
    moment_xxp  ={moment_xxp},
    moment_xpxp ={moment_xpxp},
    moment_yy  ={moment_yy},
    moment_yyp ={moment_yyp},
    moment_ypyp={moment_ypyp})

print(ebeam.info())

sourceundulator = SourceUndulator(
    name="{name}",
    syned_electron_beam=ebeam,
    syned_undulator=su,
    flag_emittance={flag_emittance},
    flag_size={flag_size},
    emin       = {emin},
    emax       = {emax},
    ng_e       = {ng_e},
    maxangle   = {maxangle},
    ng_t={ng_t},
    ng_p={ng_p},
    ng_j={ng_j},
    code_undul_phot="{code_undul_phot}")
    
sourceundulator._EMIN = {EMIN}
sourceundulator._EMAX = {EMAX}
sourceundulator._NG_E = {NG_E}
sourceundulator._MAXANGLE = {MAXANGLE}

rays = sourceundulator.calculate_rays(
    user_unit_to_m={user_unit_to_m},
    F_COHER={F_COHER},
    SEED={SEED},
    NRAYS={NRAYS})

print(sourceundulator.info())

beam = Shadow3Beam(N=rays.shape[0])
beam.rays = rays

Shadow.ShadowTools.plotxy(beam,1,3,nbins=101,nolost=1,title="Real space")
# Shadow.ShadowTools.plotxy(beam,1,4,nbins=101,nolost=1,title="Phase space X")
# Shadow.ShadowTools.plotxy(beam,3,6,nbins=101,nolost=1,title="Phase space Z")
    
#
# end script
#
"""

    def sendNewBeam(self, trigger):
        if trigger and trigger.new_object == True:
            self.runShadowSource()

    def checkFields(self):
        self.number_of_rays = congruence.checkPositiveNumber(
            self.number_of_rays, "Number of rays")
        self.seed = congruence.checkPositiveNumber(self.seed, "Seed")
        self.photon_energy = congruence.checkPositiveNumber(
            self.photon_energy, "Energy")
        self.delta_e = congruence.checkPositiveNumber(self.delta_e,
                                                      "Delta Energy")

        self.energy_in_GeV = congruence.checkPositiveNumber(
            self.energy_in_GeV, "Energy [GeV]")
        self.current = congruence.checkPositiveNumber(self.current,
                                                      "Current [A]")

        self.sigma_x = congruence.checkPositiveNumber(self.sigma_x,
                                                      "Size RMS H")
        self.sigma_z = congruence.checkPositiveNumber(self.sigma_z,
                                                      "Size RMS V")
        self.sigma_divergence_x = congruence.checkPositiveNumber(
            self.sigma_divergence_x, "Divergence RMS H")
        self.sigma_divergence_z = congruence.checkPositiveNumber(
            self.sigma_divergence_z, "Divergence RMS V")

        self.K = congruence.checkPositiveNumber(self.K, "K")
        self.period_length = congruence.checkPositiveNumber(
            self.period_length, "period length [m]")
        self.periods_number = congruence.checkStrictlyPositiveNumber(
            self.periods_number, "Number of periods")

        self.ng_t = int(
            congruence.checkStrictlyPositiveNumber(
                self.ng_t, "Number of points in theta"))
        self.ng_p = int(
            congruence.checkStrictlyPositiveNumber(self.ng_p,
                                                   "Number of points in phi"))
        self.ng_j = int(
            congruence.checkStrictlyPositiveNumber(
                self.ng_j, "Number of points in trajectory"))
        self.ng_e = int(
            congruence.checkStrictlyPositiveNumber(
                self.ng_e, "Number of points in energy"))

    def receive_syned_data(self, data):
        if not data is None:
            if isinstance(data, synedb.Beamline):
                if not data.get_light_source() is None:
                    if isinstance(
                            data.get_light_source().get_magnetic_structure(),
                            synedu.Undulator):
                        light_source = data.get_light_source()

                        # self.photon_energy =  round(light_source.get_magnetic_structure().resonance_energy(light_source.get_electron_beam().gamma()), 3)
                        self.set_at_resonance = 1
                        self.set_UseResonance()
                        self.delta_e = 0.0

                        self.energy_in_GeV = light_source.get_electron_beam(
                        ).energy()
                        self.current = light_source.get_electron_beam(
                        ).current()

                        x, xp, y, yp = light_source.get_electron_beam(
                        ).get_sigmas_all()

                        self.sigma_x = x
                        self.sigma_z = y
                        self.sigma_divergence_x = xp
                        self.sigma_divergence_z = yp

                        self.period_length = light_source.get_magnetic_structure(
                        ).period_length()
                        self.periods_number = int(
                            light_source.get_magnetic_structure(
                            ).number_of_periods())  # in meter
                        self.K = light_source.get_magnetic_structure(
                        ).K_vertical()
                    else:
                        raise ValueError("Syned light source not congruent")
                else:
                    raise ValueError(
                        "Syned data not correct: light source not present")
            else:
                raise ValueError("Syned data not correct")
Exemple #2
0
class OWSRWGrating(OWSRWOpticalElement):

    tangential_size = Setting(1.2)
    sagittal_size = Setting(0.01)
    horizontal_position_of_mirror_center = Setting(0.0)
    vertical_position_of_mirror_center = Setting(0.0)

    add_acceptance_slit = Setting(0)

    has_height_profile = Setting(0)
    height_profile_data_file = Setting("mirror.dat")
    height_profile_data_file_dimension = Setting(0)
    height_amplification_coefficient = Setting(1.0)

    diffraction_order = Setting(1)
    grooving_density_0 = Setting(
        800.0
    )  # groove density [lines/mm] (coefficient a0 in the polynomial groove density: a0 + a1*y + a2*y^2 + a3*y^3 + a4*y^4)
    grooving_density_1 = Setting(
        0.0)  # groove density polynomial coefficient a1 [lines/mm\u00b2]
    grooving_density_2 = Setting(
        0.0)  # groove density polynomial coefficient a2 [lines/mm\u00b3]
    grooving_density_3 = Setting(
        0.0)  # groove density polynomial coefficient a3 [lines/mm\u2074]
    grooving_density_4 = Setting(
        0.0)  # groove density polynomial coefficient a4 [lines/mm\u2075]
    grooving_angle = Setting(
        0.0
    )  # angle between the groove direction and the sagittal direction of the substrate

    inputs = [("SRWData", SRWData, "set_input"),
              ("Trigger", TriggerOut, "propagate_new_wavefront"),
              ("PreProcessor Data", SRWPreProcessorData,
               "setPreProcessorData"),
              WidgetDecorator.syned_input_data()[0]]

    def __init__(self):
        super().__init__(azimuth_hor_vert=True)

    def draw_specific_box(self):

        tabs_grat = oasysgui.tabWidget(self.tab_bas)

        tab_grat = oasysgui.createTabPage(tabs_grat, "Grating")
        tab_errp = oasysgui.createTabPage(tabs_grat, "Error Profile")

        self.grating_setting = oasysgui.tabWidget(tab_grat)

        substrate_tab = oasysgui.createTabPage(self.grating_setting,
                                               "Substrate Mirror Setting")
        grooving_tab = oasysgui.createTabPage(self.grating_setting,
                                              "Grooving Setting")

        self.substrate_box = oasysgui.widgetBox(substrate_tab,
                                                "",
                                                addSpace=False,
                                                orientation="vertical")
        self.grooving_box = oasysgui.widgetBox(grooving_tab,
                                               "",
                                               addSpace=False,
                                               orientation="vertical")

        oasysgui.lineEdit(self.substrate_box,
                          self,
                          "tangential_size",
                          "Tangential Size [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.substrate_box,
                          self,
                          "sagittal_size",
                          "Sagittal_Size [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.substrate_box,
                          self,
                          "horizontal_position_of_mirror_center",
                          "Horizontal position of mirror center [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.substrate_box,
                          self,
                          "vertical_position_of_mirror_center",
                          "Vertical position of mirror center [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        gui.comboBox(self.substrate_box,
                     self,
                     "add_acceptance_slit",
                     label="Add Acceptance Slit",
                     items=["No", "Yes"],
                     labelWidth=300,
                     sendSelectedValue=False,
                     orientation="horizontal")

        oasysgui.lineEdit(self.grooving_box,
                          self,
                          "diffraction_order",
                          "Diffraction order",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(
            self.grooving_box,
            self,
            "grooving_angle",
            "Angle between groove direction and\nsagittal direction of the substrate [deg]",
            labelWidth=260,
            valueType=float,
            orientation="horizontal")

        oasysgui.lineEdit(self.grooving_box,
                          self,
                          "grooving_density_0",
                          "Groove density [lines/mm]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.grooving_box,
                          self,
                          "grooving_density_1",
                          "Groove den. poly. coeff. a1 [lines/mm\u00b2]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.grooving_box,
                          self,
                          "grooving_density_2",
                          "Groove den. poly. coeff. a2 [lines/mm\u00b3]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.grooving_box,
                          self,
                          "grooving_density_3",
                          "Groove den. poly. coeff. a3 [lines/mm\u2074]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.grooving_box,
                          self,
                          "grooving_density_4",
                          "Groove den. poly. coeff. a4 [lines/mm\u2075]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        self.error_box = oasysgui.widgetBox(tab_errp,
                                            "",
                                            addSpace=False,
                                            orientation="vertical")

        gui.comboBox(self.error_box,
                     self,
                     "has_height_profile",
                     label="Use Height Error Profile",
                     items=["No", "Yes"],
                     labelWidth=300,
                     sendSelectedValue=False,
                     orientation="horizontal",
                     callback=self.set_HeightProfile)

        gui.separator(self.error_box)

        self.height_profile_box_1 = oasysgui.widgetBox(self.error_box,
                                                       "",
                                                       addSpace=False,
                                                       orientation="vertical",
                                                       height=110)
        self.height_profile_box_2 = oasysgui.widgetBox(self.error_box,
                                                       "",
                                                       addSpace=False,
                                                       orientation="vertical",
                                                       height=110)

        file_box = oasysgui.widgetBox(self.height_profile_box_2,
                                      "",
                                      addSpace=False,
                                      orientation="horizontal")

        self.le_height_profile_data_file = oasysgui.lineEdit(
            file_box,
            self,
            "height_profile_data_file",
            "Height profile data file",
            labelWidth=155,
            valueType=str,
            orientation="horizontal")
        gui.button(file_box,
                   self,
                   "...",
                   callback=self.selectHeightProfileDataFile)

        file_box_2 = oasysgui.widgetBox(self.height_profile_box_2,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        gui.comboBox(file_box_2,
                     self,
                     "height_profile_data_file_dimension",
                     label="Dimension",
                     items=["1", "2"],
                     labelWidth=280,
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.button(file_box_2, self, "View", callback=self.view_height_profile)

        oasysgui.lineEdit(self.height_profile_box_2,
                          self,
                          "height_amplification_coefficient",
                          "Height Amplification Coefficient",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        self.set_HeightProfile()

    def selectHeightProfileDataFile(self):
        self.le_height_profile_data_file.setText(
            oasysgui.selectFileFromDialog(self, self.height_profile_data_file,
                                          "Height profile data file"))

    def set_HeightProfile(self):
        self.height_profile_box_1.setVisible(self.has_height_profile == 0)
        self.height_profile_box_2.setVisible(self.has_height_profile == 1)

    def get_optical_element(self):
        grating = self.get_grating_instance()

        grating.tangential_size = self.tangential_size
        grating.sagittal_size = self.sagittal_size
        grating.grazing_angle = numpy.radians(90 - self.angle_radial)
        grating.orientation_of_reflection_plane = self.orientation_azimuthal
        grating.invert_tangent_component = self.invert_tangent_component == 1
        grating.add_acceptance_slit = self.add_acceptance_slit == 1
        grating.height_profile_data_file = self.height_profile_data_file if self.has_height_profile else None
        grating.height_profile_data_file_dimension = self.height_profile_data_file_dimension + 1
        grating.height_amplification_coefficient = self.height_amplification_coefficient
        grating.diffraction_order = self.diffraction_order
        grating.grooving_density_0 = self.grooving_density_0
        grating.grooving_density_1 = self.grooving_density_1
        grating.grooving_density_2 = self.grooving_density_2
        grating.grooving_density_3 = self.grooving_density_3
        grating.grooving_density_4 = self.grooving_density_4
        grating.grooving_angle = numpy.radians(self.grooving_angle)

        return grating

    def set_additional_parameters(self, beamline_element,
                                  propagation_parameters, beamline):
        grating = beamline.get_beamline_element_at(-1).get_optical_element()

        orientation_of_the_output_optical_axis_vector_x, \
        orientation_of_the_output_optical_axis_vector_y, \
        orientation_of_the_output_optical_axis_vector_z, \
        orientation_of_the_horizontal_base_vector_x    , \
        orientation_of_the_horizontal_base_vector_y     = grating.get_output_orientation_vectors(self.input_srw_data.get_srw_wavefront().get_photon_energy())

        self.oe_orientation_of_the_output_optical_axis_vector_x = round(
            orientation_of_the_output_optical_axis_vector_x, 8)
        self.oe_orientation_of_the_output_optical_axis_vector_y = round(
            orientation_of_the_output_optical_axis_vector_y, 8)
        self.oe_orientation_of_the_output_optical_axis_vector_z = round(
            orientation_of_the_output_optical_axis_vector_z, 8)
        self.oe_orientation_of_the_horizontal_base_vector_x = round(
            orientation_of_the_horizontal_base_vector_x, 8)
        self.oe_orientation_of_the_horizontal_base_vector_y = round(
            orientation_of_the_horizontal_base_vector_y, 8)

        super(OWSRWGrating,
              self).set_additional_parameters(beamline_element,
                                              propagation_parameters, beamline)

    def get_grating_instance(self):
        raise NotImplementedError()

    def receive_specific_syned_data(self, optical_element):
        if not optical_element is None:
            if isinstance(optical_element, Grating):
                boundaries = optical_element._boundary_shape.get_boundaries()

                self.tangential_size = round(
                    abs(boundaries[3] - boundaries[2]), 6)
                self.sagittal_size = round(abs(boundaries[1] - boundaries[0]),
                                           6)

                self.vertical_position_of_mirror_center = round(
                    0.5 * (boundaries[3] + boundaries[2]), 6)
                self.horizontal_position_of_mirror_center = round(
                    0.5 * (boundaries[1] + boundaries[0]), 6)

                self.grooving_density_0 = optical_element._ruling * 1e-3

                self.receive_shape_specific_syned_data(optical_element)
            else:
                raise Exception(
                    "Syned Data not correct: Optical Element is not a Grating")
        else:
            raise Exception("Syned Data not correct: Empty Optical Element")

    def receive_shape_specific_syned_data(self, optical_element):
        raise NotImplementedError

    def check_data(self):
        super().check_data()

        congruence.checkStrictlyPositiveNumber(self.tangential_size,
                                               "Tangential Size")
        congruence.checkStrictlyPositiveNumber(self.sagittal_size,
                                               "Sagittal Size")

        if self.has_height_profile:
            congruence.checkFile(self.height_profile_data_file)

        congruence.checkPositiveNumber(self.diffraction_order,
                                       "Diffraction Order")
        congruence.checkStrictlyPositiveNumber(self.grooving_density_0,
                                               "Groove density")

    def setPreProcessorData(self, data):
        if data is not None:
            try:
                if not data.error_profile_data is None:
                    if data.error_profile_data.error_profile_data_file != SRWErrorProfileData.NONE:
                        self.height_profile_data_file = data.error_profile_data.error_profile_data_file
                        self.height_profile_data_file_dimension = 1
                        self.has_height_profile = 1

                        self.set_HeightProfile()

                        changed = False

                        if self.sagittal_size > data.error_profile_data.error_profile_x_dim or \
                           self.tangential_size > data.error_profile_data.error_profile_y_dim:
                            changed = True

                        if changed:
                            if QMessageBox.information(
                                    self, "Confirm Modification",
                                    "Dimensions of this O.E. must be changed in order to ensure congruence with the error profile surface, accept?",
                                    QMessageBox.Yes
                                    | QMessageBox.No) == QMessageBox.Yes:
                                if self.sagittal_size > data.error_profile_data.error_profile_x_dim:
                                    self.sagittal_size = data.error_profile_data.error_profile_x_dim
                                if self.tangential_size > data.error_profile_data.error_profile_y_dim:
                                    self.tangential_size = data.error_profile_data.error_profile_y_dim

                                QMessageBox.information(
                                    self, "QMessageBox.information()",
                                    "Dimensions of this O.E. were changed",
                                    QMessageBox.Ok)
            except Exception as exception:
                QMessageBox.critical(self, "Error", str(exception),
                                     QMessageBox.Ok)

    def view_height_profile(self):
        pass
        try:
            dialog = ShowErrorProfileDialog(
                parent=self,
                file_name=self.height_profile_data_file,
                dimension=self.height_profile_data_file_dimension + 1)
            dialog.show()
        except Exception as exception:
            QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)
Exemple #3
0
class OWbm(XoppyWidget, WidgetDecorator):
    name = "BM"
    id = "orange.widgets.databm"
    description = "Bending Magnet Spectrum"
    icon = "icons/xoppy_bm.png"
    priority = 13
    category = ""
    keywords = ["xoppy", "bm"]

    inputs = WidgetDecorator.syned_input_data()

    TYPE_CALC = Setting(0)
    MACHINE_NAME = Setting("ESRF bending magnet")
    RB_CHOICE = Setting(0)
    MACHINE_R_M = Setting(25.0)
    BFIELD_T = Setting(0.8)
    BEAM_ENERGY_GEV = Setting(6.0)
    CURRENT_A = Setting(0.2)
    HOR_DIV_MRAD = Setting(1.0)
    VER_DIV = Setting(0)
    PHOT_ENERGY_MIN = Setting(100.0)
    PHOT_ENERGY_MAX = Setting(100000.0)
    NPOINTS = Setting(500)
    LOG_CHOICE = Setting(1)
    PSI_MRAD_PLOT = Setting(1.0)
    PSI_MIN = Setting(-1.0)
    PSI_MAX = Setting(1.0)
    PSI_NPOINTS = Setting(500)
    FILE_DUMP = Setting(0)

    def __init__(self):
        super().__init__(show_script_tab=True)

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "TYPE_CALC",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'Energy or Power spectra',
                         'Angular distribution (all wavelengths)',
                         'Angular distribution (one wavelength)',
                         '2D flux and power (angular,energy) distribution'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     callback=self.set_TYPE_CALC)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        self.id_MACHINE_NAME = box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MACHINE_NAME",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "RB_CHOICE",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Magnetic Radius', 'Magnetic Field'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_MACHINE_R_M = oasysgui.lineEdit(box1,
                                                self,
                                                "MACHINE_R_M",
                                                label=self.unitLabels()[idx],
                                                addSpace=False,
                                                valueType=float,
                                                orientation="horizontal",
                                                labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_BFIELD_T = oasysgui.lineEdit(box1,
                                             self,
                                             "BFIELD_T",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_BEAM_ENERGY_GEV = oasysgui.lineEdit(
            box1,
            self,
            "BEAM_ENERGY_GEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_CURRENT_A = oasysgui.lineEdit(box1,
                                              self,
                                              "CURRENT_A",
                                              label=self.unitLabels()[idx],
                                              addSpace=False,
                                              valueType=float,
                                              orientation="horizontal",
                                              labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HOR_DIV_MRAD",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "VER_DIV",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'Full (integrated in Psi)', 'At Psi=0',
                         'In [PsiMin,PsiMax]', 'At Psi=Psi_Min'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     callback=self.set_VER_DIV,
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOT_ENERGY_MIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOT_ENERGY_MAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "NPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "LOG_CHOICE",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Lin', 'Log'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=350)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PSI_MRAD_PLOT",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PSI_MIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PSI_MAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PSI_NPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 17
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "FILE_DUMP",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'YES (bm.spec)'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return [
            'Type of calculation', 'Machine name', 'B from:',
            'Machine Radius [m]', 'Magnetic Field [T]', 'Beam energy [GeV]',
            'Beam Current [A]', 'Horizontal div Theta [mrad]',
            'Psi (vertical div) for energy spectra', 'Min Photon Energy [eV]',
            'Max Photon Energy [eV]', 'Number of points',
            'Separation between energy points',
            'Max Psi[mrad] for angular plots', 'Psi min [mrad]',
            'Psi max [mrad]', 'Number of Psi points', 'Dump file'
        ]

    def unitFlags(self):
        return [
            'True', 'True', 'True', 'self.RB_CHOICE  ==  0',
            'self.RB_CHOICE  ==  1', 'True', 'True', 'True',
            'self.TYPE_CALC == 0', 'True', 'True', 'True',
            'self.TYPE_CALC == 0', 'True', 'self.VER_DIV  >=  2',
            'self.VER_DIV  ==  2', 'self.VER_DIV  ==  2', 'True'
        ]

    def set_TYPE_CALC(self):

        self.initializeTabs()
        if self.TYPE_CALC == 3:
            self.VER_DIV = 2

    def set_VER_DIV(self):
        if self.TYPE_CALC == 0: self.initializeTabs()

    def get_help_name(self):
        return 'bm'

    def check_fields(self):
        if self.RB_CHOICE == 0:
            self.MACHINE_R_M = congruence.checkStrictlyPositiveNumber(
                self.MACHINE_R_M, "Magnetic Radius")
        else:
            self.BFIELD_T = congruence.checkStrictlyPositiveNumber(
                self.BFIELD_T, "Magnetic Field")

        self.BEAM_ENERGY_GEV = congruence.checkStrictlyPositiveNumber(
            self.BEAM_ENERGY_GEV, "Beam Energy")
        self.CURRENT_A = congruence.checkStrictlyPositiveNumber(
            self.CURRENT_A, "Beam Current")
        self.HOR_DIV_MRAD = congruence.checkPositiveNumber(
            self.HOR_DIV_MRAD, "Horizontal div Theta")

        self.PHOT_ENERGY_MIN = congruence.checkPositiveNumber(
            self.PHOT_ENERGY_MIN, "Min Photon Energy")
        self.PHOT_ENERGY_MAX = congruence.checkStrictlyPositiveNumber(
            self.PHOT_ENERGY_MAX, "Max Photon Energy")
        congruence.checkLessThan(self.PHOT_ENERGY_MIN, self.PHOT_ENERGY_MAX,
                                 "Min Photon Energy", "Max Photon Energy")
        self.NPOINTS = congruence.checkStrictlyPositiveNumber(
            self.NPOINTS, "Number of Energy Points")

        self.PSI_MRAD_PLOT = congruence.checkNumber(
            self.PSI_MRAD_PLOT, "Max Psi for angular plots")

        if self.VER_DIV == 2:
            self.PSI_MIN = congruence.checkNumber(self.PSI_MIN,
                                                  "Min Photon Energy")
            self.PSI_MAX = congruence.checkNumber(self.PSI_MAX,
                                                  "Max Photon  Max")
            congruence.checkLessThan(self.PSI_MIN, self.PSI_MAX, "Psi Min",
                                     "Psi Max")
        elif self.VER_DIV == 3:
            self.PSI_MIN = congruence.checkNumber(self.PSI_MIN,
                                                  "Min Photon Energy")

    def plot_results(self, calculated_data, progressBarValue=80):
        if self.TYPE_CALC != 3:
            super().plot_results(calculated_data, progressBarValue)
            self.tabs.setCurrentIndex(len(self.getTitles()) - 1)
        elif not self.view_type == 0:
            if not calculated_data is None:
                self.view_type_combo.setEnabled(False)

                data = calculated_data.get_content("xoppy_data_3D")

                fm = data[0]
                a = data[1]
                energy_ev = data[2]

                try:
                    self.plot_data2D(fm,
                                     a,
                                     energy_ev,
                                     0,
                                     0,
                                     xtitle="Psi [mrad]",
                                     ytitle="Photon energy [eV]",
                                     title="Flux [photons/s/0.1%bw]")

                    self.plot_data2D(fm * codata.e * 1e3,
                                     a,
                                     energy_ev,
                                     1,
                                     1,
                                     xtitle="Psi [mrad]",
                                     ytitle="Photon energy [eV]",
                                     title="Spectral power [W/eV]")
                except Exception as e:
                    self.view_type_combo.setEnabled(True)

                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def do_xoppy_calculation(self):
        a6_T, fm, a, energy_ev = xoppy_calc_bm(
            TYPE_CALC=self.TYPE_CALC,
            MACHINE_NAME=self.MACHINE_NAME,
            RB_CHOICE=self.RB_CHOICE,
            MACHINE_R_M=self.MACHINE_R_M,
            BFIELD_T=self.BFIELD_T,
            BEAM_ENERGY_GEV=self.BEAM_ENERGY_GEV,
            CURRENT_A=self.CURRENT_A,
            HOR_DIV_MRAD=self.HOR_DIV_MRAD,
            VER_DIV=self.VER_DIV,
            PHOT_ENERGY_MIN=self.PHOT_ENERGY_MIN,
            PHOT_ENERGY_MAX=self.PHOT_ENERGY_MAX,
            NPOINTS=self.NPOINTS,
            LOG_CHOICE=self.LOG_CHOICE,
            PSI_MRAD_PLOT=self.PSI_MRAD_PLOT,
            PSI_MIN=self.PSI_MIN,
            PSI_MAX=self.PSI_MAX,
            PSI_NPOINTS=self.PSI_NPOINTS,
            FILE_DUMP=self.FILE_DUMP)

        # write python script in standard output
        dict_parameters = {
            "TYPE_CALC": self.TYPE_CALC,
            "MACHINE_NAME": self.MACHINE_NAME,
            "RB_CHOICE": self.RB_CHOICE,
            "MACHINE_R_M": self.MACHINE_R_M,
            "BFIELD_T": self.BFIELD_T,
            "BEAM_ENERGY_GEV": self.BEAM_ENERGY_GEV,
            "CURRENT_A": self.CURRENT_A,
            "HOR_DIV_MRAD": self.HOR_DIV_MRAD,
            "VER_DIV": self.VER_DIV,
            "PHOT_ENERGY_MIN": self.PHOT_ENERGY_MIN,
            "PHOT_ENERGY_MAX": self.PHOT_ENERGY_MAX,
            "NPOINTS": self.NPOINTS,
            "LOG_CHOICE": self.LOG_CHOICE,
            "PSI_MRAD_PLOT": self.PSI_MRAD_PLOT,
            "PSI_MIN": self.PSI_MIN,
            "PSI_MAX": self.PSI_MAX,
            "PSI_NPOINTS": self.PSI_NPOINTS,
            "FILE_DUMP": self.FILE_DUMP,
        }

        self.xoppy_script.set_code(
            self.script_template().format_map(dict_parameters))

        return a6_T, fm, a, energy_ev

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:bm)
#
from orangecontrib.xoppy.util.xoppy_bm_wiggler import xoppy_calc_bm

# TYPE_CALC: 
# 0: 'Energy or Power spectra'
# 1: 'Angular distribution (all wavelengths)'
# 2: 'Angular distribution (one wavelength)'
# 3: '2D flux and power (angular,energy) distribution'
#
a6_T, fm, a, energy_ev =  xoppy_calc_bm(
    TYPE_CALC={TYPE_CALC},
    MACHINE_NAME="{MACHINE_NAME}",
    RB_CHOICE={RB_CHOICE},
    MACHINE_R_M={MACHINE_R_M},
    BFIELD_T={BFIELD_T},
    BEAM_ENERGY_GEV={BEAM_ENERGY_GEV},
    CURRENT_A={CURRENT_A},
    HOR_DIV_MRAD={HOR_DIV_MRAD},
    VER_DIV={VER_DIV},
    PHOT_ENERGY_MIN={PHOT_ENERGY_MIN},
    PHOT_ENERGY_MAX={PHOT_ENERGY_MAX},
    NPOINTS={NPOINTS},
    LOG_CHOICE={LOG_CHOICE},
    PSI_MRAD_PLOT={PSI_MRAD_PLOT},
    PSI_MIN={PSI_MIN},
    PSI_MAX={PSI_MAX},
    PSI_NPOINTS={PSI_NPOINTS},
    FILE_DUMP=True) # writes output to bm.spec
#
# end script
#
"""

    def add_specific_content_to_calculated_data(self, calculated_data):
        calculated_data.add_content("is_log_plot", self.LOG_CHOICE)
        calculated_data.add_content("calculation_type", self.TYPE_CALC)
        calculated_data.add_content("psi", self.VER_DIV)

    def get_data_exchange_widget_name(self):
        return "BM"

    def extract_data_from_xoppy_output(self, calculation_output):
        data, fm, a, energy_ev = calculation_output

        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())
        calculated_data.add_content("xoppy_data", data)
        calculated_data.add_content("xoppy_data_3D", [fm, a, energy_ev])

        return calculated_data

    def getTitles(self):
        if self.TYPE_CALC == 0:
            return [
                'E/Ec', 'Flux s-pol/Flux total', 'Flux p-pol/Flux total',
                'Flux', 'Spectral Power'
            ]
        elif self.TYPE_CALC == 1:
            return [
                "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol", "Spectral Power"
            ]
        elif self.TYPE_CALC == 2:
            return [
                "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol", "Flux",
                "Spectral Power"
            ]
        elif self.TYPE_CALC == 3:
            return [
                "2D Flux (angle,energy)", "2D Spectral Power (angle,energy)"
            ]

    def getXTitles(self):
        if self.TYPE_CALC == 0:
            return [
                "Energy [eV]", "Energy [eV]", "Energy [eV]", "Energy [eV]",
                "Energy [eV]"
            ]
        elif self.TYPE_CALC == 1:
            return [
                "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]",
                "Psi [mrad]"
            ]
        elif self.TYPE_CALC == 2:
            return [
                "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]",
                "Psi [mrad]", "Psi [mrad]"
            ]
        elif self.TYPE_CALC == 3:
            return []

    def getYTitles(self):
        if self.TYPE_CALC == 0:
            if self.VER_DIV == 0:
                return [
                    'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total',
                    'Flux [Phot/sec/0.1%bw]', 'Power [Watts/eV]'
                ]
            elif self.VER_DIV == 1:
                return [
                    'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total',
                    'Flux [Phot/sec/0.1%bw/mrad(Psi)]',
                    'Power[Watts/eV/mrad(Psi)]'
                ]
            elif self.VER_DIV == 2:
                return [
                    'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total',
                    'Flux [Phot/sec/0.1%bw]', 'Power [Watts/eV]'
                ]
            elif self.VER_DIV == 3:
                return [
                    'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total',
                    'Flux [Phot/sec/0.1%bw/mrad(Psi)]',
                    'Power [Watts/eV/mrad(Psi)]'
                ]
        elif self.TYPE_CALC == 1:
            return [
                "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol",
                "Power [Watts/mrad(Psi)]"
            ]
        elif self.TYPE_CALC == 2:
            return [
                "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol",
                "Flux [Phot/sec/0.1%bw/mrad(Psi)]", "Power [Watts/mrad(Psi)]"
            ]
        elif self.TYPE_CALC == 3:
            return []

    def getVariablesToPlot(self):
        if self.TYPE_CALC == 0:
            return [(0, 2), (0, 3), (0, 4), (0, 5), (0, 6)]
        elif self.TYPE_CALC == 1:
            return [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]
        elif self.TYPE_CALC == 2:
            return [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)]
        elif self.TYPE_CALC == 3:
            return []

    def getLogPlot(self):
        if self.TYPE_CALC == 0:
            return [(True, False), (True, False), (True, False), (True, True),
                    (True, True)]
        elif self.TYPE_CALC == 1:
            return [(False, False), (False, False), (False, False),
                    (False, False), (False, False)]
        elif self.TYPE_CALC == 2:
            return [(False, False), (False, False), (False, False),
                    (False, False), (False, False), (False, False)]
        elif self.TYPE_CALC == 3:
            return []

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data is None:
                if not data._light_source is None and isinstance(
                        data._light_source._magnetic_structure, BendingMagnet):
                    light_source = data._light_source

                    self.MACHINE_NAME = light_source._name
                    self.BEAM_ENERGY_GEV = light_source._electron_beam._energy_in_GeV
                    self.CURRENT_A = light_source._electron_beam._current
                    self.BFIELD_T = light_source._magnetic_structure._magnetic_field
                    self.MACHINE_R_M = light_source._magnetic_structure._radius

                    self.set_enabled(False)
                else:
                    self.set_enabled(True)
                    raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)

    def set_enabled(self, value):
        if value == True:
            self.id_MACHINE_NAME.setEnabled(True)
            self.id_BEAM_ENERGY_GEV.setEnabled(True)
            self.id_CURRENT_A.setEnabled(True)
            self.id_BFIELD_T.setEnabled(True)
            self.id_MACHINE_R_M.setEnabled(True)
        else:
            self.id_MACHINE_NAME.setEnabled(False)
            self.id_BEAM_ENERGY_GEV.setEnabled(False)
            self.id_CURRENT_A.setEnabled(False)
            self.id_BFIELD_T.setEnabled(False)
            self.id_MACHINE_R_M.setEnabled(False)
Exemple #4
0
class OWxwiggler(XoppyWidget,WidgetDecorator):
    name = "WIGGLER"
    id = "orange.widgets.dataxwiggler"
    description = "Wiggler Spectrum (Full Emission)"
    icon = "icons/xoppy_xwiggler.png"
    priority = 9
    category = ""
    keywords = ["xoppy", "xwiggler"]

    FIELD = Setting(0)
    NPERIODS = Setting(12)
    ULAMBDA = Setting(0.125)
    K = Setting(14.0)
    ENERGY = Setting(6.04)
    PHOT_ENERGY_MIN = Setting(100.0)
    PHOT_ENERGY_MAX = Setting(100100.0)
    NPOINTS = Setting(100)
    NTRAJPOINTS = Setting(101)
    CURRENT = Setting(200.0)
    FILE = Setting("?")

    inputs = WidgetDecorator.syned_input_data()

    def __init__(self):
        super().__init__(show_script_tab=True)

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5)
        
        idx = -1
        
        #widget index 0 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_FIELD = gui.comboBox(box1, self, "FIELD",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['Sinusoidal', 'B from file', 'B from harmonics'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 1 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 2 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ULAMBDA = oasysgui.lineEdit(box1, self, "ULAMBDA",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 3 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_K = oasysgui.lineEdit(box1, self, "K",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 4 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ENERGY = oasysgui.lineEdit(box1, self, "ENERGY",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 5 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "PHOT_ENERGY_MIN",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 6 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "PHOT_ENERGY_MAX",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 7 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "NPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 

        
        #widget index 9 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "NTRAJPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 10 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_CURRENT = oasysgui.lineEdit(box1, self, "CURRENT",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 11 
        idx += 1 

        box1 = gui.widgetBox(box)

        file_box = oasysgui.widgetBox(box1, "", addSpace=False, orientation="horizontal", height=25)

        self.le_file = oasysgui.lineEdit(file_box, self, "FILE",
                                         label=self.unitLabels()[idx], addSpace=False, orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1) 

        gui.button(file_box, self, "...", callback=self.selectFile)

    def unitLabels(self):
         return ['Magnetic field: ','Number of periods','Wiggler period [m]','K value','Beam energy [GeV]',
                 'Min Photon Energy [eV]','Max Photon Energy [eV]','Number of energy points',
                 'Number of traj points per period','Electron Beam Current [mA]','File/Url with Magnetic Field']

    def unitFlags(self):
         return ['True','True','self.FIELD  !=  1','self.FIELD  ==  0','True',
                 'True','True','True',
                 'self.FIELD  !=  1','True','self.FIELD  !=  0']

    def selectFile(self):
        self.le_file.setText(oasysgui.selectFileFromDialog(self, self.FILE, "Open B File"))

    def get_help_name(self):
        return 'wiggler'

    def check_fields(self):
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(self.NPERIODS, "Number of Periods")
        self.ENERGY = congruence.checkStrictlyPositiveNumber(self.ENERGY, "Beam Energy")
        self.PHOT_ENERGY_MIN = congruence.checkPositiveNumber(self.PHOT_ENERGY_MIN, "Min Photon Energy")
        self.PHOT_ENERGY_MAX = congruence.checkStrictlyPositiveNumber(self.PHOT_ENERGY_MAX, "Max Photon Energy")
        congruence.checkLessThan(self.PHOT_ENERGY_MIN, self.PHOT_ENERGY_MAX, "Min Photon Energy", "Max Photon Energy")
        self.NPOINTS = congruence.checkStrictlyPositiveNumber(self.NPOINTS, "Number of Energy Points")
        self.CURRENT = congruence.checkStrictlyPositiveNumber(self.CURRENT, "Electron Beam Current")

        if self.FIELD == 0:
            self.ULAMBDA = congruence.checkStrictlyPositiveNumber(self.ULAMBDA, "Wiggler period")
            self.K = congruence.checkStrictlyPositiveNumber(self.K, "K")
            self.NTRAJPOINTS = congruence.checkStrictlyPositiveNumber(self.NTRAJPOINTS, "Number of traj points per period")
        elif self.FIELD == 1:
            self.ULAMBDA = congruence.checkStrictlyPositiveNumber(self.ULAMBDA, "Wiggler period")
            self.NTRAJPOINTS = congruence.checkStrictlyPositiveNumber(self.NTRAJPOINTS, "Number of traj points per period")
            congruence.checkUrl(self.FILE)
        elif self.FIELD == 2:
            congruence.checkUrl(self.FILE)


    def do_xoppy_calculation(self):
        e, f0, p0, cumulated_power =  xoppy_calc_wigg(
            FIELD=self.FIELD,
            NPERIODS=self.NPERIODS,
            ULAMBDA=self.ULAMBDA,
            K=self.K,
            ENERGY=self.ENERGY,
            PHOT_ENERGY_MIN=self.PHOT_ENERGY_MIN,
            PHOT_ENERGY_MAX=self.PHOT_ENERGY_MAX,
            NPOINTS=self.NPOINTS,
            NTRAJPOINTS=self.NTRAJPOINTS,
            CURRENT=self.CURRENT,
            FILE=self.FILE)

        # write python script in standard output
        dict_parameters = {
            "FIELD"           : self.FIELD,
            "NPERIODS"        : self.NPERIODS,
            "ULAMBDA"         : self.ULAMBDA,
            "K"               : self.K,
            "ENERGY"          : self.ENERGY,
            "PHOT_ENERGY_MIN" : self.PHOT_ENERGY_MIN,
            "PHOT_ENERGY_MAX" : self.PHOT_ENERGY_MAX,
            "NPOINTS"         : self.NPOINTS,
            "NTRAJPOINTS"     : self.NTRAJPOINTS,
            "CURRENT"         : self.CURRENT,
            "FILE"            : self.FILE,
            }
        # print(self.script_template().format_map(dict_parameters))


        # print(self.script_template().format_map(dict_parameters))

        self.xoppy_script.set_code(self.script_template().format_map(dict_parameters))




        return e, f0, p0 , cumulated_power

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:wiggler)
#
from orangecontrib.xoppy.util.xoppy_bm_wiggler import xoppy_calc_wigg
energy, flux, spectral_power, cumulated_power =  xoppy_calc_wigg(
    FIELD={FIELD},
    NPERIODS={NPERIODS},
    ULAMBDA={ULAMBDA},
    K={K},
    ENERGY={ENERGY},
    PHOT_ENERGY_MIN={PHOT_ENERGY_MIN},
    PHOT_ENERGY_MAX={PHOT_ENERGY_MAX},
    NPOINTS={NPOINTS},
    NTRAJPOINTS={NTRAJPOINTS},
    CURRENT={CURRENT},
    FILE="{FILE}")

# example plot
from srxraylib.plot.gol import plot
plot(energy,flux,ytitle="Flux [photons/s/o.1%bw]",xtitle="Poton energy [eV]",title="Wiggler Flux",
    xlog=True,ylog=True,show=False)
plot(energy,spectral_power,ytitle="Power [W/eV]",xtitle="Poton energy [eV]",title="Wiggler Spectral Power",
    xlog=True,ylog=True,show=False)
plot(energy,cumulated_power,ytitle="Cumulated Power [W]",xtitle="Poton energy [eV]",title="Wiggler Cumulated Power",
    xlog=False,ylog=False,show=True)
#
# end script
#
"""



    def extract_data_from_xoppy_output(self, calculation_output):
        e, f, sp, cumulated_power = calculation_output

        data = numpy.zeros((len(e), 4))
        data[:,0] = numpy.array(e)
        data[:,1] = numpy.array(f)
        data[:,2] = numpy.array(sp)
        data[:,3] = numpy.array(cumulated_power)

        calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name())
        calculated_data.add_content("xoppy_data", data)

        return calculated_data


    def get_data_exchange_widget_name(self):
        return "XWIGGLER"

    def getTitles(self):
        return ['Flux', 'Spectral Power', 'Cumulated Power']

    def getXTitles(self):
        return ["Energy [eV]", "Energy [eV]", "Energy [eV]"]

    def getYTitles(self):
        return ["Flux [Phot/sec/0.1%bw]", "Spectral Power [W/eV]", "Cumulated Power [W]"]

    def getLogPlot(self):
        return [(True, True), (True, True), (False, False)]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2), (0,3)]

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(data._light_source._magnetic_structure, synedid.InsertionDevice):
                light_source = data._light_source

                self.NPERIODS = int(light_source._magnetic_structure._number_of_periods)
                self.ENERGY = light_source._electron_beam._energy_in_GeV
                self.CURRENT = 1e3*light_source._electron_beam._current
                self.ULAMBDA = light_source._magnetic_structure._period_length
                self.K = light_source._magnetic_structure._K_vertical
                self.FIELD = 0

                self.set_enabled(False)

            else:
                self.set_enabled(True)
        else:
            self.set_enabled(True)

    def set_enabled(self,value):
        if value == True:
                self.id_NPERIODS.setEnabled(True)
                self.id_ENERGY.setEnabled(True)
                self.id_CURRENT.setEnabled(True)
                self.id_ULAMBDA.setEnabled(True)
                self.id_K.setEnabled(True)
                self.id_FIELD.setEnabled(True)
        else:
                self.id_NPERIODS.setEnabled(False)
                self.id_ENERGY.setEnabled(False)
                self.id_CURRENT.setEnabled(False)
                self.id_ULAMBDA.setEnabled(False)
                self.id_K.setEnabled(False)
                self.id_FIELD.setEnabled(False)
Exemple #5
0
class OWSRWMirror(OWSRWOpticalElement):

    tangential_size                    = Setting(1.2)
    sagittal_size                      = Setting(0.01)
    horizontal_position_of_mirror_center = Setting(0.0)
    vertical_position_of_mirror_center = Setting(0.0)

    add_acceptance_slit = Setting(0)

    has_height_profile = Setting(0)
    height_profile_data_file           = Setting("mirror.dat")
    height_profile_data_file_dimension = Setting(0)
    height_amplification_coefficient   = Setting(1.0)

    has_reflectivity = Setting(0)

    reflectivity_value = Setting(0.95)
    reflectivity_data_file = Setting("reflectivity.dat")

    reflectivity_energies_number = Setting(100)
    reflectivity_angles_number = Setting(100)
    reflectivity_components_number = Setting(0)

    reflectivity_energy_start = Setting(100.0)
    reflectivity_energy_end = Setting(10000.0)
    reflectivity_energy_scale_type = Setting(0)

    reflectivity_angle_start = Setting(0.001)
    reflectivity_angle_end = Setting(0.005)
    reflectivity_angle_scale_type = Setting(0)

    inputs = [("SRWData", SRWData, "set_input"),
              ("Trigger", TriggerOut, "propagate_new_wavefront"),
              ("PreProcessor Data #1", SRWPreProcessorData, "setPreProcessorData"),
              ("PreProcessor Data #2", SRWPreProcessorData, "setPreProcessorData"),
              WidgetDecorator.syned_input_data()[0]]

    def __init__(self):
        super().__init__(azimuth_hor_vert=True)

    def draw_specific_box(self):

        tabs_mirr = oasysgui.tabWidget(self.tab_bas)

        tab_mirr = oasysgui.createTabPage(tabs_mirr, "Mirror")
        tab_errp = oasysgui.createTabPage(tabs_mirr, "Error Profile")
        tab_refl = oasysgui.createTabPage(tabs_mirr, "Reflectivity")

        self.mirror_box = oasysgui.widgetBox(tab_mirr, "", addSpace=False, orientation="vertical")

        oasysgui.lineEdit(self.mirror_box, self, "tangential_size", "Tangential Size [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.mirror_box, self, "sagittal_size", "Sagittal_Size [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.mirror_box, self, "horizontal_position_of_mirror_center", "Horizontal position of mirror center [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.mirror_box, self, "vertical_position_of_mirror_center", "Vertical position of mirror center [m]", labelWidth=260, valueType=float, orientation="horizontal")

        gui.comboBox(self.mirror_box, self, "add_acceptance_slit", label="Add Acceptance Slit",
                     items=["No", "Yes"], labelWidth=300,
                     sendSelectedValue=False, orientation="horizontal")

        gui.separator(self.mirror_box)

        self.error_box = oasysgui.widgetBox(tab_errp, "", addSpace=False, orientation="vertical")

        gui.comboBox(self.error_box, self, "has_height_profile", label="Use Height Error Profile",
                     items=["No", "Yes"], labelWidth=300,
                     sendSelectedValue=False, orientation="horizontal", callback=self.set_HeightProfile)

        gui.separator(self.error_box)

        self.height_profile_box_1 = oasysgui.widgetBox(self.error_box, "", addSpace=False, orientation="vertical", height=110)
        self.height_profile_box_2 = oasysgui.widgetBox(self.error_box, "", addSpace=False, orientation="vertical", height=110)

        file_box =  oasysgui.widgetBox(self.height_profile_box_2, "", addSpace=False, orientation="horizontal")

        self.le_height_profile_data_file = oasysgui.lineEdit(file_box, self, "height_profile_data_file", "Height profile data file", labelWidth=155, valueType=str, orientation="horizontal")
        gui.button(file_box, self, "...", callback=self.selectHeightProfileDataFile)

        file_box_2 =  oasysgui.widgetBox(self.height_profile_box_2, "", addSpace=False, orientation="horizontal")

        gui.comboBox(file_box_2, self, "height_profile_data_file_dimension", label="Dimension",
                     items=["1", "2"], labelWidth=280,
                     sendSelectedValue=False, orientation="horizontal")

        gui.button(file_box_2, self, "View", callback=self.view_height_profile)

        oasysgui.lineEdit(self.height_profile_box_2, self, "height_amplification_coefficient", "Height Amplification Coefficient", labelWidth=260, valueType=float, orientation="horizontal")

        self.set_HeightProfile()

        self.reflectivity_box = oasysgui.widgetBox(tab_refl, "", addSpace=False, orientation="vertical")

        gui.comboBox(self.reflectivity_box, self, "has_reflectivity", label="Use Reflectivity",
                     items=["No", "Single Value", "R vs E vs \u03b1 (vs \u03c3/\u03c0)"], labelWidth=200,
                     sendSelectedValue=False, orientation="horizontal", callback=self.set_Reflectivity)

        gui.separator(self.reflectivity_box)

        self.reflectivity_box_1 = oasysgui.widgetBox(self.reflectivity_box, "", addSpace=False, orientation="vertical", height=200)

        self.reflectivity_box_2 = oasysgui.widgetBox(self.reflectivity_box, "", addSpace=False, orientation="vertical", height=200)

        oasysgui.lineEdit(self.reflectivity_box_2, self, "reflectivity_value", "Reflectivity Value", labelWidth=260, valueType=float, orientation="horizontal")

        self.reflectivity_box_3 = oasysgui.widgetBox(self.reflectivity_box, "", addSpace=False, orientation="vertical", height=270)

        file_box =  oasysgui.widgetBox(self.reflectivity_box_3, "", addSpace=False, orientation="horizontal")

        self.le_reflectivity_data_file = oasysgui.lineEdit(file_box, self, "reflectivity_data_file", "Reflectivity data file", labelWidth=185, valueType=str, orientation="horizontal")
        gui.button(file_box, self, "...", callback=self.selectReflectivityDataFile)

        gui.separator(self.reflectivity_box_3)

        oasysgui.lineEdit(self.reflectivity_box_3, self, "reflectivity_energies_number", "Number of Energy Values", labelWidth=260, valueType=int, orientation="horizontal")

        energy_box = oasysgui.widgetBox(self.reflectivity_box_3, "", addSpace=False, orientation="horizontal")

        oasysgui.lineEdit(energy_box, self, "reflectivity_energy_start", "Energy Values [eV]: Initial", labelWidth=160, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(energy_box, self, "reflectivity_energy_end", "Final", labelWidth=50, valueType=float, orientation="horizontal")

        gui.comboBox(self.reflectivity_box_3, self, "reflectivity_energy_scale_type", label="Energy Scale Type",
                     items=["Linear", "Logarithmic"], labelWidth=250,
                     sendSelectedValue=False, orientation="horizontal")

        gui.separator(self.reflectivity_box_3)

        oasysgui.lineEdit(self.reflectivity_box_3, self, "reflectivity_angles_number", "Number of Grazing Angle Values", labelWidth=260, valueType=int, orientation="horizontal")

        angle_box = oasysgui.widgetBox(self.reflectivity_box_3, "", addSpace=False, orientation="horizontal")

        oasysgui.lineEdit(angle_box, self, "reflectivity_angle_start", "Gr. Ang. Values [rad]: Initial", labelWidth=170, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(angle_box, self, "reflectivity_angle_end", "Final", labelWidth=40, valueType=float, orientation="horizontal")

        gui.comboBox(self.reflectivity_box_3, self, "reflectivity_angle_scale_type", label="Grazing Angle Scale Type",
                     items=["Linear", "Logarithmic"], labelWidth=250,
                     sendSelectedValue=False, orientation="horizontal")

        gui.separator(self.reflectivity_box_3)

        gui.comboBox(self.reflectivity_box_3, self, "reflectivity_components_number", label="Polarization",
                     items=["Total", "\u03c3/\u03c0"], labelWidth=280,
                     sendSelectedValue=False, orientation="horizontal")


        self.set_Reflectivity()

    def selectHeightProfileDataFile(self):
        self.le_height_profile_data_file.setText(oasysgui.selectFileFromDialog(self, self.height_profile_data_file, "Height profile data file"))

    def selectReflectivityDataFile(self):
        self.le_reflectivity_data_file.setText(oasysgui.selectFileFromDialog(self, self.reflectivity_data_file, "Reflectivity data file"))

    def set_HeightProfile(self):
        self.height_profile_box_1.setVisible(self.has_height_profile==0)
        self.height_profile_box_2.setVisible(self.has_height_profile==1)

    def set_Reflectivity(self):
        self.reflectivity_box_1.setVisible(self.has_reflectivity==0)
        self.reflectivity_box_2.setVisible(self.has_reflectivity==1)
        self.reflectivity_box_3.setVisible(self.has_reflectivity==2)

    def get_optical_element(self):
        
        mirror = self.get_mirror_instance()

        mirror.tangential_size=self.tangential_size
        mirror.sagittal_size=self.sagittal_size
        mirror.grazing_angle=numpy.radians(90-self.angle_radial)
        mirror.orientation_of_reflection_plane=self.orientation_azimuthal
        mirror.invert_tangent_component = self.invert_tangent_component == 1
        mirror.add_acceptance_slit=self.add_acceptance_slit == 1
        mirror.height_profile_data_file=self.height_profile_data_file if self.has_height_profile else None
        mirror.height_profile_data_file_dimension=self.height_profile_data_file_dimension + 1
        mirror.height_amplification_coefficient=self.height_amplification_coefficient

        if self.has_reflectivity == 1:
            mirror.set_reflectivity(reflectivity_data=self.reflectivity_value)
        elif self.has_reflectivity == 2:
            mirror.set_reflectivity(reflectivity_data=self.read_reflectivity_data_file(),
                                    energies_number=self.reflectivity_energies_number,
                                    angles_number=self.reflectivity_angles_number,
                                    components_number=self.reflectivity_components_number + 1,
                                    energy_start=self.reflectivity_energy_start,
                                    energy_end=self.reflectivity_energy_end,
                                    energy_scale_type=ScaleType.LINEAR if self.reflectivity_energy_scale_type==0 else ScaleType.LOGARITHMIC,
                                    angle_start=self.reflectivity_angle_start,
                                    angle_end=self.reflectivity_angle_end,
                                    angle_scale_type=ScaleType.LINEAR if self.reflectivity_angle_scale_type==0 else ScaleType.LOGARITHMIC)

        return mirror



    def read_reflectivity_data_file(self):
        return numpy.loadtxt(self.reflectivity_data_file).tolist()

    def get_mirror_instance(self):
        raise NotImplementedError()

    def receive_specific_syned_data(self, optical_element):
        if not optical_element is None:
            if isinstance(optical_element, Mirror):
                boundaries = optical_element._boundary_shape.get_boundaries()

                self.tangential_size=round(abs(boundaries[3] - boundaries[2]), 6)
                self.sagittal_size=round(abs(boundaries[1] - boundaries[0]), 6)

                self.vertical_position_of_mirror_center = round(0.5*(boundaries[3] + boundaries[2]), 6)
                self.horizontal_position_of_mirror_center = round(0.5*(boundaries[1] + boundaries[0]), 6)

                self.receive_shape_specific_syned_data(optical_element)
            else:
                raise Exception("Syned Data not correct: Optical Element is not a Mirror")
        else:
            raise Exception("Syned Data not correct: Empty Optical Element")

    def receive_shape_specific_syned_data(self, optical_element):
        raise NotImplementedError


    def check_data(self):
        super().check_data()

        congruence.checkStrictlyPositiveNumber(self.tangential_size, "Tangential Size")
        congruence.checkStrictlyPositiveNumber(self.sagittal_size, "Sagittal Size")
        
        if self.has_height_profile:
            congruence.checkFile(self.height_profile_data_file)

        if self.has_reflectivity == 1:
            congruence.checkStrictlyPositiveNumber(self.reflectivity_value, "Reflectivity Value")
        elif self.has_reflectivity == 2:
            congruence.checkFile(self.reflectivity_data_file)

            congruence.checkStrictlyPositiveNumber(self.reflectivity_energies_number, "Number of Energy Values")
            congruence.checkStrictlyPositiveNumber(self.reflectivity_energy_start, "Initial Energy Value")
            congruence.checkStrictlyPositiveNumber(self.reflectivity_energy_end, "Final Energy Value")
            congruence.checkGreaterOrEqualThan(self.reflectivity_energy_end, self.reflectivity_energy_start, "Final Energy Value", "Initial Energy Value")

            congruence.checkStrictlyPositiveNumber(self.reflectivity_angles_number, "Number of Grazing Angle Values")
            congruence.checkStrictlyPositiveNumber(self.reflectivity_angle_start, "Initial Grazing Angle Value")
            congruence.checkStrictlyPositiveNumber(self.reflectivity_angle_end, "Final Grazing Angle Value")
            congruence.checkGreaterOrEqualThan(self.reflectivity_angle_end, self.reflectivity_angle_start, "Final Grazing Angle Value", "Initial Grazing Angle Value")

    def setPreProcessorData(self, data):
        if data is not None:
            try:
                if not data.error_profile_data is None:
                    if data.error_profile_data.error_profile_data_file != SRWErrorProfileData.NONE:
                        self.height_profile_data_file = data.error_profile_data.error_profile_data_file
                        self.height_profile_data_file_dimension = 1
                        self.has_height_profile = 1
        
                        self.set_HeightProfile()
        
                        changed = False
        
                        if self.sagittal_size > data.error_profile_data.error_profile_x_dim or \
                           self.tangential_size > data.error_profile_data.error_profile_y_dim:
                            changed = True
        
                        if changed:
                            if QMessageBox.information(self, "Confirm Modification",
                                                          "Dimensions of this O.E. must be changed in order to ensure congruence with the error profile surface, accept?",
                                                          QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
                                if self.sagittal_size > data.error_profile_data.error_profile_x_dim:
                                    self.sagittal_size = data.error_profile_data.error_profile_x_dim
                                if self.tangential_size > data.error_profile_data.error_profile_y_dim:
                                    self.tangential_size = data.error_profile_data.error_profile_y_dim
        
                                QMessageBox.information(self, "QMessageBox.information()",
                                                              "Dimensions of this O.E. were changed",
                                                              QMessageBox.Ok)
                if not data.reflectivity_data is None:    
                    if data.reflectivity_data.reflectivity_data_file != SRWReflectivityData.NONE:
                        self.has_reflectivity=2
                        self.reflectivity_data_file=data.reflectivity_data.reflectivity_data_file
                        self.reflectivity_energies_number=data.reflectivity_data.energies_number
                        self.reflectivity_angles_number=data.reflectivity_data.angles_number
                        self.reflectivity_components_number=data.reflectivity_data.components_number-1
                        self.reflectivity_energy_start=data.reflectivity_data.energy_start
                        self.reflectivity_energy_end=data.reflectivity_data.energy_end
                        self.reflectivity_energy_scale_type=0 if data.reflectivity_data.energy_scale_type==ScaleType.LINEAR else 1
                        self.reflectivity_angle_start=data.reflectivity_data.angle_start
                        self.reflectivity_angle_end=data.reflectivity_data.angle_end
                        self.reflectivity_angle_scale_type=0 if data.reflectivity_data.angle_scale_type==ScaleType.LINEAR else 1

                        self.set_Reflectivity()
                        
            except Exception as exception:
                QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)
    
    def view_height_profile(self):
        pass
        try:
            dialog = ShowErrorProfileDialog(parent=self,
                                            file_name=self.height_profile_data_file,
                                            dimension=self.height_profile_data_file_dimension+1)
            dialog.show()
        except Exception as exception:
            QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)
Exemple #6
0
class OWtc_slit(XoppyWidget):
    name = "TC-SLIT"
    id = "orange.widgets.data_tc_slit"
    description = "Undulator Tuning Curves (Flux on a slit)"
    icon = "icons/xoppy_xtc.png"
    priority = 6
    category = ""
    keywords = ["xoppy", "tc_slit"]

    USEEMITTANCES = Setting(1)
    ELECTRONENERGY = Setting(6.037)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(4.99e-05)
    ELECTRONBEAMSIZEV = Setting(3.45e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(0.000107)
    ELECTRONBEAMDIVERGENCEV = Setting(1.16e-06)
    PERIODID = Setting(0.042)
    NPERIODS = Setting(38)
    DISTANCE = Setting(26.0)
    GAPH = Setting(0.00258)
    GAPV = Setting(0.00195)
    KMIN = Setting(0.001)
    KMAX = Setting(3.0)
    KPOINTS = Setting(10)
    HARMONICS = Setting("1")  # sequence of harmonics, separated by ","
    METHOD = Setting(2)

    inputs = WidgetDecorator.syned_input_data()

    def __init__(self):
        super().__init__(show_script_tab=True)

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1
        #
        #
        #

        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "USEEMITTANCES",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGY",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGYSPREAD",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONCURRENT",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1,
                                             self,
                                             "PERIODID",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1,
                                             self,
                                             "NPERIODS",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=int,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "DISTANCE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPH",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPV",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "KMIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KMAX = oasysgui.lineEdit(box1,
                                         self,
                                         "KMAX",
                                         label=self.unitLabels()[idx],
                                         addSpace=False,
                                         valueType=float,
                                         orientation="horizontal",
                                         labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "KPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        # TODO: add validator
        oasysgui.lineEdit(box1,
                          self,
                          "HARMONICS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=str,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "METHOD",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['US', 'URGENT', 'SRW'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return [
            "Use emittances", "Electron Energy [GeV]",
            "Electron Energy Spread", "Electron Current [A]",
            "Electron Beam Size H [m]", "Electron Beam Size V [m]",
            "Electron Beam Divergence H [rad]",
            "Electron Beam Divergence V [rad]", "Period ID [m]",
            "Number of periods", "Distance to slit [m]", "Slit gap H [m]",
            "Slit gap V [m]", "K Min", "K Max", "Number of K Points",
            "harmonics (e.g: 1,3)", "calculation code"
        ]

    def unitFlags(self):
        return [
            "True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1",
            "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1",
            "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True",
            "True", "True", "True", "True", "True", "True", "True", "True",
            "True"
        ]

    def get_help_name(self):
        return 'tc_slit'

    def check_fields(self):
        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1:
            self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(
                self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")
        self.PERIODID = congruence.checkStrictlyPositiveNumber(
            self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(
            self.NPERIODS, "Number of Periods")
        self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE,
                                                       "Distance to slit")
        self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
        self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
        self.KMIN = congruence.checkPositiveNumber(self.KMIN, "K Min")
        self.KMAX = congruence.checkStrictlyPositiveNumber(self.KMAX, "K Max")
        congruence.checkLessThan(self.KMIN, self.KMAX, "K Min", "K Max")
        self.KPOINTS = congruence.checkStrictlyPositiveNumber(
            self.KPOINTS, "Number of K Points")
        # self.HARMONICS = congruence.checkStrictlyPositiveNumber(self.HARMONIX, "Higher harmonic")

    def do_xoppy_calculation(self):
        return self.xoppy_calc_tc_slit()

    def extract_data_from_xoppy_output(self, calculation_output):

        K_scan, harmonics, P_scan, energy_values_at_flux_peak, flux_values = calculation_output

        harmonics_data = []

        for ih in range(len(harmonics)):
            harmonic_number = int(harmonics[ih])
            harmonics_data.append([harmonic_number, None])

            data = numpy.zeros((K_scan.size, 5))
            data[:, 0] = numpy.array(energy_values_at_flux_peak[:, ih])
            data[:, 1] = numpy.array(flux_values[:, ih])
            data[:, 2] = numpy.array(flux_values[:, ih]) * codata.e * 1e3
            data[:, 3] = numpy.array(K_scan)
            data[:, 4] = numpy.array(P_scan)

            harmonics_data[ih][1] = data

        #send exchange
        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())

        try:
            calculated_data.add_content("xoppy_data_harmonics", harmonics_data)
            calculated_data.add_content("plot_x_col", 1)
            calculated_data.add_content("plot_y_col", 2)
        except:
            pass
        try:
            calculated_data.add_content("labels", [
                "Photon energy [eV]", "Flux [photons/s/0.1%bw]", "Ky",
                "Power [W]"
            ])
        except:
            pass

        return calculated_data

    def plot_histo(self,
                   x,
                   y,
                   progressBarValue,
                   tabs_canvas_index,
                   plot_canvas_index,
                   title="",
                   xtitle="",
                   ytitle="",
                   log_x=False,
                   log_y=False,
                   harmonic=1,
                   color='blue',
                   control=True):
        h_title = "Harmonic " + str(harmonic)

        hex_r = hex(min(255, 128 + harmonic * 10))[2:].upper()
        hex_g = hex(min(255, 20 + harmonic * 15))[2:].upper()
        hex_b = hex(min(255, harmonic * 10))[2:].upper()
        if len(hex_r) == 1: hex_r = "0" + hex_r
        if len(hex_g) == 1: hex_g = "0" + hex_g
        if len(hex_b) == 1: hex_b = "0" + hex_b

        super().plot_histo(x,
                           y,
                           progressBarValue,
                           tabs_canvas_index,
                           plot_canvas_index,
                           h_title,
                           xtitle,
                           ytitle,
                           log_x,
                           log_y,
                           color="#" + hex_r + hex_g + hex_b,
                           replace=False,
                           control=control)

        self.plot_canvas[plot_canvas_index].setGraphTitle(title)
        self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True)
        self.plot_canvas[plot_canvas_index].setDefaultPlotPoints(True)

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:
                self.view_type_combo.setEnabled(False)

                xoppy_data_harmonics = calculated_data.get_content(
                    "xoppy_data_harmonics")

                titles = self.getTitles()
                xtitles = self.getXTitles()
                ytitles = self.getYTitles()

                progress_bar_step = (100 - progressBarValue) / len(titles)

                for index in range(0, len(titles)):
                    x_index, y_index = self.getVariablesToPlot()[index]
                    log_x, log_y = self.getLogPlot()[index]

                    if not self.plot_canvas[index] is None:
                        self.plot_canvas[index].clear()

                    try:
                        for h_index in range(0, len(xoppy_data_harmonics)):

                            self.plot_histo(
                                xoppy_data_harmonics[h_index][1][:, x_index],
                                xoppy_data_harmonics[h_index][1][:, y_index],
                                progressBarValue +
                                ((index + 1) * progress_bar_step),
                                tabs_canvas_index=index,
                                plot_canvas_index=index,
                                title=titles[index],
                                xtitle=xtitles[index],
                                ytitle=ytitles[index],
                                log_x=log_x,
                                log_y=log_y,
                                harmonic=xoppy_data_harmonics[h_index][0],
                                control=True)

                        self.plot_canvas[index].addCurve(
                            numpy.zeros(1),
                            numpy.array([
                                max(xoppy_data_harmonics[h_index][1][:,
                                                                     y_index])
                            ]),
                            "Click on curve to highlight it",
                            xlabel=xtitles[index],
                            ylabel=ytitles[index],
                            symbol='',
                            color='white')

                    except Exception as e:
                        self.view_type_combo.setEnabled(True)

                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                self.view_type_combo.setEnabled(True)
                self.tabs.setCurrentIndex(0)
            else:
                raise Exception("Empty Data")

    def plot_histo(self,
                   x,
                   y,
                   progressBarValue,
                   tabs_canvas_index,
                   plot_canvas_index,
                   title="",
                   xtitle="",
                   ytitle="",
                   log_x=False,
                   log_y=False,
                   harmonic=1,
                   color='blue',
                   control=True):
        h_title = "Harmonic " + str(harmonic)

        hex_r = hex(min(255, 128 + harmonic * 10))[2:].upper()
        hex_g = hex(min(255, 20 + harmonic * 15))[2:].upper()
        hex_b = hex(min(255, harmonic * 10))[2:].upper()
        if len(hex_r) == 1: hex_r = "0" + hex_r
        if len(hex_g) == 1: hex_g = "0" + hex_g
        if len(hex_b) == 1: hex_b = "0" + hex_b

        super().plot_histo(x,
                           y,
                           progressBarValue,
                           tabs_canvas_index,
                           plot_canvas_index,
                           h_title,
                           xtitle,
                           ytitle,
                           log_x,
                           log_y,
                           color="#" + hex_r + hex_g + hex_b,
                           replace=False,
                           control=control)

        self.plot_canvas[plot_canvas_index].setGraphTitle(title)
        self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True)
        self.plot_canvas[plot_canvas_index].setDefaultPlotPoints(True)

    def get_data_exchange_widget_name(self):
        return "TC_SLIT"

    def getTitles(self):
        return [
            "Flux on slit", "Spectral power on slit", "Kv",
            "Total power on slit"
        ]

    def getXTitles(self):
        return ["Energy (eV)", "Energy (eV)", "Energy (eV)", "Kv"]

    def getYTitles(self):
        return [
            "Flux (photons/s/0.1%bw)", "Spectral power (W/eV)", "Kv",
            "Total power (W)"
        ]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2), (0, 3), (3, 4)]

    def getLogPlot(self):
        return [(False, False), (False, False), (False, False), (False, False)]

    def xoppy_calc_tc_slit(self):

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

        if self.USEEMITTANCES:
            zero_emittance = False
        else:
            zero_emittance = True

        if self.METHOD == 0:
            code = "us"
        if self.METHOD == 1:
            code = "urgent"
        if self.METHOD == 2:
            code = "srw"

        harmonics = str(self.HARMONICS).split(",")  #[]
        # for i in range(self.HARMONICS+1):
        #     if i % 2 != 0: harmonics.append(i)

        K_scan, harmonics, power_array, energy_values_at_flux_peak, flux_values = srundplug.tuning_curves_on_slit(
            bl,
            Kmin=self.KMIN,
            Kmax=self.KMAX,
            Kpoints=self.KPOINTS,
            harmonics=harmonics,
            zero_emittance=zero_emittance,
            do_plot_peaks=False,
            code=code)

        if zero_emittance:
            print("\nNo emittance calculation")

        print("Done")

        # write python script in standard output
        dict_parameters = {
            'ElectronBeamDivergenceH': self.ELECTRONBEAMDIVERGENCEH,
            'ElectronBeamDivergenceV': self.ELECTRONBEAMDIVERGENCEV,
            'ElectronBeamSizeH': self.ELECTRONBEAMSIZEH,
            'ElectronBeamSizeV': self.ELECTRONBEAMSIZEV,
            'ElectronCurrent': self.ELECTRONCURRENT,
            'ElectronEnergy': self.ELECTRONENERGY,
            'ElectronEnergySpread': self.ELECTRONENERGYSPREAD,
            'NPeriods': self.NPERIODS,
            'PeriodID': self.PERIODID,
            'distance': self.DISTANCE,
            'gapH': self.GAPH,
            'gapV': self.GAPV,
            'gapHcenter': 0.0,
            'gapVcenter': 0.0,
            'HARMONICS': self.HARMONICS,
            'Kmin': self.KMIN,
            'Kmax': self.KMAX,
            'Kpoints': self.KPOINTS,
            'harmonics': harmonics,
            'zero_emittance': zero_emittance,
            'do_plot_peaks': False,
            'code': code,
        }

        self.xoppy_script.set_code(
            self.script_template().format_map(dict_parameters))

        return K_scan, harmonics, power_array, energy_values_at_flux_peak, flux_values

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:tc_slit)
#
from collections import OrderedDict
from orangecontrib.xoppy.util import srundplug


bl = OrderedDict()
bl['ElectronBeamDivergenceH'] = {ElectronBeamDivergenceH}
bl['ElectronBeamDivergenceV'] = {ElectronBeamDivergenceV}
bl['ElectronBeamSizeH']       = {ElectronBeamSizeH}
bl['ElectronBeamSizeV']       = {ElectronBeamSizeV}
bl['ElectronCurrent']         = {ElectronCurrent}
bl['ElectronEnergy']          = {ElectronEnergy}
bl['ElectronEnergySpread']    = {ElectronEnergySpread}
bl['NPeriods']                = {NPeriods}
bl['PeriodID']                = {PeriodID}
bl['distance']                = {distance}
bl['gapH']                    = {gapH}
bl['gapV']                    = {gapV}
bl['gapHcenter']              = 0.0
bl['gapVcenter']              = 0.0

harmonics = "{HARMONICS}".split(",")

K_scan,harmonics,power_array, energy_values_at_flux_peak,flux_values = srundplug.tuning_curves_on_slit(bl,
    Kmin={Kmin},
    Kmax={Kmax},
    Kpoints={Kpoints},
    harmonics=harmonics,
    zero_emittance={zero_emittance},
    do_plot_peaks={do_plot_peaks},
    code="{code}")
      
from srxraylib.plot.gol import plot
plot(energy_values_at_flux_peak,flux_values,xtitle="Photon energy [eV]",ytitle="Flux on slit [photons/s/0.1%bw]")
              
#
# end script
#
"""

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KMAX = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):
        if value == True:
            self.id_ELECTRONENERGY.setEnabled(True)
            self.id_ELECTRONENERGYSPREAD.setEnabled(True)
            self.id_ELECTRONBEAMSIZEH.setEnabled(True)
            self.id_ELECTRONBEAMSIZEV.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
            self.id_ELECTRONCURRENT.setEnabled(True)
            self.id_PERIODID.setEnabled(True)
            self.id_NPERIODS.setEnabled(True)
            self.id_KMAX.setEnabled(True)
        else:
            self.id_ELECTRONENERGY.setEnabled(False)
            self.id_ELECTRONENERGYSPREAD.setEnabled(False)
            self.id_ELECTRONBEAMSIZEH.setEnabled(False)
            self.id_ELECTRONBEAMSIZEV.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
            self.id_ELECTRONCURRENT.setEnabled(False)
            self.id_PERIODID.setEnabled(False)
            self.id_NPERIODS.setEnabled(False)
            self.id_KMAX.setEnabled(False)
Exemple #7
0
class OWtcap(XoppyWidget):
    name = "Aperture Flux TC"
    id = "orange.widgets.datatcap"
    description = "On-axis Aperture Flux Undulator Tuning Curves"
    icon = "icons/xoppy_xtc.png"
    priority = 8
    category = ""
    keywords = ["xoppy", "tcap"]

    #25 variables (minus one: TITLE removed)
    ENERGY = Setting(6.0)
    CURRENT = Setting(200.0)
    ENERGY_SPREAD = Setting(0.00138)
    SIGX = Setting(0.0148)
    SIGY = Setting(0.0037)
    SIGX1 = Setting(0.0029)
    SIGY1 = Setting(0.0015)
    PERIOD = Setting(2.8)
    NP = Setting(84)
    EMIN = Setting(3217.0)
    EMAX = Setting(11975.0)
    N = Setting(50)
    DISTANCE = Setting(30.0)
    XPS = Setting(1.0)
    YPS = Setting(1.0)
    XPC = Setting(0.0)
    YPC = Setting(0.0)
    HARMONIC_FROM = Setting(1)
    HARMONIC_TO = Setting(7)
    HARMONIC_STEP = Setting(2)
    HRED = Setting(0)
    HELICAL = Setting(0)
    NEKS = Setting(100)
    METHOD = Setting(0)
    BSL = Setting(0)

    inputs = WidgetDecorator.syned_input_data()

    def build_gui(self):

        self.IMAGE_WIDTH = 850

        tabs_setting = oasysgui.tabWidget(self.controlArea)
        tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5)

        tab_1 = oasysgui.createTabPage(tabs_setting, self.name + " Input Parameters")
        tab_2 = oasysgui.createTabPage(tabs_setting, "Undulator Setting")

        box = oasysgui.widgetBox(tab_1, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-15)

        idx = -1
        
        #widget index 1 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ENERGY = oasysgui.lineEdit(box1, self, "ENERGY",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 2 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_CURRENT = oasysgui.lineEdit(box1, self, "CURRENT",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 3 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ENERGY_SPREAD = oasysgui.lineEdit(box1, self, "ENERGY_SPREAD",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
      
        #widget index 4 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_SIGX = oasysgui.lineEdit(box1, self, "SIGX",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 5 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_SIGY = oasysgui.lineEdit(box1, self, "SIGY",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 6 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_SIGX1 = oasysgui.lineEdit(box1, self, "SIGX1",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 7 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_SIGY1 = oasysgui.lineEdit(box1, self, "SIGY1",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
  
        #widget index 8 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_PERIOD = oasysgui.lineEdit(box1, self, "PERIOD",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 9 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_NP = oasysgui.lineEdit(box1, self, "NP",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
       
        #widget index 10 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "EMIN",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 11 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "EMAX",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float,  orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 12 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "N",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)
        
        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "DISTANCE",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "XPS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "YPS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "XPC",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 17
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "YPC",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        box = oasysgui.widgetBox(tab_2, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-15)

        #widget index 18 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "HARMONIC_FROM",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 19 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "HARMONIC_TO",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 20 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "HARMONIC_STEP",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 21 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "HRED",
                     label=self.unitLabels()[idx], addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int, orientation="horizontal", labelWidth=350)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 22
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1, self, "HELICAL",
                     label=self.unitLabels()[idx], addSpace=False,
                     items=['Planar undulator', 'Helical undulator'],
                     valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 23 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "NEKS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 24
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1, self, "METHOD",
                     label=self.unitLabels()[idx], addSpace=False,
                     items=['Infinite N +convolution (Dejus)','Infinite N +convolution (Dejus)','Infinite N +convolution(Walker)','Finite-N'],
                     valueType=int, orientation="horizontal", labelWidth=150)
        self.show_at(self.unitFlags()[idx], box1)
       
        #widget index 25
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "BSL",
                     label=self.unitLabels()[idx], addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int, orientation="horizontal", labelWidth=350)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
         return ['Electron energy (GeV)','Current (mA)','Energy Spread (dE/E)',
                 'Sigma X (mm)','Sigma Y (mm)',"Sigma X' (mrad)","Sigma Y' (mrad)",
                 'Period length (cm)','Number of periods',
                 'E1 minimum energy (eV)','E1 maximum energy (eV)','Number of energy-points',                 
                 'Distance to Aperture [m]', 'Aperture Width H [mm]', 'Aperture Height V [mm]',
                 'Aperture Center H [mm]', 'Aperture Center V [mm]',
                 'Minimum harmonic number','Maximum harmonic number','Harmonic step size','Apply Harmonic Reduction',
                 'Mode','Neks OR % Helicity','Method','Baseline Subraction']


    def unitFlags(self):
         return ['True' for i in range(26)]


    def get_help_name(self):
        return 'tcap'

    def check_fields(self):
        self.ENERGY = congruence.checkStrictlyPositiveNumber(self.ENERGY, "Electron Energy")
        self.CURRENT = congruence.checkStrictlyPositiveNumber(self.CURRENT, "Current")
        self.ENERGY_SPREAD = congruence.checkStrictlyPositiveNumber(self.ENERGY_SPREAD, "Energy Spread")
        self.SIGX  = congruence.checkPositiveNumber(self.SIGX , "Sigma X")
        self.SIGY  = congruence.checkPositiveNumber(self.SIGY , "Sigma Y")
        self.SIGX1 = congruence.checkPositiveNumber(self.SIGX1, "Sigma X'")
        self.SIGY1 = congruence.checkPositiveNumber(self.SIGY1, "Sigma Y'")
        self.PERIOD = congruence.checkStrictlyPositiveNumber(self.PERIOD, "Period length")
        self.NP = congruence.checkStrictlyPositiveNumber(self.NP, "Number of periods")
        self.EMIN = congruence.checkPositiveNumber(self.EMIN, "E1 minimum energy")
        self.EMAX = congruence.checkStrictlyPositiveNumber(self.EMAX, "E1 maximum energy")
        congruence.checkLessThan(self.EMIN, self.EMAX, "E1 minimum energy", "E1 maximum energy")
        self.N = congruence.checkStrictlyPositiveNumber(self.N, "Number of Energy Points")
        self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit")
        self.XPS = congruence.checkPositiveNumber(self.XPS, "Aperture Width H")
        self.YPS = congruence.checkPositiveNumber(self.YPS, "Aperture Height V")
        self.XPC = congruence.checkPositiveNumber(self.XPC, "Aperture Center H")
        self.YPC = congruence.checkPositiveNumber(self.YPC, "Aperture Center V")
        self.HARMONIC_FROM = congruence.checkStrictlyPositiveNumber(self.HARMONIC_FROM, "Minimum harmonic number")
        self.HARMONIC_TO = congruence.checkStrictlyPositiveNumber(self.HARMONIC_TO, "Maximum harmonic number")
        congruence.checkLessThan(self.HARMONIC_FROM, self.HARMONIC_TO, "Minimum harmonic number", "Maximum harmonic number")
        self.HARMONIC_STEP = congruence.checkStrictlyPositiveNumber(self.HARMONIC_STEP, "Harmonic step size")
        self.NEKS = congruence.checkStrictlyPositiveNumber(self.NEKS, "Neks OR % Helicity")

    def do_xoppy_calculation(self):
        return self.xoppy_calc_xtcap()

    def extract_data_from_xoppy_output(self, calculation_output):
        return calculation_output

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:
                self.view_type_combo.setEnabled(False)


                xoppy_data_harmonics = calculated_data.get_content("xoppy_data_harmonics")

                titles = self.getTitles()
                xtitles = self.getXTitles()
                ytitles = self.getYTitles()

                progress_bar_step = (100-progressBarValue)/len(titles)

                for index in range(0, len(titles)):
                    x_index, y_index = self.getVariablesToPlot()[index]
                    log_x, log_y = self.getLogPlot()[index]

                    if not self.plot_canvas[index] is None:
                        self.plot_canvas[index].clear()

                    try:
                        for h_index in range(0, len(xoppy_data_harmonics)):

                            self.plot_histo(xoppy_data_harmonics[h_index][1][:, x_index],
                                            xoppy_data_harmonics[h_index][1][:, y_index],
                                            progressBarValue + ((index+1)*progress_bar_step),
                                            tabs_canvas_index=index,
                                            plot_canvas_index=index,
                                            title=titles[index],
                                            xtitle=xtitles[index],
                                            ytitle=ytitles[index],
                                            log_x=log_x,
                                            log_y=log_y,
                                            harmonic=xoppy_data_harmonics[h_index][0],
                                            control=True)

                        self.plot_canvas[index].addCurve(numpy.zeros(1),
                                                         numpy.array([max(xoppy_data_harmonics[h_index][1][:, y_index])]),
                                                         "Click on curve to highlight it",
                                                         xlabel=xtitles[index], ylabel=ytitles[index],
                                                         symbol='', color='white')

                        self.plot_canvas[index].setActiveCurve("Click on curve to highlight it")
                        self.plot_canvas[index].getLegendsDockWidget().setFixedHeight(150)
                        self.plot_canvas[index].getLegendsDockWidget().setVisible(True)

                        self.tabs.setCurrentIndex(index)
                    except Exception as e:
                        self.view_type_combo.setEnabled(True)

                        raise Exception("Data not plottable: bad content\n" + str(e))


                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="",
                   log_x=False, log_y=False, harmonic=1, color='blue', control=True):
        h_title = "Harmonic " + str(harmonic)

        hex_r = hex(min(255, 128 + harmonic*10))[2:].upper()
        hex_g = hex(min(255, 20 + harmonic*15))[2:].upper()
        hex_b = hex(min(255, harmonic*10))[2:].upper()
        if len(hex_r) == 1: hex_r = "0" + hex_r
        if len(hex_g) == 1: hex_g = "0" + hex_g
        if len(hex_b) == 1: hex_b = "0" + hex_b

        #super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle,
        #                   log_x, log_y, color="green", replace=False, control=control)

        super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle,
                           log_x, log_y, color="#" + hex_r + hex_g + hex_b, replace=False, control=control)

        self.plot_canvas[plot_canvas_index].setGraphTitle(title)
        self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True)

    def get_data_exchange_widget_name(self):
        return "XTCAP"

    def getTitles(self):
        return ["Flux peak","Ky","Total Power","Power density peak","Integrated Power on aperture"]

    def getXTitles(self):
        return ["Energy (eV)","Energy (eV)","Energy (eV)","Energy (eV)","Energy (eV)"]

    def getYTitles(self):
        return ["Flux (ph/s/mm^2/0.1%bw)","Ky","Total Power (W)","Power density (W/mm^2)","Integrated Power on Aperture (W)"]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 3), (0, 4), (0, 5), (0, 6)]

    def getLogPlot(self):
        return[(False, True), (False, False), (False, False), (False, False),(False, False)]

    def xoppy_calc_xtcap(self):

        for file in ["tcap.inp","tcap.out","tcap.log"]:
            try:
                os.remove(os.path.join(locations.home_bin_run(),file))
            except:
                pass

        with open("tcap.inp", "wt") as f:
            f.write("TCAP called from xoppy\n")
            f.write("%10.3f %10.2f %10.6f %s\n"%(self.ENERGY,self.CURRENT,self.ENERGY_SPREAD,"Ring-Energy(GeV) Current(mA) Beam-Energy-Spread"))
            f.write("%10.4f %10.4f %10.4f %10.4f %s\n"%(self.SIGX,self.SIGY,self.SIGX1,self.SIGY1,"Sx(mm) Sy(mm) Sx1(mrad) Sy1(mrad)"))
            f.write("%10.3f %d %s\n"%(self.PERIOD,self.NP,"Period(cm) N"))
            f.write("%10.1f %10.1f %d %s\n"%(self.EMIN,self.EMAX,self.N,"Emin Emax Ne"))
            f.write("%10.3f %10.3f %10.3f %10.3f %10.3f %d %d %s\n"%(self.DISTANCE,self.XPC,self.YPC,self.XPS,self.YPS,10,10,"d xpc ypc xps yps nxp nyp"))
            f.write("%d %d %d %d %s\n"%(self.HARMONIC_FROM,self.HARMONIC_TO,self.HARMONIC_STEP,self.HRED,"Hmin Hmax Hstep Hreduction"))
            f.write("%d %d %d %d %d %s\n"%(self.HELICAL,self.METHOD,1,self.NEKS,self.BSL,"Helical Method Print_K Neks Bsl-Subtr "))
            f.write("foreground\n")


        if platform.system() == "Windows":
            command = "\"" + os.path.join(locations.home_bin(),'tcap.exe') + "\""
        else:
            command = "'" + os.path.join(locations.home_bin(), 'tcap') + "'"


        print("Running command '%s' in directory: %s "%(command, locations.home_bin_run()))
        print("\n--------------------------------------------------------\n")
        # os.system(command)

        #
        #   catch the optut and write the output to a log file as well as print it.
        #
        retvalue = os.popen(command).read()
        print(retvalue)

        with open("tcap.log", "wt") as f:
            f.write(retvalue)

        print("Output file: '%s/tcap.out'"%(os.getcwd()) )
        print("\n--------------------------------------------------------\n")

        #
        # parse result files to exchange object
        #


        with open("tcap.out","r") as f:
            lines = f.readlines()

        # print output file
        # for line in lines:
        #     print(line, end="")


        # remove returns
        lines = [line[:-1] for line in lines]
        harmonics_data = []

        # separate numerical data from text
        floatlist = []
        harmoniclist = []
        txtlist = []
        for line in lines:
            try:
                tmp = line.strip()

                if tmp.startswith("Harmonic"):
 #                   harmonic_number = int(tmp.split("Harmonic")[1].strip())
                    harmonic_number = int(tmp.split()[1])

                    if harmonic_number != self.HARMONIC_FROM:
                        harmonics_data[-1][1] = harmoniclist
                        harmoniclist = []

                    harmonics_data.append([harmonic_number, None])

                tmp = float(line.strip()[0])

                floatlist.append(line)
                harmoniclist.append(line)
            except:
                txtlist.append(line)

        harmonics_data[-1][1] = harmoniclist

        data = numpy.loadtxt(floatlist)

        for index in range(0, len(harmonics_data)):
            # print (harmonics_data[index][0], harmonics_data[index][1])
            harmonics_data[index][1] = numpy.loadtxt(harmonics_data[index][1])

        #send exchange
        calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name())

        try:
            calculated_data.add_content("xoppy_data", data)
            calculated_data.add_content("xoppy_data_harmonics", harmonics_data)
            calculated_data.add_content("plot_x_col", 0)
            calculated_data.add_content("plot_y_col", 1)
        except:
            pass

        try:
            calculated_data.add_content("labels",["Energy(eV)","Flux(ph/s/0.1%bw)","FWHM(eV)","Ky",   
                                            "Ptot(W)","Pd(W/mm^2)","IntP(W)"])
            
        except:
            pass
        try:
            calculated_data.add_content("info",txtlist)
        except:
            pass

        return calculated_data

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data.get_light_source() is None and isinstance(data.get_light_source().get_magnetic_structure(), synedid):
                light_source = data.get_light_source()

                self.ENERGY = light_source.get_electron_beam().energy()
                self.ENERGY_SPREAD = light_source.get_electron_beam()._energy_spread
                self.CURRENT = 1000.0 * light_source.get_electron_beam().current()

                x, xp, y, yp = light_source.get_electron_beam().get_sigmas_all()

                self.SIGX = 1e3 * x
                self.SIGY = 1e3 * y
                self.SIGX1 = 1e3 * xp
                self.SIGY1 = 1e3 * yp
                self.PERIOD = 100.0 * light_source._magnetic_structure._period_length
                self.NP = light_source._magnetic_structure._number_of_periods

                self.EMIN = light_source.get_magnetic_structure().resonance_energy(gamma=light_source.get_electron_beam().gamma())
                self.EMAX = 5 * self.EMIN

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")



    def set_enabled(self,value):
        if value == True:
                self.id_ENERGY.setEnabled(True)
                self.id_ENERGY_SPREAD.setEnabled(True)
                self.id_SIGX.setEnabled(True)
                self.id_SIGX1.setEnabled(True)
                self.id_SIGY.setEnabled(True)
                self.id_SIGY1.setEnabled(True)
                self.id_CURRENT.setEnabled(True)
                self.id_PERIOD.setEnabled(True)
                self.id_NP.setEnabled(True)
        else:
                self.id_ENERGY.setEnabled(False)
                self.id_ENERGY_SPREAD.setEnabled(False)
                self.id_SIGX.setEnabled(False)
                self.id_SIGX1.setEnabled(False)
                self.id_SIGY.setEnabled(False)
                self.id_SIGY1.setEnabled(False)
                self.id_CURRENT.setEnabled(False)
                self.id_PERIOD.setEnabled(False)
                self.id_NP.setEnabled(False)
class OWSRWCrystal(OWSRWOpticalElement):


    inputs = [("SRWData", SRWData, "set_input"),
              ("Trigger", TriggerOut, "propagate_new_wavefront"),
              ("ExchangeData", DataExchangeObject, "acceptExchangeData"),
              WidgetDecorator.syned_input_data()[0]]

    d_spacing       = Setting(0.0)
    asymmetry_angle = Setting(0.0)
    thickness       = Setting(0.0)
    psi_0r          = Setting(0.0)
    psi_0i          = Setting(0.0)
    psi_hr          = Setting(0.0)
    psi_hi          = Setting(0.0)
    psi_hbr         = Setting(0.0)
    psi_hbi         = Setting(0.0)
    diffraction_geometry = Setting(0)

    notes = Setting("")

    usage_path = os.path.join(resources.package_dirname("orangecontrib.srw.widgets.gui"), "misc", "crystal_usage.png")

    def __init__(self):
        super().__init__(azimuth_hor_vert=True)

    def draw_specific_box(self):

        self.crystal_box = oasysgui.widgetBox(self.tab_bas, "Crystal Setting", addSpace=False, orientation="vertical")

        oasysgui.lineEdit(self.crystal_box, self, "d_spacing", "d-spacing [Å]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.crystal_box, self, "asymmetry_angle", "Asymmetry Angle [rad]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.crystal_box, self, "thickness", "Crystal Thickness [m]", labelWidth=260, valueType=float, orientation="horizontal")

        polarization_box = oasysgui.widgetBox(self.crystal_box, "Crystal Polarizability", addSpace=False, orientation="horizontal")

        polarization_box_l = oasysgui.widgetBox(polarization_box, "", addSpace=False, orientation="vertical", width=200)
        polarization_box_r = oasysgui.widgetBox(polarization_box, "", addSpace=False, orientation="vartical")

        gui.label(polarization_box_l, self, "               Real Part")
        oasysgui.lineEdit(polarization_box_l, self, "psi_0r" , "X0", labelWidth=50, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(polarization_box_l, self, "psi_hr" , "Xh \u03c3", labelWidth=50, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(polarization_box_l, self, "psi_hbr", "Xh \u03c0", labelWidth=50, valueType=float, orientation="horizontal")

        gui.label(polarization_box_r, self, "Imaginary Part")
        oasysgui.lineEdit(polarization_box_r, self, "psi_0i",  "", labelWidth=50, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(polarization_box_r, self, "psi_hi",  "", labelWidth=50, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(polarization_box_r, self, "psi_hbi", "", labelWidth=50, valueType=float, orientation="horizontal")

        self.notes_area = oasysgui.textArea(height=40, width=370)
        self.notes_area.setText(self.notes)

        self.crystal_box.layout().addWidget(self.notes_area)

        tab_usa = oasysgui.createTabPage(self.tabs_setting, "Use of the Widget")
        tab_usa.setStyleSheet("background-color: white;")

        usage_box = oasysgui.widgetBox(tab_usa, "", addSpace=True, orientation="horizontal")

        label = QLabel("")
        label.setAlignment(Qt.AlignCenter)
        label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        label.setPixmap(QPixmap(self.usage_path))

        usage_box.layout().addWidget(label)


    def get_optical_element(self):
        return SRWCrystal(orientation_of_reflection_plane = self.orientation_azimuthal,
                          invert_tangent_component        = self.invert_tangent_component == 1,
                          d_spacing                       = self.d_spacing,
                          asymmetry_angle                 = self.asymmetry_angle,
                          thickness                       = self.thickness,
                          psi_0r                          = self.psi_0r,
                          psi_0i                          = self.psi_0i,
                          psi_hr                          = self.psi_hr,
                          psi_hi                          = self.psi_hi,
                          psi_hbr                         = self.psi_hbr,
                          psi_hbi                         = self.psi_hbi,
                          incident_angle                  = numpy.radians(90-self.angle_radial))

    def receive_specific_syned_data(self, optical_element):
        if not optical_element is None:
            if isinstance(optical_element, Crystal):
                self.asymmetry_angle           = optical_element._asymmetry_angle,
                self.thickness                 = optical_element._thickness,
                self.diffraction_geometry = optical_element._diffraction_geometry
            else:
                raise Exception("Syned Data not correct: Optical Element is not a Crystal")
        else:
            raise Exception("Syned Data not correct: Empty Optical Element")


    def check_data(self):
        super().check_data()

        congruence.checkStrictlyPositiveNumber(self.d_spacing, "d-spacing")

    def acceptExchangeData(self, exchangeData):
        if not exchangeData is None:
            try:
                if exchangeData.get_program_name() == "XRAYSERVER":
                    if exchangeData.get_widget_name() == "X0H":
                        self.notes = "Data from X-Ray Server: " + exchangeData.get_content("structure") + "(" + \
                                     str(exchangeData.get_content("h")) + "," + str(exchangeData.get_content("k")) + "," + str(exchangeData.get_content("l")) + ")" +  \
                                     " at " + str(round(exchangeData.get_content("energy")*1000, 4)) + " eV"
                        self.notes_area.setText(self.notes)

                        self.angle_radial = 90 - exchangeData.get_content("bragg_angle")
                        self.d_spacing = exchangeData.get_content("d_spacing")
                        self.psi_0r    = exchangeData.get_content("xr0")
                        self.psi_0i    = exchangeData.get_content("xi0")
                        self.psi_hr    = exchangeData.get_content("xrh_s")
                        self.psi_hi    = exchangeData.get_content("xih_s")
                        self.psi_hbr   = exchangeData.get_content("xrh_p")
                        self.psi_hbi   = exchangeData.get_content("xih_p")
            except Exception as e:
                QMessageBox.critical(self, "Error", str(e.args[0]), QMessageBox.Ok)
Exemple #9
0
class OWundulator_power_density(XoppyWidget, WidgetDecorator):
    name = "Undulator Power Density"
    id = "orange.widgets.dataundulator_power_density"
    description = "Undulator Power Density"
    icon = "icons/xoppy_undulator_power_density.png"
    priority = 3
    category = ""
    keywords = ["xoppy", "undulator_power_density"]

    USEEMITTANCES = Setting(1)
    ELECTRONENERGY = Setting(6.04)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(0.000395)
    ELECTRONBEAMSIZEV = Setting(9.9e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05)
    ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06)
    PERIODID = Setting(0.018)
    NPERIODS = Setting(222)
    KV = Setting(1.68)
    DISTANCE = Setting(30.0)
    GAPH = Setting(0.003)
    GAPV = Setting(0.003)
    HSLITPOINTS = Setting(41)
    VSLITPOINTS = Setting(41)
    METHOD = Setting(0)

    inputs = [WidgetDecorator.syned_input_data()]

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1
        #
        #
        #

        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "USEEMITTANCES",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGY",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGYSPREAD",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONCURRENT",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1,
                                             self,
                                             "PERIODID",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             validator=QDoubleValidator(),
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1,
                                             self,
                                             "NPERIODS",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=int,
                                             validator=QIntValidator(),
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1,
                                       self,
                                       "KV",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       validator=QDoubleValidator(),
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "DISTANCE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPH",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPV",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "VSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "METHOD",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['US', 'URGENT', 'SRW'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return [
            "Use emittances", "Electron Energy [GeV]",
            "Electron Energy Spread", "Electron Current [A]",
            "Electron Beam Size H [m]", "Electron Beam Size V [m]",
            "Electron Beam Divergence H [rad]",
            "Electron Beam Divergence V [rad]", "Period ID [m]",
            "Number of periods", "Kv [undulator K value vertical field]",
            "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]",
            "Number of slit mesh points in H",
            "Number of slit mesh points in V", "calculation code"
        ]

    def unitFlags(self):
        return [
            "True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1",
            "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1",
            "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True",
            "True", "True", "True", "True", "True", "True", "True", "True"
        ]

    def get_help_name(self):
        return 'undulator_power_density'

    def check_fields(self):

        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1:
            self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(
                self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")
        self.PERIODID = congruence.checkStrictlyPositiveNumber(
            self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(
            self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE,
                                                       "Distance to slit")
        self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
        self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
        self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.HSLITPOINTS, "Number of slit mesh points in H")
        self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.VSLITPOINTS, "Number of slit mesh points in V")

        if self.METHOD == 1:  # URGENT
            congruence.checkLessOrEqualThan(
                self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT ",
                " 51")
            congruence.checkLessOrEqualThan(
                self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT ",
                " 51")

        # if sys.platform == 'linux' and self.METHOD == 2:
        #     raise Exception("SRW calculation code not supported under Linux")

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:

                self.initializeTabs(
                )  # added by srio to avoid overlapping graphs

                self.view_type_combo.setEnabled(False)

                data = calculated_data.get_content("xoppy_data")
                code = calculated_data.get_content("xoppy_code")

                h = data[0]
                v = data[1]
                p = data[2]

                try:

                    print("Result arrays (shapes): ", h.shape, v.shape,
                          p.shape)

                    self.plot_data2D(p,
                                     h,
                                     v,
                                     0,
                                     0,
                                     xtitle='H [mm]',
                                     ytitle='V [mm]',
                                     title='Code ' + code +
                                     '; Power density [W/mm^2]')

                except Exception as e:
                    self.view_type_combo.setEnabled(True)

                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def do_xoppy_calculation(self):
        return xoppy_calc_undulator_power_density(
            ELECTRONENERGY=self.ELECTRONENERGY,
            ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD,
            ELECTRONCURRENT=self.ELECTRONCURRENT,
            ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH,
            ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV,
            ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH,
            ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV,
            PERIODID=self.PERIODID,
            NPERIODS=self.NPERIODS,
            KV=self.KV,
            DISTANCE=self.DISTANCE,
            GAPH=self.GAPH,
            GAPV=self.GAPV,
            HSLITPOINTS=self.HSLITPOINTS,
            VSLITPOINTS=self.VSLITPOINTS,
            METHOD=self.METHOD,
            USEEMITTANCES=self.USEEMITTANCES)

    def extract_data_from_xoppy_output(self, calculation_output):
        h, v, p, code = calculation_output

        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())

        calculated_data.add_content("xoppy_data", [h, v, p])
        calculated_data.add_content("xoppy_code", code)

        return calculated_data

    def get_data_exchange_widget_name(self):
        return "UNDULATOR_POWER_DENSITY"

    def getTitles(self):
        return ['Undulator Power Density']

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KV = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):
        if value == True:
            self.id_ELECTRONENERGY.setEnabled(True)
            self.id_ELECTRONENERGYSPREAD.setEnabled(True)
            self.id_ELECTRONBEAMSIZEH.setEnabled(True)
            self.id_ELECTRONBEAMSIZEV.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
            self.id_ELECTRONCURRENT.setEnabled(True)
            self.id_PERIODID.setEnabled(True)
            self.id_NPERIODS.setEnabled(True)
            self.id_KV.setEnabled(True)
        else:
            self.id_ELECTRONENERGY.setEnabled(False)
            self.id_ELECTRONENERGYSPREAD.setEnabled(False)
            self.id_ELECTRONBEAMSIZEH.setEnabled(False)
            self.id_ELECTRONBEAMSIZEV.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
            self.id_ELECTRONCURRENT.setEnabled(False)
            self.id_PERIODID.setEnabled(False)
            self.id_NPERIODS.setEnabled(False)
            self.id_KV.setEnabled(False)
Exemple #10
0
class OWundulator_spectrum(XoppyWidget, WidgetDecorator):
    name = "Undulator Spectrum"
    id = "orange.widgets.dataundulator_spectrum"
    description = "Undulator Spectrum"
    icon = "icons/xoppy_undulator_spectrum.png"
    priority = 1
    category = ""
    keywords = ["xoppy", "undulator_spectrum"]

    USEEMITTANCES = Setting(1)
    ELECTRONENERGY = Setting(6.04)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(0.000395)
    ELECTRONBEAMSIZEV = Setting(9.9e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05)
    ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06)
    PERIODID = Setting(0.018)
    NPERIODS = Setting(222)
    KV = Setting(1.68)
    KH = Setting(0.0)
    KPHASE = Setting(0.0)
    DISTANCE = Setting(30.0)
    GAPH = Setting(0.001)
    GAPV = Setting(0.001)
    GAPH_CENTER = Setting(0.0)
    GAPV_CENTER = Setting(0.0)
    PHOTONENERGYMIN = Setting(3000.0)
    PHOTONENERGYMAX = Setting(55000.0)
    PHOTONENERGYPOINTS = Setting(500)
    METHOD = Setting(2)

    inputs = WidgetDecorator.syned_input_data()

    def __init__(self):
        super().__init__(show_script_tab=True)

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1

        #
        #
        #

        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "USEEMITTANCES",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGY",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGYSPREAD",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONCURRENT",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1,
                                             self,
                                             "PERIODID",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1,
                                             self,
                                             "NPERIODS",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=int,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1,
                                       self,
                                       "KV",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9B
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KH = oasysgui.lineEdit(box1,
                                       self,
                                       "KH",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9C
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KPHASE = oasysgui.lineEdit(box1,
                                           self,
                                           "KPHASE",
                                           label=self.unitLabels()[idx],
                                           addSpace=False,
                                           valueType=float,
                                           orientation="horizontal",
                                           labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "DISTANCE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPH",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPV",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11B
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPH_CENTER",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12B
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPV_CENTER",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYMIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYMAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "METHOD",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['US', 'URGENT', 'SRW'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return [
            "Use emittances", "Electron Energy [GeV]",
            "Electron Energy Spread", "Electron Current [A]",
            "Electron Beam Size H [m]", "Electron Beam Size V [m]",
            "Electron Beam Divergence H [rad]",
            "Electron Beam Divergence V [rad]", "Period ID [m]",
            "Number of periods", "Kv [K value vertical field]",
            "Kh [K value horizontal field]",
            "Kphase [phase diff Kh - Kv in rad]", "Distance to slit [m]",
            "Slit gap H [m]", "Slit gap V [m]", "Slit center H [m]",
            "Slit center V [m]", "photon Energy Min [eV]",
            "photon Energy Max [eV]", "photon Energy Points",
            "calculation code"
        ]

    def unitFlags(self):
        return [
            "True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1",
            "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1",
            "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True",
            "True", "True", "self.METHOD != 0", "self.METHOD != 0", "True",
            "True", "True", "True", "True", "True", "True", "True", "True"
        ]

    def get_help_name(self):
        return 'undulator_spectrum'

    def check_fields(self):
        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1:
            self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(
                self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")
        self.PERIODID = congruence.checkStrictlyPositiveNumber(
            self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(
            self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.KH = congruence.checkPositiveNumber(self.KH, "Kh")
        self.KPHASE = congruence.checkNumber(self.KPHASE, "KPHASE")
        self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE,
                                                       "Distance to slit")
        self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
        self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
        self.GAPH_CENTER = congruence.checkPositiveNumber(
            self.GAPH_CENTER, "Slit center H")
        self.GAPV_CENTER = congruence.checkPositiveNumber(
            self.GAPV_CENTER, "Slit center V")
        self.PHOTONENERGYMIN = congruence.checkPositiveNumber(
            self.PHOTONENERGYMIN, "photon Energy Min")
        self.PHOTONENERGYMAX = congruence.checkStrictlyPositiveNumber(
            self.PHOTONENERGYMAX, "photon Energy Max")
        congruence.checkLessThan(self.PHOTONENERGYMIN, self.PHOTONENERGYMAX,
                                 "photon Energy Min", "photon Energy Max")
        self.PHOTONENERGYPOINTS = congruence.checkStrictlyPositiveNumber(
            self.PHOTONENERGYPOINTS, "photon Energy Points")

        if self.METHOD == 1:  # URGENT
            congruence.checkLessThan(self.PHOTONENERGYPOINTS, 4701,
                                     "Number of energy points", "4701")

        # if sys.platform == 'linux' and self.METHOD == 2:
        #     raise Exception("SRW calculation code not supported under Linux")

    def do_xoppy_calculation(self):
        energy, flux, spectral_power, cumulated_power = xoppy_calc_undulator_spectrum(
            ELECTRONENERGY=self.ELECTRONENERGY,
            ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD,
            ELECTRONCURRENT=self.ELECTRONCURRENT,
            ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH,
            ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV,
            ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH,
            ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV,
            PERIODID=self.PERIODID,
            NPERIODS=self.NPERIODS,
            KV=self.KV,
            KH=self.KH,
            KPHASE=self.KPHASE,
            DISTANCE=self.DISTANCE,
            GAPH=self.GAPH,
            GAPV=self.GAPV,
            GAPH_CENTER=self.GAPH_CENTER,
            GAPV_CENTER=self.GAPV_CENTER,
            PHOTONENERGYMIN=self.PHOTONENERGYMIN,
            PHOTONENERGYMAX=self.PHOTONENERGYMAX,
            PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS,
            METHOD=self.METHOD,
            USEEMITTANCES=self.USEEMITTANCES)

        # write python script in standard output
        dict_parameters = {
            "ELECTRONENERGY": self.ELECTRONENERGY,
            "ELECTRONENERGYSPREAD": self.ELECTRONENERGYSPREAD,
            "ELECTRONCURRENT": self.ELECTRONCURRENT,
            "ELECTRONBEAMSIZEH": self.ELECTRONBEAMSIZEH,
            "ELECTRONBEAMSIZEV": self.ELECTRONBEAMSIZEV,
            "ELECTRONBEAMDIVERGENCEH": self.ELECTRONBEAMDIVERGENCEH,
            "ELECTRONBEAMDIVERGENCEV": self.ELECTRONBEAMDIVERGENCEV,
            "PERIODID": self.PERIODID,
            "NPERIODS": self.NPERIODS,
            "KV": self.KV,
            "KH": self.KH,
            "KPHASE": self.KPHASE,
            "DISTANCE": self.DISTANCE,
            "GAPH": self.GAPH,
            "GAPV": self.GAPV,
            "GAPH_CENTER": self.GAPH_CENTER,
            "GAPV_CENTER": self.GAPV_CENTER,
            "PHOTONENERGYMIN": self.PHOTONENERGYMIN,
            "PHOTONENERGYMAX": self.PHOTONENERGYMAX,
            "PHOTONENERGYPOINTS": self.PHOTONENERGYPOINTS,
            "METHOD": self.METHOD,
            "USEEMITTANCES": self.USEEMITTANCES,
        }

        # print(self.script_template().format_map(dict_parameters))

        self.xoppy_script.set_code(
            self.script_template().format_map(dict_parameters))

        return energy, flux, spectral_power, cumulated_power

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:undulator_spectrum)
#
from orangecontrib.xoppy.util.xoppy_undulators import xoppy_calc_undulator_spectrum
energy, flux, spectral_power, cumulated_power = xoppy_calc_undulator_spectrum(
    ELECTRONENERGY={ELECTRONENERGY},
    ELECTRONENERGYSPREAD={ELECTRONENERGYSPREAD},
    ELECTRONCURRENT={ELECTRONCURRENT},
    ELECTRONBEAMSIZEH={ELECTRONBEAMSIZEH},
    ELECTRONBEAMSIZEV={ELECTRONBEAMSIZEV},
    ELECTRONBEAMDIVERGENCEH={ELECTRONBEAMDIVERGENCEH},
    ELECTRONBEAMDIVERGENCEV={ELECTRONBEAMDIVERGENCEV},
    PERIODID={PERIODID},
    NPERIODS={NPERIODS},
    KV={KV},
    KH={KH},
    KPHASE={KPHASE},
    DISTANCE={DISTANCE},
    GAPH={GAPH},
    GAPV={GAPV},
    GAPH_CENTER={GAPH_CENTER},
    GAPV_CENTER={GAPV_CENTER},
    PHOTONENERGYMIN={PHOTONENERGYMIN},
    PHOTONENERGYMAX={PHOTONENERGYMAX},
    PHOTONENERGYPOINTS={PHOTONENERGYPOINTS},
    METHOD={METHOD},
    USEEMITTANCES={USEEMITTANCES})
# example plot
from srxraylib.plot.gol import plot
plot(energy,flux,ytitle="Flux [photons/s/o.1%bw]",xtitle="Poton energy [eV]",title="Undulator Flux",
    xlog=False,ylog=False,show=False)
plot(energy,spectral_power,ytitle="Power [W/eV]",xtitle="Poton energy [eV]",title="Undulator Spectral Power",
    xlog=False,ylog=False,show=False)
plot(energy,cumulated_power,ytitle="Cumulated Power [W]",xtitle="Poton energy [eV]",title="Undulator Cumulated Power",
    xlog=False,ylog=False,show=True)
#
# end script
#
"""

    def extract_data_from_xoppy_output(self, calculation_output):
        e, f, sp, csp = calculation_output

        data = numpy.zeros((len(e), 4))
        data[:, 0] = numpy.array(e)
        data[:, 1] = numpy.array(f)
        data[:, 2] = numpy.array(sp)
        data[:, 3] = numpy.array(csp)

        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())
        calculated_data.add_content("xoppy_data", data)

        return calculated_data

    def get_data_exchange_widget_name(self):
        return "UNDULATOR_FLUX"

    def getTitles(self):
        return ['Undulator Flux', 'Spectral Power', 'Cumulated Power']

    def getXTitles(self):
        return ["Energy [eV]", "Energy [eV]", "Energy [eV]"]

    def getYTitles(self):
        return [
            "Flux [Phot/sec/0.1%bw]", "Spectral Power [W/eV]",
            "Cumulated Power [W]"
        ]

    def getLogPlot(self):
        return [(False, False), (False, False), (False, False)]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2), (0, 3)]

    def getDefaultPlotTabIndex(self):
        return 0

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = int(
                    light_source._magnetic_structure._number_of_periods)
                self.KV = light_source._magnetic_structure._K_vertical
                self.KH = light_source._magnetic_structure._K_horizontal
                # TODO  self.KPHASE = light_source._magnetic_structure....

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):
        if value == True:
            self.id_ELECTRONENERGY.setEnabled(True)
            self.id_ELECTRONENERGYSPREAD.setEnabled(True)
            self.id_ELECTRONBEAMSIZEH.setEnabled(True)
            self.id_ELECTRONBEAMSIZEV.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
            self.id_ELECTRONCURRENT.setEnabled(True)
            self.id_PERIODID.setEnabled(True)
            self.id_NPERIODS.setEnabled(True)
            self.id_KV.setEnabled(True)
            self.id_KH.setEnabled(True)
        else:
            self.id_ELECTRONENERGY.setEnabled(False)
            self.id_ELECTRONENERGYSPREAD.setEnabled(False)
            self.id_ELECTRONBEAMSIZEH.setEnabled(False)
            self.id_ELECTRONBEAMSIZEV.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
            self.id_ELECTRONCURRENT.setEnabled(False)
            self.id_PERIODID.setEnabled(False)
            self.id_NPERIODS.setEnabled(False)
            self.id_KV.setEnabled(False)
            self.id_KH.setEnabled(False)
Exemple #11
0
class OWundulator_radiation(XoppyWidget, WidgetDecorator):
    name = "Undulator Radiation"
    id = "orange.widgets.dataundulator_radiation"
    description = "Undulator Radiation"
    icon = "icons/xoppy_undulator_radiation.png"
    priority = 5
    category = ""
    keywords = ["xoppy", "undulator_radiation"]

    # overwrite from
    outputs = [{"name": "xoppy_data", "type": DataExchangeObject, "doc": ""}]

    USEEMITTANCES = Setting(1)
    ELECTRONENERGY = Setting(6.04)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(0.000395)
    ELECTRONBEAMSIZEV = Setting(9.9e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05)
    ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06)

    PERIODID = Setting(0.018)
    NPERIODS = Setting(222)
    KV = Setting(1.68)

    DISTANCE = Setting(30.0)
    SETRESONANCE = Setting(0)
    HARMONICNUMBER = Setting(1)

    GAPH = Setting(0.003)
    GAPV = Setting(0.003)
    HSLITPOINTS = Setting(41)
    VSLITPOINTS = Setting(41)

    PHOTONENERGYMIN = Setting(6000.0)
    PHOTONENERGYMAX = Setting(8500.0)
    PHOTONENERGYPOINTS = Setting(20)

    METHOD = Setting(2)
    H5_FILE_DUMP = Setting(0)

    inputs = WidgetDecorator.syned_input_data()

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1

        #
        #
        #

        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "USEEMITTANCES",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGY",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGYSPREAD",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONCURRENT",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            validator=QDoubleValidator(),
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1,
                                             self,
                                             "PERIODID",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             validator=QDoubleValidator(),
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1,
                                             self,
                                             "NPERIODS",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=int,
                                             validator=QIntValidator(),
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1,
                                       self,
                                       "KV",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       validator=QDoubleValidator(),
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "DISTANCE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        # widget <><><>
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "SETRESONANCE",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'User defined', 'Set to resonance/central cone',
                         'Set to resonance/up to first ring'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget <><><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HARMONICNUMBER",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPH",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPV",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "VSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYMIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYMAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "METHOD",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['US', 'URGENT', 'SRW', 'pySRU'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "H5_FILE_DUMP",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'None', 'Write h5 file: undulator_radiation.h5',
                         'Read from file...'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250,
                     callback=self.read_or_write_file)
        self.show_at(self.unitFlags()[idx], box1)

    def read_or_write_file(self):

        value = self.H5_FILE_DUMP

        if value == 0:
            return
        elif value == 1:  # write
            return
        elif value == 2:  # read

            self.H5_FILE_DUMP = 0

            tmp = ConfirmDialog.confirmed(
                self,
                message=
                "Please select in a hdf5 file a data block\n(such as XOPPY_RADIATION)\nthat contains a 'Radiation' entry",
                title="Confirm Action")
            if tmp == False: return

            dialog = DataFileDialog(self)
            dialog.setFilterMode(DataFileDialog.FilterMode.ExistingGroup)
            # dialog.setDirectory("")
            # Execute the dialog as modal
            result = dialog.exec_()

            if result:
                print("Selection:")
                print(dialog.selectedFile())
                print(dialog.selectedUrl())
                print(dialog.selectedDataUrl().data_path())

                calculation_output = self.extract_data_from_h5file(
                    dialog.selectedFile(),
                    dialog.selectedDataUrl().data_path())

                if calculation_output is None:
                    raise Exception("Bad data from file.")
                else:
                    self.calculated_data = self.extract_data_from_xoppy_output(
                        calculation_output)

                    try:
                        self.set_fields_from_h5file(
                            dialog.selectedFile(),
                            dialog.selectedDataUrl().data_path())
                    except:
                        pass

                    # self.add_specific_content_to_calculated_data(self.calculated_data)
                    #
                    self.setStatusMessage("Plotting Results")

                    self.plot_results(self.calculated_data,
                                      progressBarValue=60)

                    self.setStatusMessage("")

                    self.send("xoppy_data", self.calculated_data)

                self.set_enabled(True)

    def extract_data_from_h5file(self, file_h5, subtitle):

        hf = h5py.File(file_h5, 'r')

        try:
            p = hf[subtitle + "/Radiation/stack_data"].value
            e = hf[subtitle + "/Radiation/axis0"].value
            h = hf[subtitle + "/Radiation/axis1"].value
            v = hf[subtitle + "/Radiation/axis2"].value
        except:
            raise Exception("Data not plottable: bad content\n" + str(e))

        code = "unknown"

        try:
            if hf[subtitle + "/parameters/METHOD"].value == 0:
                code = 'US'
            elif hf[subtitle + "/parameters/METHOD"].value == 1:
                code = 'URGENT'
            elif hf[subtitle + "/parameters/METHOD"].value == 2:
                code = 'SRW'
            elif hf[subtitle + "/parameters/METHOD"].value == 3:
                code = 'pySRU'
        except:
            pass

        hf.close()

        return e, h, v, p, code

    def set_fields_from_h5file(self, file_h5, subtitle):

        hf = h5py.File(file_h5, 'r')

        self.METHOD = hf[subtitle + "/parameters/METHOD"].value
        self.USEEMITTANCES = hf[subtitle + "/parameters/USEEMITTANCES"].value
        self.ELECTRONENERGY = hf[subtitle + "/parameters/ELECTRONENERGY"].value
        self.ELECTRONENERGYSPREAD = hf[
            subtitle + "/parameters/ELECTRONENERGYSPREAD"].value
        self.ELECTRONCURRENT = hf[subtitle +
                                  "/parameters/ELECTRONCURRENT"].value
        self.ELECTRONBEAMSIZEH = hf[subtitle +
                                    "/parameters/ELECTRONBEAMSIZEH"].value
        self.ELECTRONBEAMSIZEV = hf[subtitle +
                                    "/parameters/ELECTRONBEAMSIZEV"].value
        self.ELECTRONBEAMDIVERGENCEH = hf[
            subtitle + "/parameters/ELECTRONBEAMDIVERGENCEH"].value
        self.ELECTRONBEAMDIVERGENCEV = hf[
            subtitle + "/parameters/ELECTRONBEAMDIVERGENCEV"].value
        self.PERIODID = hf[subtitle + "/parameters/PERIODID"].value
        self.NPERIODS = hf[subtitle + "/parameters/NPERIODS"].value
        self.KV = hf[subtitle + "/parameters/KV"].value
        self.DISTANCE = hf[subtitle + "/parameters/DISTANCE"].value
        self.SETRESONANCE = hf[subtitle + "/parameters/SETRESONANCE"].value
        self.HARMONICNUMBER = hf[subtitle + "/parameters/HARMONICNUMBER"].value
        self.GAPH = hf[subtitle + "/parameters/GAPH"].value
        self.GAPV = hf[subtitle + "/parameters/GAPV"].value
        self.HSLITPOINTS = hf[subtitle + "/parameters/HSLITPOINTS"].value
        self.VSLITPOINTS = hf[subtitle + "/parameters/VSLITPOINTS"].value
        self.PHOTONENERGYMIN = hf[subtitle +
                                  "/parameters/PHOTONENERGYMIN"].value
        self.PHOTONENERGYMAX = hf[subtitle +
                                  "/parameters/PHOTONENERGYMAX"].value
        self.PHOTONENERGYPOINTS = hf[subtitle +
                                     "/parameters/PHOTONENERGYPOINTS"].value

        hf.close()

    def unitLabels(self):
        return [
            "Use emittances", "Electron Energy [GeV]",
            "Electron Energy Spread", "Electron Current [A]",
            "Electron Beam Size H [m]", "Electron Beam Size V [m]",
            "Electron Beam Divergence H [rad]",
            "Electron Beam Divergence V [rad]", "Period ID [m]",
            "Number of periods", "Kv [undulator K value vertical field]",
            "Distance to slit [m]", "Set photon energy and slit",
            "Harmonic number", "Slit gap H [m]", "Slit gap V [m]",
            "Number of slit mesh points in H",
            "Number of slit mesh points in V", "Photon Energy Min [eV]",
            "Photon Energy Max [eV]", "Number of Photon Energy Points",
            "calculation code", "hdf5 file"
        ]

    # TODO check energy spread flag: set to False (not used at all)!!
    def unitFlags(self):
        return [
            "True", "True", "False", "True", "self.USEEMITTANCES == 1",
            "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1",
            "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True",
            "self.SETRESONANCE > 0", "self.SETRESONANCE == 0",
            "self.SETRESONANCE == 0", "True", "True", "self.SETRESONANCE == 0",
            "self.SETRESONANCE == 0", "self.SETRESONANCE == 0", "True", "True"
        ]

    def get_help_name(self):
        return 'undulator_radiation'

    def check_fields(self):
        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1:
            self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(
                self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkNumber(
            self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkNumber(
            self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")

        self.PERIODID = congruence.checkStrictlyPositiveNumber(
            self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(
            self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.DISTANCE = congruence.checkStrictlyPositiveNumber(
            self.DISTANCE, "Distance to slit")

        if self.SETRESONANCE == 0:
            self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
            self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
            self.PHOTONENERGYMIN = congruence.checkNumber(
                self.PHOTONENERGYMIN, "Photon Energy Min")
            self.PHOTONENERGYMAX = congruence.checkNumber(
                self.PHOTONENERGYMAX, "Photon Energy Max")
            congruence.checkGreaterOrEqualThan(
                self.PHOTONENERGYPOINTS, 2, "Number of Photon Energy Points",
                " 2")
        else:
            self.HARMONICNUMBER = congruence.checkStrictlyPositiveNumber(
                self.HARMONICNUMBER, "Harmonic number")

        self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.HSLITPOINTS, "Number of slit mesh points in H")
        self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.VSLITPOINTS, "Number of slit mesh points in V")

        if self.METHOD == 1:  # URGENT
            congruence.checkLessOrEqualThan(
                self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT ",
                " 51")
            congruence.checkLessOrEqualThan(
                self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT ",
                " 51")

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:

                self.initializeTabs(
                )  # added by srio to avoid overlapping graphs

                self.view_type_combo.setEnabled(False)

                p, e, h, v = calculated_data.get_content("xoppy_data")
                code = calculated_data.get_content("xoppy_code")

                try:
                    self.plot_data3D(
                        p,
                        e,
                        h,
                        v,
                        0,
                        0,
                        xtitle='H [mm]',
                        ytitle='V [mm]',
                        title='Code ' + code +
                        '; Flux [photons/s/0.1%bw/mm^2]',
                    )

                    self.tabs.setCurrentIndex(0)
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                try:
                    if len(e) > 1:
                        energy_step = e[1] - e[0]
                    else:
                        energy_step = 1.0

                    self.plot_data2D(
                        p.sum(axis=0) * energy_step * codata.e * 1e3,
                        h,
                        v,
                        1,
                        0,
                        xtitle='H [mm]',
                        ytitle='V [mm]',
                        title='Code ' + code + '; Power density [W/mm^2]',
                    )

                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                try:
                    print("\nResult arrays (shapes): ", e.shape, h.shape,
                          v.shape, p.shape)
                    self.plot_data1D(
                        e,
                        p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) *
                        (v[1] - v[0]),
                        2,
                        0,
                        xtitle='Photon Energy [eV]',
                        ytitle='Flux [photons/s/0.1%bw]',
                        title='Code ' + code + '; Flux',
                    )

                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                try:
                    print("\nResult arrays (shapes): ", e.shape, h.shape,
                          v.shape, p.shape)
                    self.plot_data1D(
                        e,
                        p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) *
                        (v[1] - v[0]) * codata.e * 1e3,
                        3,
                        0,
                        xtitle='Photon Energy [eV]',
                        ytitle='Spectral power [W/eV]',
                        title='Code ' + code + '; Spectral power',
                    )

                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def do_xoppy_calculation(self):

        if self.H5_FILE_DUMP == 0:
            h5_file = ""
        else:
            h5_file = "undulator_radiation.h5"

        dict_parameters = {
            "ELECTRONENERGY": self.ELECTRONENERGY,
            "ELECTRONENERGYSPREAD": self.ELECTRONENERGYSPREAD,
            "ELECTRONCURRENT": self.ELECTRONCURRENT,
            "ELECTRONBEAMSIZEH": self.ELECTRONBEAMSIZEH,
            "ELECTRONBEAMSIZEV": self.ELECTRONBEAMSIZEV,
            "ELECTRONBEAMDIVERGENCEH": self.ELECTRONBEAMDIVERGENCEH,
            "ELECTRONBEAMDIVERGENCEV": self.ELECTRONBEAMDIVERGENCEV,
            "PERIODID": self.PERIODID,
            "NPERIODS": self.NPERIODS,
            "KV": self.KV,
            "DISTANCE": self.DISTANCE,
            "SETRESONANCE": self.SETRESONANCE,
            "HARMONICNUMBER": self.HARMONICNUMBER,
            "GAPH": self.GAPH,
            "GAPV": self.GAPV,
            "HSLITPOINTS": self.HSLITPOINTS,
            "VSLITPOINTS": self.VSLITPOINTS,
            "METHOD": self.METHOD,
            "PHOTONENERGYMIN": self.PHOTONENERGYMIN,
            "PHOTONENERGYMAX": self.PHOTONENERGYMAX,
            "PHOTONENERGYPOINTS": self.PHOTONENERGYPOINTS,
            "USEEMITTANCES": self.USEEMITTANCES,
            "h5_file": h5_file,
            "h5_entry_name": "XOPPY_RADIATION",
            "h5_initialize": True
        }

        # write python script in standard output
        print(self.script_template().format_map(dict_parameters))

        return xoppy_calc_undulator_radiation(
            ELECTRONENERGY=self.ELECTRONENERGY,
            ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD,
            ELECTRONCURRENT=self.ELECTRONCURRENT,
            ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH,
            ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV,
            ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH,
            ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV,
            PERIODID=self.PERIODID,
            NPERIODS=self.NPERIODS,
            KV=self.KV,
            DISTANCE=self.DISTANCE,
            SETRESONANCE=self.SETRESONANCE,
            HARMONICNUMBER=self.HARMONICNUMBER,
            GAPH=self.GAPH,
            GAPV=self.GAPV,
            HSLITPOINTS=self.HSLITPOINTS,
            VSLITPOINTS=self.VSLITPOINTS,
            METHOD=self.METHOD,
            PHOTONENERGYMIN=self.PHOTONENERGYMIN,
            PHOTONENERGYMAX=self.PHOTONENERGYMAX,
            PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS,
            USEEMITTANCES=self.USEEMITTANCES,
            h5_file=h5_file,
            h5_entry_name="XOPPY_RADIATION",
            h5_initialize=True,
            h5_parameters=dict_parameters,
        )

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:undulator_radiation)
#
from orangecontrib.xoppy.util.xoppy_undulators import xoppy_calc_undulator_radiation
e, h, v, p, code = xoppy_calc_undulator_radiation(
        ELECTRONENERGY           = {ELECTRONENERGY},
        ELECTRONENERGYSPREAD     = {ELECTRONENERGYSPREAD},
        ELECTRONCURRENT          = {ELECTRONCURRENT},
        ELECTRONBEAMSIZEH        = {ELECTRONBEAMSIZEH},
        ELECTRONBEAMSIZEV        = {ELECTRONBEAMSIZEV},
        ELECTRONBEAMDIVERGENCEH  = {ELECTRONBEAMDIVERGENCEH},
        ELECTRONBEAMDIVERGENCEV  = {ELECTRONBEAMDIVERGENCEV},
        PERIODID                 = {PERIODID},
        NPERIODS                 = {NPERIODS},
        KV                       = {KV},
        DISTANCE                 = {DISTANCE},
        SETRESONANCE             = {SETRESONANCE},
        HARMONICNUMBER           = {HARMONICNUMBER},
        GAPH                     = {GAPH},
        GAPV                     = {GAPV},
        HSLITPOINTS              = {HSLITPOINTS},
        VSLITPOINTS              = {VSLITPOINTS},
        METHOD                   = {METHOD},
        PHOTONENERGYMIN          = {PHOTONENERGYMIN},
        PHOTONENERGYMAX          = {PHOTONENERGYMAX},
        PHOTONENERGYPOINTS       = {PHOTONENERGYPOINTS},
        USEEMITTANCES            = {USEEMITTANCES},
        h5_file                  = "{h5_file}",
        h5_entry_name            = "XOPPY_RADIATION",
        h5_initialize            = True,
        )

# example plot
from srxraylib.plot.gol import plot_image
plot_image(p[0],h,v,title="Flux [photons/s] per 0.1 bw per mm2 at %f eV"%({PHOTONENERGYMIN}),xtitle="H [mm]",ytitle="V [mm]")
#
# end script
#
"""

    def extract_data_from_xoppy_output(self, calculation_output):
        e, h, v, p, code = calculation_output

        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())

        calculated_data.add_content("xoppy_data", [p, e, h, v])
        calculated_data.add_content("xoppy_code", code)

        return calculated_data

    def get_data_exchange_widget_name(self):
        return "UNDULATOR_RADIATION"

    def getTitles(self):
        return [
            'Undulator Flux vs E,X,Y', 'Undulator Power Density vs X,Y',
            'Undulator Flux vs E', 'Undulator Spectral Power vs E'
        ]

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KV = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):
        if value == True:
            self.id_ELECTRONENERGY.setEnabled(True)
            self.id_ELECTRONENERGYSPREAD.setEnabled(True)
            self.id_ELECTRONBEAMSIZEH.setEnabled(True)
            self.id_ELECTRONBEAMSIZEV.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
            self.id_ELECTRONCURRENT.setEnabled(True)
            self.id_PERIODID.setEnabled(True)
            self.id_NPERIODS.setEnabled(True)
            self.id_KV.setEnabled(True)
        else:
            self.id_ELECTRONENERGY.setEnabled(False)
            self.id_ELECTRONENERGYSPREAD.setEnabled(False)
            self.id_ELECTRONBEAMSIZEH.setEnabled(False)
            self.id_ELECTRONBEAMSIZEV.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
            self.id_ELECTRONCURRENT.setEnabled(False)
            self.id_PERIODID.setEnabled(False)
            self.id_NPERIODS.setEnabled(False)
            self.id_KV.setEnabled(False)
Exemple #12
0
class OWEllipticalMirror(WiseWidget, WidgetDecorator):
    name = "EllipticalMirror"
    id = "EllipticalMirror"
    description = "EllipticalMirror"
    icon = "icons/elliptical_mirror.png"
    priority = 2
    category = ""
    keywords = ["wise", "elliptical"]

    inputs = [("Input", WiseOutput, "set_input"), ("PreInput", WisePreInputData, "set_pre_input")]

    WidgetDecorator.append_syned_input_data(inputs)

    f1 = Setting(98000)
    f2 = Setting(1200)
    alpha = Setting(2)
    length = Setting(400)
    use_figure_error = Setting(0)
    figure_error_file = Setting("figure_error.dat")
    figure_error_step = Setting(0.002)
    figure_error_um_conversion = Setting(1.0)
    use_roughness = Setting(0)
    roughness_file = Setting("roughness.dat")
    roughness_x_scaling = Setting(1.0)
    roughness_y_scaling = Setting(1.0)
    roughness_fit_data = Setting(0)
    calculation_type = Setting(0)
    number_of_points = Setting(0)
    detector_size = Setting(50)
    calculated_number_of_points = 0

    input_data = None

    def set_input(self, input_data):
        self.setStatusMessage("")

        if not input_data is None:
            if input_data.has_optical_element():
                QMessageBox.critical(self, "Error", "Propagation from previous O.E. not yet supported", QMessageBox.Ok)

                self.setStatusMessage("Error!")

            self.input_data = input_data

            if self.is_automatic_run: self.compute()

    def set_pre_input(self, data):
        if data is not None:
            if data.figure_error_file != WisePreInputData.NONE:
                self.figure_error_file = data.figure_error_file
                self.figure_error_step = data.figure_error_step
                self.figure_error_um_conversion = data.figure_user_units_to_m
                self.use_figure_error = 1

                self.set_UseFigureError()

            if data.roughness_file != WisePreInputData.NONE:
                self.roughness_file=data.roughness_file
                self.roughness_x_scaling = data.roughness_x_scaling
                self.roughness_y_scaling = data.roughness_y_scaling
                self.use_roughness = 1

                self.set_UseRoughness()

    def build_gui(self):

        self.tabs_setting = oasysgui.tabWidget(self.controlArea)
        self.tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT)
        self.tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5)

        self.tab_bas = oasysgui.createTabPage(self.tabs_setting, "Mirror Setting")
        self.tab_pro = oasysgui.createTabPage(self.tabs_setting, "Calculation Setting")

        main_box = oasysgui.widgetBox(self.tab_bas, "Elliptical Mirror Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-20)

        self.le_f1 = oasysgui.lineEdit(main_box, self, "f1", "F1", labelWidth=240, valueType=float, orientation="horizontal")
        self.le_f2 = oasysgui.lineEdit(main_box, self, "f2", "F2", labelWidth=240, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(main_box, self, "alpha", "Incidence Angle [deg]", labelWidth=240, valueType=float, orientation="horizontal")
        self.le_length = oasysgui.lineEdit(main_box, self, "length", "Length", labelWidth=240, valueType=float, orientation="horizontal")

        figure_error_box = oasysgui.widgetBox(self.tab_bas, "Figure Error Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-20)


        gui.comboBox(figure_error_box, self, "use_figure_error", label="Error Profile",
                     items=["None", "User Defined"], labelWidth=240,
                     callback=self.set_UseFigureError, sendSelectedValue=False, orientation="horizontal")

        self.use_figure_error_box = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=80)
        self.use_figure_error_box_empty = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=80)


        file_box =  oasysgui.widgetBox(self.use_figure_error_box, "", addSpace=False, orientation="horizontal")
        self.le_figure_error_file = oasysgui.lineEdit(file_box, self, "figure_error_file", "File Name", labelWidth=100, valueType=str, orientation="horizontal")
        gui.button(file_box, self, "...", callback=self.selectFigureErrorFile)

        self.le_figure_error_step = oasysgui.lineEdit(self.use_figure_error_box, self, "figure_error_step", "Step", labelWidth=240, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.use_figure_error_box, self, "figure_error_um_conversion", "user file u.m. to [m] factor", labelWidth=240, valueType=float, orientation="horizontal")

        self.set_UseFigureError()

        gui.comboBox(figure_error_box, self, "use_roughness", label="roughness",
                     items=["None", "User Defined"], labelWidth=240,
                     callback=self.set_UseRoughness, sendSelectedValue=False, orientation="horizontal")

        self.use_roughness_box = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=110)
        self.use_roughness_box_empty = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=110)

        file_box = oasysgui.widgetBox(self.use_roughness_box, "", addSpace=False, orientation="horizontal")
        self.le_roughness_file = oasysgui.lineEdit(file_box, self, "roughness_file", "File Name", labelWidth=100, valueType=str, orientation="horizontal")
        gui.button(file_box, self, "...", callback=self.selectroughnessFile)

        oasysgui.lineEdit(self.use_roughness_box, self, "roughness_x_scaling", "x user file u.m. to [m]   factor", labelWidth=240, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.use_roughness_box, self, "roughness_y_scaling", "y user file u.m. to [m^3] factor", labelWidth=240, valueType=float, orientation="horizontal")

        gui.comboBox(self.use_roughness_box, self, "roughness_fit_data", label="Fit numeric data with power law",
                     items=["No", "Yes"], labelWidth=240, sendSelectedValue=False, orientation="horizontal")

        self.set_UseRoughness()

        calculation_box = oasysgui.widgetBox(self.tab_pro, "Calculation Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-20)

        gui.comboBox(calculation_box, self, "calculation_type", label="Numeric Integration",
                     items=["Automatic Number of Points", "User Defined Number of Points"], labelWidth=140,
                     callback=self.set_CalculationType, sendSelectedValue=False, orientation="horizontal")


        self.detector_box = oasysgui.widgetBox(calculation_box, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-40)

        oasysgui.lineEdit(self.detector_box, self, "detector_size", "(Hypotetic) Detector Size [" + u"\u03BC" + "m]", labelWidth=240, valueType=float, orientation="horizontal")

        le_calculated_number_of_points = oasysgui.lineEdit(self.detector_box, self, "calculated_number_of_points", "Calculated Number of Points", labelWidth=240, valueType=float, orientation="horizontal")
        le_calculated_number_of_points.setReadOnly(True)
        font = QFont(le_calculated_number_of_points.font())
        font.setBold(True)
        le_calculated_number_of_points.setFont(font)
        palette = QPalette(le_calculated_number_of_points.palette())
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 160))
        le_calculated_number_of_points.setPalette(palette)

        self.number_box = oasysgui.widgetBox(calculation_box, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-40)

        oasysgui.lineEdit(self.number_box, self, "number_of_points", "Number of Points", labelWidth=240, valueType=int, orientation="horizontal")

        self.set_CalculationType()

    def selectFigureErrorFile(self):
        self.le_figure_error_file.setText(oasysgui.selectFileFromDialog(self, self.figure_error_file, "Select File", file_extension_filter="Data Files (*.dat *.txt)"))

    def selectroughnessFile(self):
        self.le_roughness_file.setText(oasysgui.selectFileFromDialog(self, self.roughness_file, "Select File", file_extension_filter="Data Files (*.dat *.txt)"))

    def set_UseFigureError(self):
        self.use_figure_error_box.setVisible(self.use_figure_error == 1)
        self.use_figure_error_box_empty.setVisible(self.use_figure_error == 0)

    def set_UseRoughness(self):
        self.use_roughness_box.setVisible(self.use_roughness == 1)
        self.use_roughness_box_empty.setVisible(self.use_roughness == 0)

    def set_CalculationType(self):
        self.detector_box.setVisible(self.calculation_type==0)
        self.number_box.setVisible(self.calculation_type==1)

    def after_change_workspace_units(self):
        label = self.le_f1.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_f2.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_length.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_figure_error_step.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

    def check_fields(self):
        self.f1 = congruence.checkStrictlyPositiveNumber(self.f1, "F1")
        self.f2 = congruence.checkStrictlyPositiveNumber(self.f2, "F2")
        self.alpha = congruence.checkAngle(self.alpha, "Incidence Angle")
        self.length = congruence.checkStrictlyPositiveNumber(self.length, "Length")

        if self.use_figure_error == 1:
            congruence.checkFileName(self.figure_error_file)

        if self.use_roughness == 1:
            congruence.checkFileName(self.roughness_file)

        if self.calculation_type == 0: #auto
            self.detector_size = congruence.checkStrictlyPositiveNumber(self.detector_size, "Detector Size")
        else:
            self.number_of_points = congruence.checkStrictlyPositiveNumber(self.number_of_points, "Number of Points")

    def do_wise_calculation(self):
        if self.input_data is None:
            raise Exception("No Input Data!")

        elliptic_mirror = Optics.Ellipse(f1 = self.f1 * self.workspace_units_to_m,
                                         f2 = self.f2 * self.workspace_units_to_m,
                                         Alpha = numpy.radians(self.alpha),
                                         L = self.length * self.workspace_units_to_m)

        if self.use_figure_error == 1:
            elliptic_mirror.FigureErrorAdd(numpy.loadtxt(self.figure_error_file) * self.figure_error_um_conversion,
                                           self.figure_error_step * self.workspace_units_to_m) # (m)



        if self.use_roughness == 1:
            elliptic_mirror.Roughness.NumericPsdLoadXY(self.roughness_file,
                                                       xScaling = self.roughness_x_scaling * self.workspace_units_to_m,
                                                       yScaling = self.roughness_y_scaling * self.workspace_units_to_m,
                                                       xIsSpatialFreq = False)
            elliptic_mirror.Roughness.Options.FIT_NUMERIC_DATA_WITH_POWER_LAW = (self.roughness_fit_data == 1)
            elliptic_mirror.Options.USE_ROUGHNESS = True
        else:
            elliptic_mirror.Options.USE_ROUGHNESS = False

        #------------------------------------------------------------

        source = self.input_data.get_source()

        if source.get_property("source_on_mirror_focus"):
            longitudinal_correction = float(source.get_property("longitudinal_correction"))
            transverse_correction   = float(source.get_property("transverse_correction"))
            delta_theta             = float(source.get_property("delta_theta"))

            if longitudinal_correction == 0.0:
                if transverse_correction == 0.0:
                    alpha = 0
                else:
                    alpha = elliptic_mirror.p1_Angle + numpy.sign(transverse_correction)*numpy.pi/2
            else:
                alpha = elliptic_mirror.p1_Angle + numpy.arctan(transverse_correction/longitudinal_correction)

            defocus = numpy.sqrt(longitudinal_correction**2 + transverse_correction**2)

            theta = elliptic_mirror.p1_Angle + delta_theta
            z_origin = elliptic_mirror.XYF1[0] + defocus*numpy.cos(alpha)
            y_origin = elliptic_mirror.XYF1[1] + defocus*numpy.sin(alpha)

            print("theta (deg)", numpy.degrees(theta), "Z", z_origin, "Y", y_origin)

            if (isinstance(source.inner_wise_source, Optics.GaussianSource_1d)):
                source.inner_wise_source = Optics.GaussianSource_1d(source.inner_wise_source.Lambda,
                                                                    source.inner_wise_source.Waist0,
                                                                    ZOrigin=z_origin,
                                                                    YOrigin=y_origin,
                                                                    Theta=theta)
            elif (isinstance(source.inner_wise_source, Optics.PointSource_1d)):
                source.inner_wise_source = Optics.GaussianSource_1d(source.inner_wise_source.Lambda,
                                                                    XOrigin=z_origin,
                                                                    YOrigin=y_origin)
            else:
                source.inner_wise_source.ZOrigin = z_origin
                source.inner_wise_source.YOrigin = y_origin
                source.inner_wise_source.ThetaPropagation = theta

        if self.calculation_type == WiseNumericalIntegrationParameters.AUTOMATIC:
            detector_size = self.detector_size*1e-6
            number_of_points = -1
        else:
            detector_size = 0.0
            number_of_points = self.number_of_points

        numerical_integration_parameters = WiseNumericalIntegrationParameters(self.calculation_type, detector_size, number_of_points)

        propagation_parameter = WisePropagationParameters(propagation_type=WisePropagationParameters.MIRROR_ONLY,
                                                          source=source.inner_wise_source,
                                                          optical_element=elliptic_mirror,
                                                          numerical_integration_parameters=numerical_integration_parameters)

        propagation_output = WisePropagatorsChain.Instance().do_propagation(propagation_parameter,
                                                                            WisePropagationAlgorithms.HuygensIntegral)


        if self.calculation_type == WiseNumericalIntegrationParameters.AUTOMATIC:
            self.calculated_number_of_points = propagation_output.number_of_points
        else:
            self.calculated_number_of_points = 0

        wavefront_out = WiseWavefront(propagation_output.mir_x,
                                      propagation_output.mir_y,
                                      propagation_output.mir_s,
                                      propagation_output.mir_E,
                                      propagation_output.residuals)


        numerical_integration_parameters_out = WiseNumericalIntegrationParameters(self.calculation_type,
                                                                                  detector_size,
                                                                                  number_of_points,
                                                                                  propagation_output.number_of_points)

        optical_element_out = WiseOpticalElement(inner_wise_optical_element=elliptic_mirror)

        data_to_plot = numpy.zeros((5, len(propagation_output.mir_s)))
        data_to_plot[0, :] = propagation_output.mir_s / self.workspace_units_to_m
        data_to_plot[1, :] = Amp(propagation_output.mir_E)**2
        data_to_plot[2, :] = Cyc(propagation_output.mir_E)

        if len(propagation_output.residuals) > 0:
            figure_error_x = numpy.linspace(0, self.length, len(propagation_output.residuals))
            data_to_plot_fe = numpy.zeros((2, len(figure_error_x)))

            data_to_plot_fe[0, :] = figure_error_x
            data_to_plot_fe[1, :] = propagation_output.residuals*1e9 # nm
        else:
            data_to_plot_fe = numpy.zeros((2, 1))

            data_to_plot_fe[0, :] = numpy.zeros(1)
            data_to_plot_fe[1, :] = numpy.zeros(1)

        return source, optical_element_out, wavefront_out, numerical_integration_parameters_out, data_to_plot, data_to_plot_fe

    def getTabTitles(self):
        return ["Field Intensity (mirror)", "Optical Cycles (mirror)", "Figure Error"]

    def getTitles(self):
        return ["Field Intensity (mirror)", "Optical Cycles (mirror)", "Figure Error"]

    def getXTitles(self):
        return ["rho [" + self.workspace_units_label + "]", "Z [" + self.workspace_units_label + "]", "Z [$\mu$m]"]

    def getYTitles(self):
        return ["|E0|**2", "Optical Cycles", "Height Error [nm]"]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2), (0, 1)]

    def getLogPlot(self):
        return [(False, False), (False, False), (False, False)]

    def extract_plot_data_from_calculation_output(self, calculation_output):
        return calculation_output[4], calculation_output[5]


    def plot_results(self, plot_data, progressBarValue=80):
        if not self.view_type == 0:
            if not plot_data is None:

                plot_data_1 = plot_data[0]
                plot_data_2 = plot_data[1]

                self.view_type_combo.setEnabled(False)

                titles = self.getTitles()
                xtitles = self.getXTitles()
                ytitles = self.getYTitles()

                progress_bar_step = (100-progressBarValue)/len(titles)

                for index in range(0, len(titles)):
                    x_index, y_index = self.getVariablesToPlot()[index]
                    log_x, log_y = self.getLogPlot()[index]

                    try:
                        if index < 2:
                            self.plot_histo(plot_data_1[x_index, :],
                                            plot_data_1[y_index, :],
                                            progressBarValue + ((index+1)*progress_bar_step),
                                            tabs_canvas_index=index,
                                            plot_canvas_index=index,
                                            title=titles[index],
                                            xtitle=xtitles[index],
                                            ytitle=ytitles[index],
                                            log_x=log_x,
                                            log_y=log_y)
                        else:
                            self.plot_histo(plot_data_2[x_index, :],
                                            plot_data_2[y_index, :],
                                            progressBarValue + ((index+1)*progress_bar_step),
                                            tabs_canvas_index=index,
                                            plot_canvas_index=index,
                                            title=titles[index],
                                            xtitle=xtitles[index],
                                            ytitle=ytitles[index],
                                            log_x=log_x,
                                            log_y=log_y)

                        self.tabs.setCurrentIndex(index)
                    except Exception as e:
                        self.view_type_combo.setEnabled(True)

                        raise Exception("Data not plottable: bad content\n" + str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")


    def extract_wise_output_from_calculation_output(self, calculation_output):
        return WiseOutput(source=calculation_output[0],
                          optical_element=calculation_output[1],
                          wavefront=calculation_output[2],
                          numerical_integration_parameters=calculation_output[3])


    def receive_syned_data(self, data):
        if not data is None:
            beamline_element = data.get_beamline_element_at(-1)

            if beamline_element is None:
                raise Exception("Syned Data not correct: Empty Beamline Element")

            optical_element = beamline_element._optical_element

            if optical_element is None:
                raise Exception("Syned Data not correct: Empty Optical Element")

            if not isinstance(optical_element, Mirror):
                raise Exception("Syned Data not correct: Optical Element is not a Mirror")

            if not isinstance(optical_element._surface_shape, Ellipsoid):
                raise Exception("Syned Data not correct: Mirror Surface Shape is not Elliptical")

            self.alpha = round(numpy.degrees(0.5*numpy.pi-beamline_element._coordinates._angle_radial), 4)

            boundaries = optical_element._boundary_shape.get_boundaries()

            tangential_size=round(abs(boundaries[3] - boundaries[2])/self.workspace_units_to_m, 6)
            sagittal_size=round(abs(boundaries[1] - boundaries[0])/self.workspace_units_to_m, 6)

            axis = QInputDialog.getItem(self, "Projection Axis", "Select Direction", ("Horizontal", "Vertical"), 0, False)

            if axis == 0:
                self.length = sagittal_size
            else:
                self.length = tangential_size

            p, q = optical_element._surface_shape.get_p_q(numpy.radians(self.alpha))

            self.f1 = numpy.round(p/self.workspace_units_to_m, 6)
            self.f2 = numpy.round(q/self.workspace_units_to_m, 6)
Exemple #13
0
class OWundulator_radiation(XoppyWidget, WidgetDecorator):
    name = "Undulator Radiation"
    id = "orange.widgets.dataundulator_radiation"
    description = "Undulator Radiation"
    icon = "icons/xoppy_undulator_radiation.png"
    priority = 5
    category = ""
    keywords = ["xoppy", "undulator_radiation"]

    USEEMITTANCES=Setting(1)
    ELECTRONENERGY = Setting(6.04)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(0.000395)
    ELECTRONBEAMSIZEV = Setting(9.9e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05)
    ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06)

    PERIODID = Setting(0.018)
    NPERIODS = Setting(222)
    KV = Setting(1.68)

    DISTANCE = Setting(30.0)
    SETRESONANCE = Setting(0)
    HARMONICNUMBER = Setting(1)

    GAPH = Setting(0.003)
    GAPV = Setting(0.003)
    HSLITPOINTS = Setting(41)
    VSLITPOINTS = Setting(41)

    PHOTONENERGYMIN = Setting(6000.0)
    PHOTONENERGYMAX = Setting(8500.0)
    PHOTONENERGYPOINTS = Setting(20)


    METHOD = Setting(2)

    inputs = [WidgetDecorator.syned_input_data()]


    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5)
        
        idx = -1 

        #
        #
        #


        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1, self, "USEEMITTANCES",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['No', 'Yes'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 0 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONENERGY = oasysgui.lineEdit(box1, self, "ELECTRONENERGY",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 1 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(box1, self, "ELECTRONENERGYSPREAD",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 2 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(box1, self, "ELECTRONCURRENT",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 3 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEH",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 4 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 5 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEH",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 6 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 7 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 8 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 


        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1, self, "KV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)




        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "DISTANCE",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)



        # widget <><><>
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1, self, "SETRESONANCE",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['User defined', 'Set to resonance/central cone','Set to resonance/up to first ring'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget <><><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "HARMONICNUMBER",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)


        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "GAPH",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "GAPV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "HSLITPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "VSLITPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)


        
        #widget index 15 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "METHOD",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['US', 'URGENT', 'SRW','pySRU'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 

    def unitLabels(self):
        return ["Use emittances","Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]",
                "Electron Beam Size H [m]", "Electron Beam Size V [m]","Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]",
                "Period ID [m]", "Number of periods","Kv [undulator K value vertical field]",
                "Distance to slit [m]",
                "Set photon energy and slit","Harmonic number",
                "Slit gap H [m]", "Slit gap V [m]",
                "Number of slit mesh points in H", "Number of slit mesh points in V",
                "Photon Energy Min [eV]","Photon Energy Max [eV]","Number of Photon Energy Points",
                "calculation code"]

    # TODO check energy spread flag: set to False (not used at all)!!
    def unitFlags(self):
        return ["True", "True", "False", "True",
                "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1","self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1",
                "True", "True", "True",
                "True",
                "True", "self.SETRESONANCE > 0",
                "self.SETRESONANCE == 0", "self.SETRESONANCE == 0",
                "True", "True",
                "self.SETRESONANCE == 0", "self.SETRESONANCE == 0","self.SETRESONANCE == 0",
                "True"]

    def get_help_name(self):
        return 'undulator_radiation'

    def check_fields(self):
        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkNumber(self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkNumber(self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")

        self.PHOTONENERGYMIN = congruence.checkNumber(self.PHOTONENERGYMIN, "Photon Energy Min")
        self.PHOTONENERGYMAX = congruence.checkNumber(self.PHOTONENERGYMAX, "Photon Energy Max")
        self.PHOTONENERGYPOINTS = congruence.checkStrictlyPositiveNumber(self.PHOTONENERGYPOINTS, "Number of Photon Energy Points")

        self.PERIODID = congruence.checkStrictlyPositiveNumber(self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.DISTANCE = congruence.checkStrictlyPositiveNumber(self.DISTANCE, "Distance to slit")

        self.HARMONICNUMBER = congruence.checkStrictlyPositiveNumber(self.HARMONICNUMBER, "Harminic number")

        self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
        self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
        self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber(self.HSLITPOINTS, "Number of slit mesh points in H")
        self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber(self.VSLITPOINTS, "Number of slit mesh points in V")

        if  self.METHOD == 1: # URGENT
            congruence.checkLessOrEqualThan(self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT "," 51")
            congruence.checkLessOrEqualThan(self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT "," 51")

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:

                self.initializeTabs() # added by srio to avoid overlapping graphs

                self.view_type_combo.setEnabled(False)

                p,e,h,v = calculated_data.get_content("xoppy_data")
                code = calculated_data.get_content("xoppy_code")


                try:
                    self.plot_data3D(p, e, h, v, 0, 0,
                                     xtitle='H [mm]',
                                     ytitle='V [mm]',
                                     title='Code '+code+'; Flux [photons/s/0.1%bw/mm^2]',)

                    self.tabs.setCurrentIndex(0)
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" + str(e))

                try:
                    self.plot_data2D(p.sum(axis=0)*(e[1]-e[0])*codata.e*1e3, h, v, 1, 0,
                                     xtitle='H [mm]',
                                     ytitle='V [mm]',
                                     title='Code '+code+'; Power density [W/mm^2]',)

                    # self.tabs.setCurrentIndex(1)
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" + str(e))


                try:
                    print("Result arrays (shapes): ",e.shape,h.shape,v.shape,p.shape)
                    self.plot_data1D(e,p.sum(axis=2).sum(axis=1)*(h[1]-h[0])*(v[1]-v[0]), 2, 0,
                                     xtitle='Photon Energy [eV]',
                                     ytitle= 'Flux [photons/s/0.1%bw/mm^2]',
                                     title='Code '+code+'; Flux',)

                    # self.tabs.setCurrentIndex(2)
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    raise Exception("Data not plottable: bad content\n" + str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")





    def do_xoppy_calculation(self):
        return xoppy_calc_undulator_radiation(ELECTRONENERGY=self.ELECTRONENERGY,
                    ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD,
                    ELECTRONCURRENT=self.ELECTRONCURRENT,
                    ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH,
                    ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV,
                    ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH,
                    ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV,
                    PERIODID=self.PERIODID,
                    NPERIODS=self.NPERIODS,
                    KV=self.KV,
                    DISTANCE=self.DISTANCE,
                    SETRESONANCE=self.SETRESONANCE,
                    HARMONICNUMBER=self.HARMONICNUMBER,
                    GAPH=self.GAPH,
                    GAPV=self.GAPV,
                    HSLITPOINTS=self.HSLITPOINTS,
                    VSLITPOINTS=self.VSLITPOINTS,
                    METHOD=self.METHOD,
                    PHOTONENERGYMIN=self.PHOTONENERGYMIN,
                    PHOTONENERGYMAX=self.PHOTONENERGYMAX,
                    PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS,
                    USEEMITTANCES=self.USEEMITTANCES)

    def extract_data_from_xoppy_output(self, calculation_output):
        e, h, v, p, code = calculation_output

        calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name())

        calculated_data.add_content("xoppy_data", [p, e, h, v])
        calculated_data.add_content("xoppy_code", code)

        return calculated_data


    def get_data_exchange_widget_name(self):
        return "UNDULATOR_RADIATION"

    def getTitles(self):
        return ['Undulator Flux','Undulator Power Density','Undulator Spectrum']


    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(data._light_source._magnetic_structure, synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KV = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self,value):
        if value == True:
                self.id_ELECTRONENERGY.setEnabled(True)
                self.id_ELECTRONENERGYSPREAD.setEnabled(True)
                self.id_ELECTRONBEAMSIZEH.setEnabled(True)
                self.id_ELECTRONBEAMSIZEV.setEnabled(True)
                self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
                self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
                self.id_ELECTRONCURRENT.setEnabled(True)
                self.id_PERIODID.setEnabled(True)
                self.id_NPERIODS.setEnabled(True)
                self.id_KV.setEnabled(True)
        else:
                self.id_ELECTRONENERGY.setEnabled(False)
                self.id_ELECTRONENERGYSPREAD.setEnabled(False)
                self.id_ELECTRONBEAMSIZEH.setEnabled(False)
                self.id_ELECTRONBEAMSIZEV.setEnabled(False)
                self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
                self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
                self.id_ELECTRONCURRENT.setEnabled(False)
                self.id_PERIODID.setEnabled(False)
                self.id_NPERIODS.setEnabled(False)
                self.id_KV.setEnabled(False)
Exemple #14
0
class Source(ow_generic_element.GenericElement):

    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    category = "Sources"
    keywords = ["data", "file", "load", "read"]

    inputs = [("Trigger", TriggerOut, "sendNewBeam")]

    WidgetDecorator.append_syned_input_data(inputs)

    outputs = [{"name":"Beam",
                "type":ShadowBeam,
                "doc":"Shadow Beam",
                "id":"beam"}]

    file_to_write_out = Setting(0)

    want_main_area=1

    TABS_AREA_HEIGHT = 618
    CONTROL_AREA_WIDTH = 405

    number_of_rays=Setting(5000)
    seed=Setting(5676561)

    def __init__(self, show_automatic_box=False):
        super().__init__(show_automatic_box=show_automatic_box)

        self.runaction = widget.OWAction("Copy Source Parameters", self)
        self.runaction.triggered.connect(self.copy_src_parameters)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Paste Source Parameters", self)
        self.runaction.triggered.connect(self.paste_src_parameters)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Run Shadow/Source", self)
        self.runaction.triggered.connect(self.runShadowSource)
        self.addAction(self.runaction)

        self.general_options_box.setVisible(False)

        button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")

        button = gui.button(button_box, self, "Run Shadow/Source", callback=self.runShadowSource)
        font = QFont(button.font())
        font.setBold(True)
        button.setFont(font)
        palette = QPalette(button.palette()) # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Blue'))
        button.setPalette(palette) # assign new palette
        button.setFixedHeight(45)

        button = gui.button(button_box, self, "Reset Fields", callback=self.callResetSettings)
        font = QFont(button.font())
        font.setItalic(True)
        button.setFont(font)
        palette = QPalette(button.palette()) # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Red'))
        button.setPalette(palette) # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(150)

        gui.separator(self.controlArea)

    def get_write_file_options(self):
        write_begin_file = 0
        write_start_file = 0
        write_end_file = 0

        if self.file_to_write_out == 1:
            write_begin_file = 1
        if self.file_to_write_out == 2:
            write_begin_file = 1

            if sys.platform == 'linux':
                QMessageBox.warning(self, "Warning", "Debug Mode is not yet available for sources in Linux platforms", QMessageBox.Ok)
            else:
                write_start_file = 1
                write_end_file = 1

        return write_begin_file, write_start_file, write_end_file

    def copy_src_parameters(self):
        global shadow_src_to_copy

        shadow_src_to_copy = ShadowSource.create_src()

        self.populateFields(shadow_src_to_copy)

        shadow_src_to_copy.set_source_type(self.__class__.__name__)

    def paste_src_parameters(self):
        global shadow_src_to_copy

        if not shadow_src_to_copy is None:
            try:
                if "BendingMagnet" in shadow_src_to_copy.source_type and not "BendingMagnet" in str(self.__class__):
                    raise Exception("Paste Parameters not allowed:\nDestination Source is not a BendingMagnet")
                elif "Undulator" in shadow_src_to_copy.source_type and not "Undulator" in str(self.__class__):
                    raise Exception("Paste Parameters not allowed:\nDestination Source is not an Undulator")
                elif "Geometrical" in shadow_src_to_copy.source_type and not "Geometrical" in str(self.__class__):
                    raise Exception("Paste Parameters not allowed:\nDestination Source is not a Geometrical Source")
                elif "Wiggler" in shadow_src_to_copy.source_type and not "Wiggler" in str(self.__class__):
                    raise Exception("Paste Parameters not allowed:\nDestination Source is not a Wiggler")

                if QMessageBox.information(self, "Confirm Operation",
                                              "Confirm Paste Operation?",
                                              QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
                    shadow_temp_file = congruence.checkFileName("tmp_src_buffer.dat")
                    shadow_src_to_copy.src.write(shadow_temp_file)

                    shadow_file, type = ShadowFile.readShadowFile(shadow_temp_file)

                    self.deserialize(shadow_file)

            except Exception as exception:
                QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)


    def sendNewBeam(self, trigger):
        if trigger and trigger.new_object == True:
            if trigger.has_additional_parameter("seed_increment"):
                self.seed += trigger.get_additional_parameter("seed_increment")

            self.runShadowSource()

    def populateFields(self, shadow_src):
        pass

    def deserialize(self, shadow_file):
        pass
Exemple #15
0
class OWundulator_spectrum(XoppyWidget, WidgetDecorator):
    name = "Undulator Spectrum"
    id = "orange.widgets.dataundulator_spectrum"
    description = "Undulator Spectrum"
    icon = "icons/xoppy_undulator_spectrum.png"
    priority = 1
    category = ""
    keywords = ["xoppy", "undulator_spectrum"]

    USEEMITTANCES=Setting(1)
    ELECTRONENERGY = Setting(6.04)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(0.000395)
    ELECTRONBEAMSIZEV = Setting(9.9e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05)
    ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06)
    PERIODID = Setting(0.018)
    NPERIODS = Setting(222)
    KV = Setting(1.68)
    DISTANCE = Setting(30.0)
    GAPH = Setting(0.001)
    GAPV = Setting(0.001)
    PHOTONENERGYMIN = Setting(3000.0)
    PHOTONENERGYMAX = Setting(55000.0)
    PHOTONENERGYPOINTS = Setting(500)
    METHOD = Setting(0)

    inputs = [WidgetDecorator.syned_input_data()]

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5)

        idx = -1



        #
        #
        #


        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1, self, "USEEMITTANCES",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['No', 'Yes'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)




        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(box1, self, "ELECTRONENERGY",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(box1, self, "ELECTRONENERGYSPREAD",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(box1, self, "ELECTRONCURRENT",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEH",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEH",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1, self, "KV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "DISTANCE",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "GAPH",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "GAPV",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1, self, "METHOD",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['US', 'URGENT', 'SRW'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
         return ["Use emittances","Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods", "Kv [undulator K value vertical field]", "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "photon Energy Min [eV]", "photon Energy Max [eV]", "photon Energy Points", "calculation code"]

    def unitFlags(self):
         return ["True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True", "True", "True", "True", "True", "True"]

    def get_help_name(self):
        return 'undulator_spectrum'

    def check_fields(self):
        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber(self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber(self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")
        self.PERIODID = congruence.checkStrictlyPositiveNumber(self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit")
        self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
        self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
        self.PHOTONENERGYMIN = congruence.checkPositiveNumber(self.PHOTONENERGYMIN, "photon Energy Min")
        self.PHOTONENERGYMAX = congruence.checkStrictlyPositiveNumber(self.PHOTONENERGYMAX, "photon Energy Max")
        congruence.checkLessThan(self.PHOTONENERGYMIN, self.PHOTONENERGYMAX, "photon Energy Min", "photon Energy Max")
        self.PHOTONENERGYPOINTS = congruence.checkStrictlyPositiveNumber(self.PHOTONENERGYPOINTS, "photon Energy Points")

        if self.METHOD == 1: # URGENT
            congruence.checkLessThan(self.PHOTONENERGYPOINTS,4701,"Number of energy points","4701")

        # if sys.platform == 'linux' and self.METHOD == 2:
        #     raise Exception("SRW calculation code not supported under Linux")

    def do_xoppy_calculation(self):
        return xoppy_calc_undulator_spectrum(ELECTRONENERGY=self.ELECTRONENERGY,
                                             ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD,
                                             ELECTRONCURRENT=self.ELECTRONCURRENT,
                                             ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH,
                                             ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV,
                                             ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH,
                                             ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV,
                                             PERIODID=self.PERIODID,
                                             NPERIODS=self.NPERIODS,
                                             KV=self.KV,
                                             DISTANCE=self.DISTANCE,
                                             GAPH=self.GAPH,
                                             GAPV=self.GAPV,
                                             PHOTONENERGYMIN=self.PHOTONENERGYMIN,
                                             PHOTONENERGYMAX=self.PHOTONENERGYMAX,
                                             PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS,
                                             METHOD=self.METHOD,
                                             USEEMITTANCES=self.USEEMITTANCES)

    def extract_data_from_xoppy_output(self, calculation_output):
        e, f, sp = calculation_output

        data = numpy.zeros((len(e), 3))
        data[:, 0] = numpy.array(e)
        data[:, 1] = numpy.array(f)
        data[:, 2] = numpy.array(sp)

        calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name())
        calculated_data.add_content("xoppy_data", data)

        return calculated_data

    def get_data_exchange_widget_name(self):
        return "UNDULATOR_FLUX"

    def getTitles(self):
        return ['Undulator Flux', 'Spectral Power']

    def getXTitles(self):
        return ["Energy [eV]", "Energy [eV]"]

    def getYTitles(self):
        return ["Flux [Phot/sec/0.1%bw]", "Spectral Power [W/eV]"]

    def getLogPlot(self):
        return [(False, False), (False, False)]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2)]

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(data._light_source._magnetic_structure, synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KV = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self,value):
        if value == True:
                self.id_ELECTRONENERGY.setEnabled(True)
                self.id_ELECTRONENERGYSPREAD.setEnabled(True)
                self.id_ELECTRONBEAMSIZEH.setEnabled(True)
                self.id_ELECTRONBEAMSIZEV.setEnabled(True)
                self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
                self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
                self.id_ELECTRONCURRENT.setEnabled(True)
                self.id_PERIODID.setEnabled(True)
                self.id_NPERIODS.setEnabled(True)
                self.id_KV.setEnabled(True)
        else:
                self.id_ELECTRONENERGY.setEnabled(False)
                self.id_ELECTRONENERGYSPREAD.setEnabled(False)
                self.id_ELECTRONBEAMSIZEH.setEnabled(False)
                self.id_ELECTRONBEAMSIZEV.setEnabled(False)
                self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
                self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
                self.id_ELECTRONCURRENT.setEnabled(False)
                self.id_PERIODID.setEnabled(False)
                self.id_NPERIODS.setEnabled(False)
                self.id_KV.setEnabled(False)
Exemple #16
0
class PowerLoopPoint(widget.OWWidget):

    name = "Power Density Loop Point"
    description = "Tools: LoopPoint"
    icon = "icons/cycle.png"
    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    priority = 5
    category = "User Defined"
    keywords = ["data", "file", "load", "read"]

    inputs = WidgetDecorator.syned_input_data()
    inputs.append(("Trigger", TriggerIn, "passTrigger"))
    inputs.append(
        ("Energy Spectrum", DataExchangeObject, "acceptEnergySpectrum"))
    inputs.append(("Filters", DataExchangeObject, "acceptFilters"))

    outputs = [{
        "name": "Trigger",
        "type": TriggerOut,
        "doc": "Trigger",
        "id": "Trigger"
    }]
    want_main_area = 1

    current_new_object = 0
    number_of_new_objects = 0

    total_current_new_object = 0
    total_new_objects = Setting(0)

    run_loop = True
    suspend_loop = False

    energies = Setting("")

    seed_increment = Setting(1)

    autobinning = Setting(1)

    auto_n_step = Setting(1001)
    auto_perc_total_power = Setting(99)

    send_power_step = Setting(0)

    electron_energy = Setting(6.0)
    K_vertical = Setting(1.943722)
    K_horizontal = Setting(0.0)
    period_length = Setting(0.025)
    number_of_periods = Setting(184)
    theta_x = Setting(0.0)
    theta_z = Setting(0.0)

    current_energy_binning = -1
    current_energy_value = None
    current_energy_step = None
    current_power_step = None

    energy_binnings = None

    external_binning = False

    filters = None
    spectrum_data = None

    #################################
    process_last = True

    #################################

    def __init__(self):
        self.runaction = OWAction("Start", self)
        self.runaction.triggered.connect(self.startLoop)
        self.addAction(self.runaction)

        self.runaction = OWAction("Stop", self)
        self.runaction.triggered.connect(self.stopLoop)
        self.addAction(self.runaction)

        self.runaction = OWAction("Suspend", self)
        self.runaction.triggered.connect(self.suspendLoop)
        self.addAction(self.runaction)

        self.runaction = OWAction("Restart", self)
        self.runaction.triggered.connect(self.restartLoop)
        self.addAction(self.runaction)

        self.setFixedWidth(1200)
        self.setFixedHeight(710)

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=True,
                                        orientation="horizontal")

        self.start_button = gui.button(button_box,
                                       self,
                                       "Start",
                                       callback=self.startLoop)
        self.start_button.setFixedHeight(35)

        stop_button = gui.button(button_box,
                                 self,
                                 "Stop",
                                 callback=self.stopLoop)
        stop_button.setFixedHeight(35)
        font = QFont(stop_button.font())
        font.setBold(True)
        stop_button.setFont(font)
        palette = QPalette(stop_button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('red'))
        stop_button.setPalette(palette)  # assign new palette

        self.stop_button = stop_button

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=True,
                                        orientation="horizontal")

        suspend_button = gui.button(button_box,
                                    self,
                                    "Suspend",
                                    callback=self.suspendLoop)
        suspend_button.setFixedHeight(35)
        font = QFont(suspend_button.font())
        font.setBold(True)
        suspend_button.setFont(font)
        palette = QPalette(
            suspend_button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('orange'))
        suspend_button.setPalette(palette)  # assign new palette

        self.re_start_button = gui.button(button_box,
                                          self,
                                          "Restart",
                                          callback=self.restartLoop)
        self.re_start_button.setFixedHeight(35)
        self.re_start_button.setEnabled(False)

        tabs = oasysgui.tabWidget(self.controlArea)
        tab_loop = oasysgui.createTabPage(tabs, "Loop Management")
        tab_und = oasysgui.createTabPage(tabs, "Undulator")

        left_box_2 = oasysgui.widgetBox(tab_und,
                                        "Parameters From Syned",
                                        addSpace=False,
                                        orientation="vertical",
                                        width=385,
                                        height=560)

        oasysgui.lineEdit(left_box_2,
                          self,
                          "electron_energy",
                          "Ring Energy [GeV]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal").setReadOnly(True)
        oasysgui.lineEdit(left_box_2,
                          self,
                          "number_of_periods",
                          "Number of Periods",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal").setReadOnly(True)
        oasysgui.lineEdit(left_box_2,
                          self,
                          "period_length",
                          "Undulator Period [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal").setReadOnly(True)
        oasysgui.lineEdit(left_box_2,
                          self,
                          "K_vertical",
                          "K Vertical",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal").setReadOnly(True)
        oasysgui.lineEdit(left_box_2,
                          self,
                          "K_horizontal",
                          "K Horizontal",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal").setReadOnly(True)

        left_box_1 = oasysgui.widgetBox(tab_loop,
                                        "",
                                        addSpace=False,
                                        orientation="vertical",
                                        width=385,
                                        height=560)

        oasysgui.lineEdit(left_box_1,
                          self,
                          "seed_increment",
                          "Source Montecarlo Seed Increment",
                          labelWidth=250,
                          valueType=int,
                          orientation="horizontal")

        gui.separator(left_box_1)

        gui.comboBox(left_box_1,
                     self,
                     "autobinning",
                     label="Energy Binning",
                     items=[
                         "Manual", "Automatic (Constant Power)",
                         "Automatic (Constant Energy)"
                     ],
                     labelWidth=150,
                     callback=self.set_Autobinning,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.autobinning_box_1 = oasysgui.widgetBox(left_box_1,
                                                    "",
                                                    addSpace=False,
                                                    orientation="vertical",
                                                    height=50)
        self.autobinning_box_2 = oasysgui.widgetBox(left_box_1,
                                                    "",
                                                    addSpace=False,
                                                    orientation="vertical",
                                                    height=140)

        # ----------------------------------------------

        gui.button(self.autobinning_box_1,
                   self,
                   "Compute Bins",
                   callback=self.calculate_energy_binnings)

        oasysgui.widgetLabel(self.autobinning_box_1,
                             "Energy From, Energy To, Energy Step [eV]")

        # ----------------------------------------------

        oasysgui.lineEdit(self.autobinning_box_2,
                          self,
                          "auto_n_step",
                          "Number of Steps",
                          labelWidth=250,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(self.autobinning_box_2,
                          self,
                          "auto_perc_total_power",
                          "% Total Power",
                          labelWidth=250,
                          valueType=float,
                          orientation="horizontal")
        gui.comboBox(self.autobinning_box_2,
                     self,
                     "send_power_step",
                     label="Send Power Step",
                     items=["No", "Yes"],
                     labelWidth=350,
                     sendSelectedValue=False,
                     orientation="horizontal")

        button_box = oasysgui.widgetBox(self.autobinning_box_2,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        gui.button(button_box,
                   self,
                   "Reload Spectrum and Filters",
                   callback=self.read_spectrum_and_filters_file)
        gui.button(button_box,
                   self,
                   "Reload Spectrum Only",
                   callback=self.read_spectrum_file_only)

        oasysgui.widgetLabel(
            self.autobinning_box_2,
            "Energy Value [eV], Energy Step [eV], Power Step [W]")

        def write_text():
            self.energies = self.text_area.toPlainText()

        self.text_area = oasysgui.textArea(height=95,
                                           width=385,
                                           readOnly=False)
        self.text_area.setText(self.energies)
        self.text_area.setStyleSheet(
            "background-color: white; font-family: Courier, monospace;")
        self.text_area.textChanged.connect(write_text)

        left_box_1.layout().addWidget(self.text_area)

        gui.separator(left_box_1)

        self.le_number_of_new_objects = oasysgui.lineEdit(
            left_box_1,
            self,
            "total_new_objects",
            "Total Energy Values",
            labelWidth=250,
            valueType=int,
            orientation="horizontal")
        self.le_number_of_new_objects.setReadOnly(True)
        font = QFont(self.le_number_of_new_objects.font())
        font.setBold(True)
        self.le_number_of_new_objects.setFont(font)
        palette = QPalette(self.le_number_of_new_objects.palette()
                           )  # make a copy of the palette
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 160))
        self.le_number_of_new_objects.setPalette(palette)

        self.le_number_of_new_objects = oasysgui.lineEdit(
            left_box_1,
            self,
            "number_of_new_objects",
            "Current Binning Energy Values",
            labelWidth=250,
            valueType=int,
            orientation="horizontal")
        self.le_number_of_new_objects.setReadOnly(True)
        font = QFont(self.le_number_of_new_objects.font())
        font.setBold(True)
        self.le_number_of_new_objects.setFont(font)
        palette = QPalette(self.le_number_of_new_objects.palette()
                           )  # make a copy of the palette
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 160))
        self.le_number_of_new_objects.setPalette(palette)

        gui.separator(left_box_1)

        le_current_value = oasysgui.lineEdit(left_box_1,
                                             self,
                                             "total_current_new_object",
                                             "Total New " +
                                             self.get_object_name(),
                                             labelWidth=250,
                                             valueType=int,
                                             orientation="horizontal")
        le_current_value.setReadOnly(True)
        font = QFont(le_current_value.font())
        font.setBold(True)
        le_current_value.setFont(font)
        palette = QPalette(
            le_current_value.palette())  # make a copy of the palette
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 160))
        le_current_value.setPalette(palette)

        le_current_value = oasysgui.lineEdit(left_box_1,
                                             self,
                                             "current_new_object",
                                             "Current Binning New " +
                                             self.get_object_name(),
                                             labelWidth=250,
                                             valueType=int,
                                             orientation="horizontal")
        le_current_value.setReadOnly(True)
        font = QFont(le_current_value.font())
        font.setBold(True)
        le_current_value.setFont(font)
        palette = QPalette(
            le_current_value.palette())  # make a copy of the palette
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 160))
        le_current_value.setPalette(palette)

        le_current_value = oasysgui.lineEdit(left_box_1,
                                             self,
                                             "current_energy_value",
                                             "Current Energy Value",
                                             labelWidth=250,
                                             valueType=float,
                                             orientation="horizontal")
        le_current_value.setReadOnly(True)
        font = QFont(le_current_value.font())
        font.setBold(True)
        le_current_value.setFont(font)
        palette = QPalette(
            le_current_value.palette())  # make a copy of the palette
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 160))
        le_current_value.setPalette(palette)

        gui.rubber(self.controlArea)

        tabs = oasysgui.tabWidget(self.mainArea)
        tabs.setFixedHeight(self.height() - 15)
        tabs.setFixedWidth(775)

        tab_plot = oasysgui.createTabPage(tabs, "Cumulated Power")
        tab_flux = oasysgui.createTabPage(tabs, "Spectral Flux")
        tab_fil = oasysgui.createTabPage(tabs, "Filter")

        self.cumulated_power_plot = oasysgui.plotWindow(tab_plot,
                                                        position=True)
        self.cumulated_power_plot.setFixedHeight(self.height() - 20)
        self.cumulated_power_plot.setFixedWidth(775)
        self.cumulated_power_plot.setGraphXLabel("Energy [eV]")
        self.cumulated_power_plot.setGraphYLabel("Cumulated Power [W]")
        self.cumulated_power_plot.setGraphTitle("Cumulated Power")

        self.spectral_flux_plot = oasysgui.plotWindow(tab_flux, position=True)
        self.spectral_flux_plot.setFixedHeight(self.height() - 20)
        self.spectral_flux_plot.setFixedWidth(775)
        self.spectral_flux_plot.setGraphXLabel("Energy [eV]")
        self.spectral_flux_plot.setGraphYLabel("Flux [ph/s/.1%bw]")
        self.spectral_flux_plot.setGraphTitle("Spectral Flux")

        self.filter_plot = oasysgui.plotWindow(tab_fil, position=True)
        self.filter_plot.setFixedHeight(self.height() - 20)
        self.filter_plot.setFixedWidth(775)
        self.filter_plot.setGraphXLabel("Energy [eV]")
        self.filter_plot.setGraphYLabel("Intensity Factor")
        self.filter_plot.setGraphTitle("Filter on Flux")

        self.set_Autobinning()

    def set_Autobinning(self):
        self.autobinning_box_1.setVisible(self.autobinning == 0)
        self.autobinning_box_2.setVisible(self.autobinning == 1
                                          or self.autobinning == 2)
        self.text_area.setReadOnly(self.autobinning >= 1)
        self.text_area.setFixedHeight(201 if self.autobinning >= 1 else 290)

    def read_spectrum_file(self, reset_filters=True):
        try:
            if reset_filters:
                self.filters = None
                self.filter_plot.clear()

            data = numpy.loadtxt("autobinning.dat", skiprows=1)

            calculated_data = DataExchangeObject(program_name="ShadowOui",
                                                 widget_name="PowerLoopPoint")
            calculated_data.add_content("spectrum_data", data)

            self.acceptEnergySpectrum(calculated_data)
        except Exception as e:
            QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)

            if self.IS_DEVELOP: raise e

    def read_spectrum_file_only(self):
        self.read_spectrum_file(True)

    def read_spectrum_and_filters_file(self):
        try:
            data = numpy.loadtxt("filters.dat", skiprows=1)

            calculated_data = DataExchangeObject(program_name="ShadowOui",
                                                 widget_name="PowerLoopPoint")
            calculated_data.add_content("filters_data", data)

            self.acceptFilters(calculated_data)
        except Exception:
            self.filters = None

        self.read_spectrum_file(False)

    def receive_syned_data(self, data):
        if not data is None:
            try:
                if not data._light_source is None and isinstance(
                        data._light_source, LightSource):
                    light_source = data._light_source

                    self.electron_energy = light_source._electron_beam._energy_in_GeV

                    self.K_horizontal = light_source._magnetic_structure._K_horizontal
                    self.K_vertical = light_source._magnetic_structure._K_vertical
                    self.period_length = light_source._magnetic_structure._period_length
                    self.number_of_periods = light_source._magnetic_structure._number_of_periods
                else:
                    raise ValueError("Syned data not correct")
            except Exception as exception:
                QMessageBox.critical(self, "Error", str(exception),
                                     QMessageBox.Ok)

                if self.IS_DEVELOP: raise exception

    def receive_specific_syned_data(self, data):
        raise NotImplementedError()

    def acceptFilters(self, exchange_data):
        if not exchange_data is None:
            try:  # FROM XOPPY F1F2
                write_file = True

                try:
                    data = exchange_data.get_content("filters_data")
                    write_file = False
                except:
                    if not exchange_data.get_program_name() == "XOPPY":
                        raise ValueError(
                            "Only XOPPY F1F2 and CRYSTAL widgets are accepted")

                    if exchange_data.get_widget_name() == "XF1F2":
                        data = exchange_data.get_content("xoppy_data")
                    elif exchange_data.get_widget_name() == "XCRYSTAL":
                        data = exchange_data.get_content("xoppy_data")
                        cols = data.shape[1]
                        data = exchange_data.get_content("xoppy_data")[
                            0:cols:cols - 1, 0:cols:cols - 1]
                    elif exchange_data.get_widget_name() == "MLAYER":
                        data = exchange_data.get_content("xoppy_data")[0:3:2,
                                                                       0:3:2]

                self.filters = data

                energies = self.filters[:, 0]
                intensity_factors = self.filters[:, 1]

                if write_file:
                    file = open("filters.dat", "w")
                    file.write("Energy Filter")

                    for energy, intensity_factor in zip(
                            energies, intensity_factors):
                        file.write("\n" + str(energy) + " " +
                                   str(intensity_factor))

                    file.flush()
                    file.close()

                self.filter_plot.clear()
                self.filter_plot.addCurve(energies,
                                          intensity_factors,
                                          replace=True,
                                          legend="Intensity Factor")
                self.filter_plot.setGraphXLabel("Energy [eV]")
                self.filter_plot.setGraphYLabel("Intensity Factor")
                self.filter_plot.setGraphTitle("Filter on Flux")

                if self.autobinning == 0:
                    if write_file:
                        QMessageBox.information(
                            self, "Info",
                            "File filters.dat written on working directory, switch to Automatic binning to load it",
                            QMessageBox.Ok)
                else:
                    if write_file:
                        QMessageBox.information(
                            self, "Info",
                            "File filters.dat written on working directory",
                            QMessageBox.Ok)

                if not self.spectrum_data is None:
                    calculated_data = DataExchangeObject(
                        program_name="ShadowOui", widget_name="PowerLoopPoint")
                    calculated_data.add_content("spectrum_data",
                                                self.spectrum_data)

                    self.acceptEnergySpectrum(calculated_data)

            except Exception as e:
                QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)

                if self.IS_DEVELOP: raise e

    def acceptEnergySpectrum(self, exchange_data):
        if not exchange_data is None:
            try:
                write_file = True

                try:
                    data = exchange_data.get_content("spectrum_data")
                    write_file = False
                except:
                    try:
                        data = exchange_data.get_content("srw_data")
                    except:
                        data = exchange_data.get_content("xoppy_data")

                self.spectrum_data = data.copy()

                energies = data[:, 0]
                flux_through_finite_aperture = data[:, 1]
                flux_through_finite_aperture_filtered = flux_through_finite_aperture.copy(
                )

                if not self.filters is None:
                    flux_through_finite_aperture_filtered *= numpy.interp(
                        energies, self.filters[:, 0], self.filters[:, 1])

                if write_file:
                    file = open("autobinning.dat", "w")
                    file.write("Energy Flux")

                    for energy, flux in zip(energies,
                                            flux_through_finite_aperture):
                        file.write("\n" + str(energy) + " " + str(flux))

                    file.flush()
                    file.close()

                if self.autobinning == 0:
                    if write_file:
                        QMessageBox.information(
                            self, "Info",
                            "File autobinning.dat written on working directory, switch to Automatic binning to load it",
                            QMessageBox.Ok)
                else:
                    if write_file:
                        QMessageBox.information(
                            self, "Info",
                            "File autobinning.dat written on working directory",
                            QMessageBox.Ok)

                    congruence.checkStrictlyPositiveNumber(
                        self.auto_n_step, "(Auto) % Number of Steps")
                    congruence.checkStrictlyPositiveNumber(
                        self.auto_perc_total_power, "(Auto) % Total Power")

                    energy_step = energies[1] - energies[0]

                    # last energy do not contribute to the total (the approximated integral of the power is out of the range)

                    power = flux_through_finite_aperture * (1e3 * energy_step *
                                                            codata.e)
                    cumulated_power = numpy.cumsum(power)
                    total_power = cumulated_power[-1]

                    if not self.filters is None:
                        power_filtered = flux_through_finite_aperture_filtered * (
                            1e3 * energy_step * codata.e)
                        cumulated_power_filtered = numpy.cumsum(power_filtered)
                        total_power_filtered = cumulated_power_filtered[-1]

                    self.text_area.clear()

                    self.cumulated_power_plot.clear()
                    self.spectral_flux_plot.clear()

                    good = numpy.where(
                        cumulated_power <= self.auto_perc_total_power * 0.01 *
                        total_power)

                    energies = energies[good]
                    cumulated_power = cumulated_power[good]
                    flux_through_finite_aperture = flux_through_finite_aperture[
                        good]

                    if not self.filters is None:
                        cumulated_power_filtered = cumulated_power_filtered[
                            good]
                        flux_through_finite_aperture_filtered = flux_through_finite_aperture_filtered[
                            good]

                    if self.autobinning == 1:  # constant power
                        interpolated_cumulated_power = numpy.linspace(
                            start=numpy.min(cumulated_power),
                            stop=numpy.max(cumulated_power),
                            num=self.auto_n_step + 1)
                        interpolated_energies = numpy.interp(
                            interpolated_cumulated_power, cumulated_power,
                            energies)
                        energy_steps = numpy.ediff1d(interpolated_energies)

                        interpolated_energies = interpolated_energies[:-1]
                        interpolated_cumulated_power = interpolated_cumulated_power[:
                                                                                    -1]

                        power_steps = numpy.ones(
                            self.auto_n_step
                        ) * cumulated_power[-1] / self.auto_n_step

                    elif self.autobinning == 2:  # constant energy
                        minimum_energy = energies[0]
                        maximum_energy = energies[-1]
                        energy_step = (maximum_energy -
                                       minimum_energy) / self.auto_n_step

                        interpolated_energies = numpy.arange(
                            minimum_energy, maximum_energy, energy_step)
                        interpolated_cumulated_power = numpy.interp(
                            interpolated_energies, energies, cumulated_power)

                        energy_steps = numpy.ones(
                            self.auto_n_step) * energy_step
                        power_steps = numpy.ediff1d(
                            numpy.append(numpy.zeros(1),
                                         interpolated_cumulated_power))

                    flux_steps = numpy.interp(interpolated_energies, energies,
                                              flux_through_finite_aperture)

                    self.energy_binnings = []
                    self.total_new_objects = 0

                    self.cumulated_power_plot.addCurve(
                        energies,
                        cumulated_power,
                        replace=True,
                        legend="Cumulated Power")
                    if not self.filters is None:
                        self.cumulated_power_plot.addCurve(
                            energies,
                            cumulated_power_filtered,
                            replace=False,
                            legend="Cumulated Power Filters",
                            linestyle="--",
                            color="#006400")
                    self.cumulated_power_plot.setGraphXLabel("Energy [eV]")
                    self.cumulated_power_plot.setGraphYLabel("Cumulated " + (
                        "" if self.filters is None else " (Filtered)") +
                                                             " Power")
                    if self.filters is None:
                        self.cumulated_power_plot.setGraphTitle(
                            "Total Power: " +
                            str(round(power_steps.sum(), 2)) + " W")
                    else:
                        self.cumulated_power_plot.setGraphTitle(
                            "Total (Filtered) Power: " +
                            str(round(power_steps.sum(), 2)) + "  (" +
                            str(round(total_power_filtered, 2)) + ") W")

                    self.spectral_flux_plot.addCurve(
                        energies,
                        flux_through_finite_aperture,
                        replace=True,
                        legend="Spectral Flux")
                    if not self.filters is None:
                        self.spectral_flux_plot.addCurve(
                            energies,
                            flux_through_finite_aperture_filtered,
                            replace=False,
                            legend="Spectral Flux Filters",
                            linestyle="--",
                            color="#006400")
                    self.spectral_flux_plot.setGraphXLabel("Energy [eV]")
                    self.spectral_flux_plot.setGraphYLabel("Flux [ph/s/.1%bw]")
                    self.spectral_flux_plot.setGraphTitle("Spectral Flux" + (
                        "" if self.filters is None else " (Filtered)"))

                    self.cumulated_power_plot.addCurve(
                        interpolated_energies,
                        interpolated_cumulated_power,
                        replace=False,
                        legend="Energy Binning",
                        color="red",
                        linestyle=" ",
                        symbol="+")

                    self.spectral_flux_plot.addCurve(interpolated_energies,
                                                     flux_steps,
                                                     replace=False,
                                                     legend="Energy Binning",
                                                     color="red",
                                                     linestyle=" ",
                                                     symbol="+")

                    text = ""

                    for energy_value, energy_step, power_step in zip(
                            interpolated_energies, energy_steps, power_steps):
                        energy_binning = EnergyBinning(
                            energy_value=round(energy_value, 3),
                            energy_step=round(energy_step, 3),
                            power_step=round(power_step, 4))

                        text += str(round(energy_value, 3)) + ", " + \
                                str(round(energy_step, 3))  + ", " + \
                                str(round(power_step, 4)) + "\n"

                        self.energy_binnings.append(energy_binning)
                        self.total_new_objects += 1

                    self.text_area.setText(text)

                    self.external_binning = True
            except Exception as e:
                QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)

                if self.IS_DEVELOP: raise e
        else:
            self.energy_binnings = None
            self.total_new_objects = 0
            self.external_binning = False
            self.text_area.setText("")

    def calculate_energy_binnings(self):
        if not self.external_binning:
            self.total_new_objects = 0

            rows = self.energies.split("\n")
            for row in rows:
                data = row.split(",")
                if len(data) == 3:
                    if self.energy_binnings is None: self.energy_binnings = []

                    energy_from = float(data[0].strip())
                    energy_to = float(data[1].strip())
                    energy_step = float(data[2].strip())

                    energy_binning = EnergyBinning(energy_value=energy_from,
                                                   energy_value_to=energy_to,
                                                   energy_step=energy_step)
                    self.energy_binnings.append(energy_binning)

                    self.total_new_objects += int(
                        (energy_to - energy_from) / energy_step)

    def calculate_number_of_new_objects(self):
        if len(self.energy_binnings) > 0:
            if self.external_binning:
                self.number_of_new_objects = 1
            else:
                energy_binning = self.energy_binnings[
                    self.current_energy_binning]

                self.number_of_new_objects = int(
                    (energy_binning.energy_value_to -
                     energy_binning.energy_value) / energy_binning.energy_step)
        else:
            self.number_of_new_objects = 0

    def reset_values(self):
        self.current_new_object = 0
        self.total_current_new_object = 0
        self.current_energy_value = None
        self.current_energy_step = None
        self.current_energy_binning = -1
        self.current_power_step = None

        if not self.external_binning: self.energy_binnings = None

    def startLoop(self):
        try:
            self.calculate_energy_binnings()

            self.current_new_object = 1
            self.total_current_new_object = 1
            self.current_energy_binning = 0
            self.current_energy_value = round(
                self.energy_binnings[0].energy_value, 8)
            self.current_energy_step = round(
                self.energy_binnings[0].energy_step, 8)
            self.current_power_step = None if self.energy_binnings[
                0].power_step is None else (
                    None if self.send_power_step == 0 else round(
                        self.energy_binnings[0].power_step, 8))
            self.calculate_number_of_new_objects()

            self.start_button.setEnabled(False)
            self.text_area.setEnabled(False)
            self.setStatusMessage("Running " + self.get_object_name() + " " +
                                  str(self.total_current_new_object) + " of " +
                                  str(self.total_new_objects))
            self.send(
                "Trigger",
                TriggerOut(new_object=True,
                           additional_parameters={
                               "energy_value":
                               self.current_energy_value,
                               "energy_step":
                               self.current_energy_step,
                               "power_step":
                               -1 if self.current_power_step is None else
                               self.current_power_step,
                               "seed_increment":
                               self.seed_increment,
                               "start_event":
                               True
                           }))
        except Exception as e:
            if self.IS_DEVELOP: raise e
            else: pass

    def stopLoop(self):
        try:
            if ConfirmDialog.confirmed(
                    parent=self, message="Confirm Interruption of the Loop?"):
                self.run_loop = False
                self.reset_values()
                self.setStatusMessage("Interrupted by user")
        except Exception as e:
            if self.IS_DEVELOP: raise e
            else: pass

    def suspendLoop(self):
        try:
            if ConfirmDialog.confirmed(
                    parent=self, message="Confirm Suspension of the Loop?"):
                self.run_loop = False
                self.suspend_loop = True
                self.stop_button.setEnabled(False)
                self.re_start_button.setEnabled(True)
                self.setStatusMessage("Suspended by user")
        except Exception as e:
            if self.IS_DEVELOP: raise e
            else: pass

    def restartLoop(self):
        try:
            self.run_loop = True
            self.suspend_loop = False
            self.stop_button.setEnabled(True)
            self.re_start_button.setEnabled(False)
            self.passTrigger(TriggerIn(new_object=True))
        except Exception as e:
            if self.IS_DEVELOP: raise e
            else: pass

    def get_object_name(self):
        return "Beam"

    def passTrigger(self, trigger):
        if self.run_loop:
            if trigger:
                if trigger.interrupt:
                    self.reset_values()
                    self.start_button.setEnabled(True)
                    self.text_area.setEnabled(True)
                    self.setStatusMessage("")
                    self.send("Trigger", TriggerOut(new_object=False))
                elif trigger.new_object:
                    if self.energy_binnings is None:
                        self.calculate_energy_binnings()

                    if self.current_energy_binning == -1:
                        QMessageBox.critical(
                            self, "Error",
                            "Power Loop has to be started properly: press the button Start",
                            QMessageBox.Ok)
                        return

                    if self.current_energy_binning < len(self.energy_binnings):
                        energy_binning = self.energy_binnings[
                            self.current_energy_binning]

                        self.total_current_new_object += 1

                        if self.current_new_object < self.number_of_new_objects:
                            if self.current_energy_value is None:
                                self.current_new_object = 1
                                self.calculate_number_of_new_objects()
                                self.current_energy_value = round(
                                    energy_binning.energy_value, 8)
                            else:
                                self.current_new_object += 1
                                self.current_energy_value = round(
                                    self.current_energy_value +
                                    energy_binning.energy_step, 8)

                            self.current_power_step = None if energy_binning.power_step is None else (
                                None if self.send_power_step == 0 else round(
                                    energy_binning.power_step, 8))

                            self.setStatusMessage(
                                "Running " + self.get_object_name() + " " +
                                str(self.total_current_new_object) + " of " +
                                str(self.total_new_objects))
                            self.start_button.setEnabled(False)
                            self.text_area.setEnabled(False)
                            self.send(
                                "Trigger",
                                TriggerOut(
                                    new_object=True,
                                    additional_parameters={
                                        "energy_value":
                                        self.current_energy_value,
                                        "energy_step":
                                        energy_binning.energy_step,
                                        "power_step":
                                        -1 if self.current_power_step is None
                                        else self.current_power_step,
                                        "seed_increment":
                                        self.seed_increment,
                                        "start_event":
                                        False
                                    }))
                        else:
                            self.current_energy_binning += 1

                            if self.current_energy_binning < len(
                                    self.energy_binnings):
                                energy_binning = self.energy_binnings[
                                    self.current_energy_binning]

                                self.current_new_object = 1
                                self.calculate_number_of_new_objects()
                                self.current_energy_value = round(
                                    energy_binning.energy_value, 8)
                                self.current_power_step = None if energy_binning.power_step is None else (
                                    None if self.send_power_step == 0 else
                                    round(energy_binning.power_step, 8))

                                self.setStatusMessage(
                                    "Running " + self.get_object_name() + " " +
                                    str(self.total_current_new_object) +
                                    " of " + str(self.total_new_objects))
                                self.start_button.setEnabled(False)
                                self.text_area.setEnabled(False)
                                self.send(
                                    "Trigger",
                                    TriggerOut(
                                        new_object=True,
                                        additional_parameters={
                                            "energy_value":
                                            self.current_energy_value,
                                            "energy_step":
                                            energy_binning.energy_step,
                                            "power_step":
                                            -1
                                            if self.current_power_step is None
                                            else self.current_power_step,
                                            "seed_increment":
                                            self.seed_increment,
                                            "start_event":
                                            False
                                        }))
                            else:
                                self.reset_values()
                                self.start_button.setEnabled(True)
                                self.text_area.setEnabled(True)
                                self.setStatusMessage("")
                                self.send("Trigger",
                                          TriggerOut(new_object=False))
                    else:
                        self.reset_values()
                        self.start_button.setEnabled(True)
                        self.text_area.setEnabled(True)
                        self.setStatusMessage("")
                        self.send("Trigger", TriggerOut(new_object=False))
        else:
            if not self.suspend_loop:
                self.reset_values()
                self.start_button.setEnabled(True)
                self.text_area.setEnabled(True)

            self.send("Trigger", TriggerOut(new_object=False))
            self.setStatusMessage("")
            self.suspend_loop = False
            self.run_loop = True
class OWSRWGaussianSource(SRWWavefrontViewer, WidgetDecorator):

    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    category = "Sources"
    keywords = ["data", "file", "load", "read"]
    name = "Gaussian Source"
    description = "SRW Source: Gaussian Source"
    icon = "icons/gaussian_source.png"
    priority = 10

    inputs = WidgetDecorator.syned_input_data()
    inputs.append(("Trigger", TriggerOut, "sendNewWavefront"))

    outputs = [{
        "name": "SRWData",
        "type": SRWData,
        "doc": "SRW Source Data",
        "id": "data"
    }]

    want_main_area = 1

    source_name = None

    beam_center_at_waist_x = Setting(0.0)
    beam_center_at_waist_y = Setting(0.0)
    beam_center_at_waist_z = Setting(0.0)
    average_angle_at_waist_x = Setting(0.0)
    average_angle_at_waist_y = Setting(0.0)
    energy_per_pulse = Setting(0.001)
    repetition_rate = Setting(1)
    polarization = Setting(0)
    horizontal_sigma_at_waist = Setting(1e-6)
    vertical_sigma_at_waist = Setting(1e-6)
    pulse_duration = Setting(10e-15)
    transverse_gauss_hermite_mode_order_x = Setting(0)
    transverse_gauss_hermite_mode_order_y = Setting(0)

    wf_photon_energy = Setting(8000.0)
    wf_h_slit_gap = Setting(0.001)
    wf_v_slit_gap = Setting(0.001)
    wf_h_slit_points = Setting(100)
    wf_v_slit_points = Setting(100)
    wf_distance = Setting(10.0)

    wf_sampling_factor_for_adjusting_nx_ny = Setting(0.0)

    TABS_AREA_HEIGHT = 618
    CONTROL_AREA_WIDTH = 405

    def __init__(self, show_automatic_box=False):
        super().__init__(show_automatic_box=show_automatic_box)

        self.runaction = widget.OWAction("Run SRW", self)
        self.runaction.triggered.connect(self.runSRWSource)
        self.addAction(self.runaction)

        self.general_options_box.setVisible(False)

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        button = gui.button(button_box,
                            self,
                            "Run SRW Source",
                            callback=self.runSRWSource)
        font = QFont(button.font())
        font.setBold(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Blue'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)

        button = gui.button(button_box,
                            self,
                            "Reset Fields",
                            callback=self.callResetSettings)
        font = QFont(button.font())
        font.setItalic(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Red'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(150)

        gui.separator(self.controlArea)

        self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)

        self.tabs_setting = oasysgui.tabWidget(self.controlArea)
        self.tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT)
        self.tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5)

        self.tab_source = oasysgui.createTabPage(self.tabs_setting,
                                                 "Light Source Setting")

        left_box_1 = oasysgui.widgetBox(self.tab_source,
                                        "Gaussian Source Parameters",
                                        addSpace=True,
                                        orientation="vertical",
                                        height=380)

        oasysgui.lineEdit(left_box_1,
                          self,
                          "beam_center_at_waist_x",
                          "Beam center at waist x [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "beam_center_at_waist_y",
                          "Beam center at waist y [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "beam_center_at_waist_z",
                          "Beam center at waist z [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "average_angle_at_waist_x",
                          "Average angle at waist x [rad]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "average_angle_at_waist_y",
                          "Average angle at waist y [rad]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "energy_per_pulse",
                          "Energy per pulse [J]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "repetition_rate",
                          "Repetition rate [Hz]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        gui.comboBox(left_box_1,
                     self,
                     "polarization",
                     label="Polarization",
                     items=Polarization.tuple(),
                     labelWidth=150,
                     sendSelectedValue=False,
                     orientation="horizontal")

        oasysgui.lineEdit(left_box_1,
                          self,
                          "horizontal_sigma_at_waist",
                          "\u03c3x at waist [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "vertical_sigma_at_waist",
                          "\u03c3y at waist [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "pulse_duration",
                          "Pulse duration [s]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "transverse_gauss_hermite_mode_order_x",
                          "Transverse Gauss-Hermite mode order x",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(left_box_1,
                          self,
                          "transverse_gauss_hermite_mode_order_y",
                          "Transverse Gauss-Hermite mode order y",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")

        self.tab_plots = oasysgui.createTabPage(self.tabs_setting,
                                                "Wavefront Setting")

        self.tabs_plots_setting = oasysgui.tabWidget(self.tab_plots)

        # PROPAGATION -------------------------------------------

        tab_wav = oasysgui.createTabPage(self.tabs_plots_setting,
                                         "Propagation")

        wav_box = oasysgui.widgetBox(tab_wav,
                                     "Wavefront Parameters",
                                     addSpace=True,
                                     orientation="vertical")

        oasysgui.lineEdit(wav_box,
                          self,
                          "wf_photon_energy",
                          "Photon Energy [eV]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(wav_box,
                          self,
                          "wf_h_slit_gap",
                          "H Slit Gap [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(wav_box,
                          self,
                          "wf_v_slit_gap",
                          "V Slit Gap [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(wav_box,
                          self,
                          "wf_h_slit_points",
                          "H Slit Points",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(wav_box,
                          self,
                          "wf_v_slit_points",
                          "V Slit Points",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")
        oasysgui.lineEdit(wav_box,
                          self,
                          "wf_distance",
                          "Propagation Distance [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        pre_box = oasysgui.widgetBox(tab_wav,
                                     "Precision Parameters",
                                     addSpace=False,
                                     orientation="vertical")

        oasysgui.lineEdit(
            pre_box,
            self,
            "wf_sampling_factor_for_adjusting_nx_ny",
            "Sampling factor for adjusting nx/ny\n(effective if > 0)",
            labelWidth=260,
            valueType=int,
            orientation="horizontal")

        gui.rubber(self.controlArea)

    def runSRWSource(self):
        self.setStatusMessage("")
        self.progressBarInit()

        try:
            self.checkFields()

            srw_source = self.get_srw_source()
            srw_source.name = self.source_name if not self.source_name is None else self.windowTitle(
            ),

            self.progressBarSet(10)

            self.setStatusMessage("Running SRW")

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.progressBarSet(20)

            self.setStatusMessage("")

            beamline = SRWBeamline(light_source=srw_source)
            wavefront = self.calculate_wavefront_propagation(srw_source)

            tickets = []

            if self.is_do_plots():
                self.setStatusMessage("Plotting Results")

                self.run_calculation_intensity(wavefront, tickets)

                self.plot_results(tickets)

            self.setStatusMessage("")

            self.send("SRWData",
                      SRWData(srw_beamline=beamline, srw_wavefront=wavefront))

        except Exception as exception:
            QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)

            if self.IS_DEVELOP: raise exception

        self.progressBarFinished()

    def sendNewWavefront(self, trigger):
        if trigger and trigger.new_object == True:
            self.runSRWSource()

    def get_srw_source(self):
        return SRWGaussianLightSource(
            beam_center_at_waist_x=self.beam_center_at_waist_x,
            beam_center_at_waist_y=self.beam_center_at_waist_y,
            beam_center_at_waist_z=self.beam_center_at_waist_z,
            average_angle_at_waist_x=self.average_angle_at_waist_x,
            average_angle_at_waist_y=self.average_angle_at_waist_y,
            photon_energy=self.wf_photon_energy,
            energy_per_pulse=self.energy_per_pulse,
            repetition_rate=self.repetition_rate,
            polarization=self.polarization + 1,
            horizontal_sigma_at_waist=self.horizontal_sigma_at_waist,
            vertical_sigma_at_waist=self.vertical_sigma_at_waist,
            pulse_duration=self.pulse_duration,
            transverse_gauss_hermite_mode_order_x=self.
            transverse_gauss_hermite_mode_order_x,
            transverse_gauss_hermite_mode_order_y=self.
            transverse_gauss_hermite_mode_order_y)

    def checkFields(self):
        congruence.checkPositiveNumber(self.energy_per_pulse,
                                       "Energy per pulse")
        congruence.checkPositiveNumber(self.horizontal_sigma_at_waist,
                                       "\u03c3x at waist")
        congruence.checkPositiveNumber(self.vertical_sigma_at_waist,
                                       "\u03c3y at waist")
        congruence.checkPositiveNumber(self.pulse_duration, "Pulse duration")
        congruence.checkPositiveNumber(
            self.transverse_gauss_hermite_mode_order_x,
            "Transverse Gauss-Hermite mode order x")
        congruence.checkPositiveNumber(
            self.transverse_gauss_hermite_mode_order_y,
            "Transverse Gauss-Hermite mode order y")

        # WAVEFRONT

        congruence.checkStrictlyPositiveNumber(
            self.wf_photon_energy, "Wavefront Propagation Photon Energy")
        congruence.checkStrictlyPositiveNumber(
            self.wf_h_slit_gap, "Wavefront Propagation H Slit Gap")
        congruence.checkStrictlyPositiveNumber(
            self.wf_v_slit_gap, "Wavefront Propagation V Slit Gap")
        congruence.checkStrictlyPositiveNumber(
            self.wf_h_slit_points, "Wavefront Propagation H Slit Points")
        congruence.checkStrictlyPositiveNumber(
            self.wf_v_slit_points, "Wavefront Propagation V Slit Points")
        congruence.checkPositiveNumber(self.wf_distance,
                                       "Wavefront Propagation Distance")
        congruence.checkPositiveNumber(
            self.wf_sampling_factor_for_adjusting_nx_ny,
            "Wavefront Propagation Sampling Factor for adjusting nx/ny")

    def run_calculation_intensity(self,
                                  srw_wavefront,
                                  tickets,
                                  progress_bar_value=30):

        e, h, v, i = srw_wavefront.get_intensity(multi_electron=False)

        tickets.append(
            SRWPlot.get_ticket_2D(h * 1000, v * 1000, i[int(e.size / 2)]))

        self.progressBarSet(progress_bar_value)

        e, h, v, i = srw_wavefront.get_phase()

        tickets.append(
            SRWPlot.get_ticket_2D(h * 1000, v * 1000, i[int(e.size / 2)]))

        self.progressBarSet(progress_bar_value + 20)

    def calculate_wavefront_propagation(self, srw_source):
        wf_parameters = WavefrontParameters(
            photon_energy_min=self.wf_photon_energy,
            photon_energy_max=self.wf_photon_energy,
            photon_energy_points=1,
            h_slit_gap=self.wf_h_slit_gap,
            v_slit_gap=self.wf_v_slit_gap,
            h_slit_points=self.wf_h_slit_points,
            v_slit_points=self.wf_v_slit_points,
            distance=self.wf_distance,
            wavefront_precision_parameters=WavefrontPrecisionParameters(
                sampling_factor_for_adjusting_nx_ny=self.
                wf_sampling_factor_for_adjusting_nx_ny))

        return srw_source.get_SRW_Wavefront(
            source_wavefront_parameters=wf_parameters)

    def receive_syned_data(self, data):
        if not data is None:
            QMessageBox.critical(
                self, "Error",
                "Syned data not supported for Gaussian Light Source",
                QMessageBox.Ok)

    def getVariablesToPlot(self):
        return [[1, 2], [1, 2]]

    def getTitles(self, with_um=False):
        if with_um: return ["Intensity [ph/s/.1%bw/mm\u00b2]", "Phase [rad]"]
        else: return ["Intensity", "Phase"]

    def getXTitles(self):
        return ["X [\u03bcm]", "X [\u03bcm]"]

    def getYTitles(self):
        return ["Y [\u03bcm]", "Y [\u03bcm]"]

    def getXUM(self):
        return ["X [\u03bcm]", "X [\u03bcm]"]

    def getYUM(self):
        return ["Y [\u03bcm]", "Y [\u03bcm]"]
Exemple #18
0
class Source(ow_generic_element.GenericElement):

    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    category = "Sources"
    keywords = ["data", "file", "load", "read"]

    inputs = [("Trigger", TriggerOut, "sendNewBeam")]

    WidgetDecorator.append_syned_input_data(inputs)

    outputs = [{
        "name": "Beam",
        "type": ShadowBeam,
        "doc": "Shadow Beam",
        "id": "beam"
    }]

    file_to_write_out = Setting(0)

    want_main_area = 1

    TABS_AREA_HEIGHT = 618
    CONTROL_AREA_WIDTH = 405

    number_of_rays = Setting(5000)
    seed = Setting(5676561)

    def __init__(self, show_automatic_box=False):
        super().__init__(show_automatic_box=show_automatic_box)

        self.runaction = widget.OWAction("Copy Source Parameters", self)
        self.runaction.triggered.connect(self.copy_src_parameters)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Paste Source Parameters", self)
        self.runaction.triggered.connect(self.paste_src_parameters)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Run Shadow/Source", self)
        self.runaction.triggered.connect(self.runShadowSource)
        self.addAction(self.runaction)

        self.general_options_box.setVisible(False)

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        button = gui.button(button_box,
                            self,
                            "Run Shadow/Source",
                            callback=self.runShadowSource)
        font = QFont(button.font())
        font.setBold(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Blue'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)

        button = gui.button(button_box,
                            self,
                            "Reset Fields",
                            callback=self.callResetSettings)
        font = QFont(button.font())
        font.setItalic(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Red'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(150)

        gui.separator(self.controlArea)

    def initializeTabs(self):
        current_tab = self.tabs.currentIndex()

        enabled = self.isFootprintEnabled()

        size = len(self.tab)
        indexes = range(0, size)
        for index in indexes:
            self.tabs.removeTab(size - 1 - index)

        show_effective_source_size = QSettings().value(
            "output/show-effective-source-size", 0, int) == 1

        titles = self.getTitles()

        if show_effective_source_size:
            self.tab = [
                oasysgui.createTabPage(self.tabs, titles[0]),
                oasysgui.createTabPage(self.tabs, titles[1]),
                oasysgui.createTabPage(self.tabs, titles[2]),
                oasysgui.createTabPage(self.tabs, titles[3]),
                oasysgui.createTabPage(self.tabs, titles[4]),
                oasysgui.createTabPage(self.tabs, titles[5]),
            ]

            self.plot_canvas = [None, None, None, None, None, None]
        else:
            self.tab = [
                oasysgui.createTabPage(self.tabs, titles[0]),
                oasysgui.createTabPage(self.tabs, titles[1]),
                oasysgui.createTabPage(self.tabs, titles[2]),
                oasysgui.createTabPage(self.tabs, titles[3]),
                oasysgui.createTabPage(self.tabs, titles[4]),
            ]

            self.plot_canvas = [None, None, None, None, None]

        for tab in self.tab:
            tab.setFixedHeight(self.IMAGE_HEIGHT)
            tab.setFixedWidth(self.IMAGE_WIDTH)

        self.enableFootprint(enabled)

        self.tabs.setCurrentIndex(min(current_tab, len(self.tab) - 1))

    def isFootprintEnabled(self):
        return False

    def enableFootprint(self, enabled=False):
        pass

    def get_write_file_options(self):
        write_begin_file = 0
        write_start_file = 0
        write_end_file = 0

        if self.file_to_write_out == 1:
            write_begin_file = 1
        if self.file_to_write_out == 2:
            write_begin_file = 1

            if sys.platform == 'linux':
                QMessageBox.warning(
                    self, "Warning",
                    "Debug Mode is not yet available for sources in Linux platforms",
                    QMessageBox.Ok)
            else:
                write_start_file = 1
                write_end_file = 1

        return write_begin_file, write_start_file, write_end_file

    def copy_src_parameters(self):
        global shadow_src_to_copy

        shadow_src_to_copy = ShadowSource.create_src()

        self.populateFields(shadow_src_to_copy)

        shadow_src_to_copy.set_source_type(self.__class__.__name__)

    def paste_src_parameters(self):
        global shadow_src_to_copy

        if not shadow_src_to_copy is None:
            try:
                if "BendingMagnet" in shadow_src_to_copy.source_type and not "BendingMagnet" in str(
                        self.__class__):
                    raise Exception(
                        "Paste Parameters not allowed:\nDestination Source is not a BendingMagnet"
                    )
                elif "Undulator" in shadow_src_to_copy.source_type and not "Undulator" in str(
                        self.__class__):
                    raise Exception(
                        "Paste Parameters not allowed:\nDestination Source is not an Undulator"
                    )
                elif "Geometrical" in shadow_src_to_copy.source_type and not "Geometrical" in str(
                        self.__class__):
                    raise Exception(
                        "Paste Parameters not allowed:\nDestination Source is not a Geometrical Source"
                    )
                elif "Wiggler" in shadow_src_to_copy.source_type and not "Wiggler" in str(
                        self.__class__):
                    raise Exception(
                        "Paste Parameters not allowed:\nDestination Source is not a Wiggler"
                    )

                if QMessageBox.information(
                        self, "Confirm Operation", "Confirm Paste Operation?",
                        QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
                    shadow_temp_file = congruence.checkFileName(
                        "tmp_src_buffer.dat")
                    shadow_src_to_copy.src.write(shadow_temp_file)

                    shadow_file, type = ShadowFile.readShadowFile(
                        shadow_temp_file)

                    self.deserialize(shadow_file)

            except Exception as exception:
                QMessageBox.critical(self, "Error", str(exception),
                                     QMessageBox.Ok)

    def sendNewBeam(self, trigger):
        if trigger and trigger.new_object == True:
            if trigger.has_additional_parameter("seed_increment"):
                self.seed += trigger.get_additional_parameter("seed_increment")

            self.runShadowSource()

    def populateFields(self, shadow_src):
        pass

    def deserialize(self, shadow_file):
        pass

    def plot_results(self, beam_out, footprint_beam=None, progressBarValue=80):
        show_effective_source_size = QSettings().value(
            "output/show-effective-source-size", 0, int) == 1

        if show_effective_source_size:
            if len(self.tab) == 5: self.initializeTabs()
        else:
            if len(self.tab) == 6: self.initializeTabs()

        super().plot_results(beam_out, footprint_beam, progressBarValue)

        if show_effective_source_size and not self.view_type == 2:
            effective_source_size_beam = beam_out.duplicate(history=False)
            effective_source_size_beam._beam.retrace(0)

            variables = self.getVariablestoPlot()
            titles = self.getTitles()
            xtitles = self.getXTitles()
            ytitles = self.getYTitles()
            xums = self.getXUM()
            yums = self.getYUM()

            if self.view_type == 1:
                self.plot_xy_fast(effective_source_size_beam,
                                  100,
                                  variables[0][0],
                                  variables[0][1],
                                  plot_canvas_index=5,
                                  title=titles[0],
                                  xtitle=xtitles[0],
                                  ytitle=ytitles[0])
            elif self.view_type == 0:
                self.plot_xy(effective_source_size_beam,
                             100,
                             variables[0][0],
                             variables[0][1],
                             plot_canvas_index=5,
                             title=titles[0],
                             xtitle=xtitles[0],
                             ytitle=ytitles[0],
                             xum=xums[0],
                             yum=yums[0])

    def runShadowSource(self):
        raise NotImplementedError("This method is abstract")

    def getTitles(self):
        return [
            "X,Z", "X',Z'", "X,X'", "Z,Z'", "Energy", "Effective Source Size"
        ]
Exemple #19
0
class OWws(XoppyWidget, WidgetDecorator):
    name = "WS"
    id = "orange.widgets.dataws"
    description = "Wiggler Spectrum on a Screen"
    icon = "icons/xoppy_ws.png"
    priority = 11
    category = ""
    keywords = ["xoppy", "ws"]

    ENERGY = Setting(7.0)
    CUR = Setting(100.0)
    PERIOD = Setting(8.5)
    N = Setting(28)
    KX = Setting(0.0)
    KY = Setting(8.74)
    EMIN = Setting(1000.0)
    EMAX = Setting(200000.0)
    NEE = Setting(500)
    D = Setting(30.0)
    XPC = Setting(0.0)
    YPC = Setting(0.0)
    XPS = Setting(2.0)
    YPS = Setting(2.0)
    NXP = Setting(10)
    NYP = Setting(10)

    inputs = WidgetDecorator.syned_input_data()

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ENERGY = oasysgui.lineEdit(box1,
                                           self,
                                           "ENERGY",
                                           label=self.unitLabels()[idx],
                                           addSpace=False,
                                           valueType=float,
                                           validator=QDoubleValidator(),
                                           orientation="horizontal",
                                           labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_CUR = oasysgui.lineEdit(box1,
                                        self,
                                        "CUR",
                                        label=self.unitLabels()[idx],
                                        addSpace=False,
                                        valueType=float,
                                        validator=QDoubleValidator(),
                                        orientation="horizontal",
                                        labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIOD = oasysgui.lineEdit(box1,
                                           self,
                                           "PERIOD",
                                           label=self.unitLabels()[idx],
                                           addSpace=False,
                                           valueType=float,
                                           validator=QDoubleValidator(),
                                           orientation="horizontal",
                                           labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_N = oasysgui.lineEdit(box1,
                                      self,
                                      "N",
                                      label=self.unitLabels()[idx],
                                      addSpace=False,
                                      valueType=float,
                                      validator=QDoubleValidator(),
                                      orientation="horizontal",
                                      labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        # COMMENTED AS IT IS NOT IMPLEMENTED!!
        #widget index 5
        # idx += 1
        # box1 = gui.widgetBox(box)
        # oasysgui.lineEdit(box1, self, "KX",
        #              label=self.unitLabels()[idx], addSpace=False,
        #             valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        # self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KY = oasysgui.lineEdit(box1,
                                       self,
                                       "KY",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       validator=QDoubleValidator(),
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "EMIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "EMAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "NEE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "D",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "XPC",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "YPC",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "XPS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "YPS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "NXP",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "NYP",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        # return ['Beam energy (GeV)','Beam current (mA)','Period (cm)','Number of periods','Kx','Ky','Min energy (eV)','Max energy (eV)','Number of energy steps','Distance (m)','X-pos. (mm)','Y-pos. (mm)','X slit [mm or mrad]','Y slit [mm or mrad]','Integration points X','Integration points Y']
        return [
            'Beam energy (GeV)', 'Beam current (mA)', 'Period (cm)',
            'Number of periods', 'Ky', 'Min energy (eV)', 'Max energy (eV)',
            'Number of energy steps', 'Distance (m)', 'X-pos. (mm)',
            'Y-pos. (mm)', 'X slit [mm or mrad]', 'Y slit [mm or mrad]',
            'Integration points X', 'Integration points Y'
        ]

    def unitFlags(self):
        return [
            'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True',
            'True', 'True', 'True', 'True', 'True', 'True', 'True'
        ]

    def get_help_name(self):
        return 'ws'

    def check_fields(self):
        self.ENERGY = congruence.checkStrictlyPositiveNumber(
            self.ENERGY, "Beam Energy")
        self.CUR = congruence.checkStrictlyPositiveNumber(
            self.CUR, "Beam Current")
        self.PERIOD = congruence.checkStrictlyPositiveNumber(
            self.PERIOD, "Period")
        self.N = congruence.checkStrictlyPositiveNumber(
            self.N, "Number of Periods")
        self.KX = congruence.checkNumber(self.KX, "Kx")
        self.KY = congruence.checkNumber(self.KY, "Ky")
        self.EMIN = congruence.checkPositiveNumber(self.EMIN, "Min Energy")
        self.EMAX = congruence.checkStrictlyPositiveNumber(
            self.EMAX, "Max Energy")
        congruence.checkLessThan(self.EMIN, self.EMAX, "Min Energy",
                                 "Max Energy")
        self.NEE = congruence.checkStrictlyPositiveNumber(
            self.NEE, "Number of energy steps")
        self.D = congruence.checkPositiveNumber(self.D, "Distance")
        self.XPC = congruence.checkNumber(self.XPC, "X-pos")
        self.YPC = congruence.checkNumber(self.YPC, "Y-pos")
        self.XPS = congruence.checkNumber(self.XPS, "X slit")
        self.YPS = congruence.checkNumber(self.YPS, "Y Slit")
        self.NXP = congruence.checkStrictlyPositiveNumber(
            self.NXP, "Integration points X")
        self.NYP = congruence.checkStrictlyPositiveNumber(
            self.NYP, "Integration points Y")

    def do_xoppy_calculation(self):
        return xoppy_calc_ws(ENERGY=self.ENERGY,
                             CUR=self.CUR,
                             PERIOD=self.PERIOD,
                             N=self.N,
                             KX=self.KX,
                             KY=self.KY,
                             EMIN=self.EMIN,
                             EMAX=self.EMAX,
                             NEE=self.NEE,
                             D=self.D,
                             XPC=self.XPC,
                             YPC=self.YPC,
                             XPS=self.XPS,
                             YPS=self.YPS,
                             NXP=self.NXP,
                             NYP=self.NYP)

    def get_data_exchange_widget_name(self):
        return "WS"

    def getTitles(self):
        return ['Flux', 'Spectral power', 'Cumulated power']

    def getXTitles(self):
        return ["Energy [eV]", "Energy [eV]", "Energy [eV]"]

    def getYTitles(self):
        return [
            "Flux [Photons/sec/0.1%bw]", "Spectral Power [W/eV]",
            "Cumulated Power [W]"
        ]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2), (0, 3)]

    def getLogPlot(self):
        return [(True, True), (True, True), (False, False)]

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.N = int(
                    light_source._magnetic_structure._number_of_periods)
                self.ENERGY = light_source._electron_beam._energy_in_GeV
                self.CUR = 1e3 * light_source._electron_beam._current
                self.PERIOD = 1e2 * light_source._magnetic_structure._period_length
                self.KY = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
        else:
            self.set_enabled(True)

    def set_enabled(self, value):
        if value == True:
            self.id_N.setEnabled(True)
            self.id_ENERGY.setEnabled(True)
            self.id_CUR.setEnabled(True)
            self.id_PERIOD.setEnabled(True)
            self.id_KY.setEnabled(True)
        else:
            self.id_N.setEnabled(False)
            self.id_ENERGY.setEnabled(False)
            self.id_CUR.setEnabled(False)
            self.id_PERIOD.setEnabled(False)
            self.id_KY.setEnabled(False)
Exemple #20
0
class OWOpticalElement(WiseWidget, WidgetDecorator):
    category = ""
    keywords = ["wise", "mirror"]

    inputs = [("Input", WiseData, "set_input"),
              ("PreInput", WisePreInputData, "set_pre_input")]

    WidgetDecorator.append_syned_input_data(inputs)

    oe_name = Setting("Optical Element")

    alpha = Setting(2.0)
    length = Setting(400.0)
    ignore = Setting(False)

    use_small_displacements = Setting(0)
    rotation = Setting(0.0)
    transverse = Setting(0.0)
    longitudinal = Setting(0.0)

    use_figure_error = Setting(0)
    figure_error_file = Setting("figure_error.dat")
    figure_error_step = Setting(0.002)
    figure_error_amplitude_scaling = Setting(1.0)
    figure_error_um_conversion = Setting(1.0)

    use_roughness = Setting(0)
    roughness_file = Setting("roughness.dat")
    roughness_x_scaling = Setting(1.0)
    roughness_y_scaling = Setting(1.0)
    roughness_fit_data = Setting(0)

    use_multipool = Setting(0)
    n_pools = Setting(5)
    number_of_cpus = multiprocessing.cpu_count() - 1
    force_cpus = Setting(1)

    calculation_type = Setting(0)
    number_of_points = Setting(7000)

    input_data = None

    has_figure_error_box = True
    is_full_propagator = False

    def build_gui(self):
        self.tabs_setting = oasysgui.tabWidget(self.controlArea)
        self.tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT)
        self.tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5)

        self.tab_bas = oasysgui.createTabPage(self.tabs_setting,
                                              "O.E. Setting")
        self.tab_pro = oasysgui.createTabPage(self.tabs_setting,
                                              "Calculation Setting")

        main_box = oasysgui.widgetBox(self.tab_bas,
                                      "O.E. Input Parameters",
                                      orientation="vertical",
                                      width=self.CONTROL_AREA_WIDTH - 20)

        oasysgui.lineEdit(main_box,
                          self,
                          "oe_name",
                          "O.E. Name",
                          labelWidth=120,
                          valueType=str,
                          orientation="horizontal")

        oasysgui.lineEdit(main_box,
                          self,
                          "alpha",
                          "Incidence Angle [deg]",
                          labelWidth=240,
                          valueType=float,
                          orientation="horizontal")
        self.le_length = oasysgui.lineEdit(main_box,
                                           self,
                                           "length",
                                           "Length",
                                           labelWidth=240,
                                           valueType=float,
                                           orientation="horizontal")

        self.build_mirror_specific_gui(main_box)

        gui.comboBox(main_box,
                     self,
                     "ignore",
                     label="Ignore",
                     items=["No", "Yes"],
                     labelWidth=240,
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.separator(main_box)

        self.tabs_mirror = oasysgui.tabWidget(main_box)
        self.tabs_mirror.setFixedWidth(self.CONTROL_AREA_WIDTH - 40)

        self.tab_pos = oasysgui.createTabPage(self.tabs_mirror, "Position")
        if self.has_figure_error_box:
            self.tab_err = oasysgui.createTabPage(self.tabs_mirror,
                                                  "Figure Error")
        self.tab_dis = oasysgui.createTabPage(self.tabs_mirror, "Displacement")

        super(OWOpticalElement, self).build_positioning_directive_box(
            container_box=self.tab_pos,
            width=self.CONTROL_AREA_WIDTH - 50,
            element_type=ElementType.MIRROR)

        displacement_box = oasysgui.widgetBox(self.tab_dis,
                                              "Small Displacements",
                                              orientation="vertical",
                                              width=self.CONTROL_AREA_WIDTH -
                                              50)

        gui.comboBox(displacement_box,
                     self,
                     "use_small_displacements",
                     label="Small Displacements",
                     items=["No", "Yes"],
                     labelWidth=240,
                     callback=self.set_UseSmallDisplacement,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.use_small_displacements_box = oasysgui.widgetBox(
            displacement_box,
            "",
            addSpace=True,
            orientation="vertical",
            height=150,
            width=self.CONTROL_AREA_WIDTH - 65)
        self.use_small_displacements_box_empty = oasysgui.widgetBox(
            displacement_box,
            "",
            addSpace=True,
            orientation="vertical",
            height=150,
            width=self.CONTROL_AREA_WIDTH - 65)

        oasysgui.lineEdit(self.use_small_displacements_box,
                          self,
                          "rotation",
                          "Rotation [deg]",
                          labelWidth=240,
                          valueType=float,
                          orientation="horizontal")
        self.le_transverse = oasysgui.lineEdit(
            self.use_small_displacements_box,
            self,
            "transverse",
            "Transverse displacement",
            labelWidth=240,
            valueType=float,
            orientation="horizontal")
        self.le_longitudinal = oasysgui.lineEdit(
            self.use_small_displacements_box,
            self,
            "longitudinal",
            "Longitudinal displacement",
            labelWidth=240,
            valueType=float,
            orientation="horizontal")

        self.set_UseSmallDisplacement()

        # ---------------------------------------------------------------------------
        if self.has_figure_error_box:
            figure_error_tab = oasysgui.tabWidget(self.tab_err)
            error_tab = oasysgui.createTabPage(figure_error_tab,
                                               "Error Profile")
            roughness_tab = oasysgui.createTabPage(figure_error_tab,
                                                   "Roughness")

            figure_error_box = oasysgui.widgetBox(
                error_tab,
                "",
                orientation="vertical",
                width=self.CONTROL_AREA_WIDTH - 65)
            roughness_box = oasysgui.widgetBox(roughness_tab,
                                               "",
                                               orientation="vertical",
                                               width=self.CONTROL_AREA_WIDTH -
                                               65)

            gui.comboBox(figure_error_box,
                         self,
                         "use_figure_error",
                         label="Error Profile",
                         items=["None", "User Defined"],
                         labelWidth=240,
                         callback=self.set_UseFigureError,
                         sendSelectedValue=False,
                         orientation="horizontal")

            self.use_figure_error_box = oasysgui.widgetBox(
                figure_error_box,
                "",
                addSpace=True,
                orientation="vertical",
                height=150)
            self.use_figure_error_box_empty = oasysgui.widgetBox(
                figure_error_box,
                "",
                addSpace=True,
                orientation="vertical",
                height=150)

            file_box = oasysgui.widgetBox(self.use_figure_error_box,
                                          "",
                                          addSpace=False,
                                          orientation="horizontal")
            self.le_figure_error_file = oasysgui.lineEdit(
                file_box,
                self,
                "figure_error_file",
                "File Name",
                labelWidth=100,
                valueType=str,
                orientation="horizontal")
            gui.button(file_box,
                       self,
                       "...",
                       callback=self.selectFigureErrorFile)

            self.le_figure_error_step = oasysgui.lineEdit(
                self.use_figure_error_box,
                self,
                "figure_error_step",
                "Step",
                labelWidth=240,
                valueType=float,
                orientation="horizontal")
            oasysgui.lineEdit(self.use_figure_error_box,
                              self,
                              "figure_error_amplitude_scaling",
                              "Amplitude scaling factor",
                              labelWidth=240,
                              valueType=float,
                              orientation="horizontal")
            oasysgui.lineEdit(self.use_figure_error_box,
                              self,
                              "figure_error_um_conversion",
                              "User file u.m. to [m] factor",
                              labelWidth=240,
                              valueType=float,
                              orientation="horizontal")

            self.set_UseFigureError()

            gui.comboBox(roughness_box,
                         self,
                         "use_roughness",
                         label="Roughness",
                         items=["None", "User Defined"],
                         labelWidth=240,
                         callback=self.set_UseRoughness,
                         sendSelectedValue=False,
                         orientation="horizontal")

            self.use_roughness_box = oasysgui.widgetBox(roughness_box,
                                                        "",
                                                        addSpace=True,
                                                        orientation="vertical",
                                                        height=150)
            self.use_roughness_box_empty = oasysgui.widgetBox(
                roughness_box,
                "",
                addSpace=True,
                orientation="vertical",
                height=150)

            file_box = oasysgui.widgetBox(self.use_roughness_box,
                                          "",
                                          addSpace=False,
                                          orientation="horizontal")
            self.le_roughness_file = oasysgui.lineEdit(
                file_box,
                self,
                "roughness_file",
                "File Name",
                labelWidth=100,
                valueType=str,
                orientation="horizontal")
            gui.button(file_box,
                       self,
                       "...",
                       callback=self.selectRoughnessFile)

            oasysgui.lineEdit(self.use_roughness_box,
                              self,
                              "roughness_x_scaling",
                              "x user file u.m. to [m]   factor",
                              labelWidth=240,
                              valueType=float,
                              orientation="horizontal")
            oasysgui.lineEdit(self.use_roughness_box,
                              self,
                              "roughness_y_scaling",
                              "y user file u.m. to [m^3] factor",
                              labelWidth=240,
                              valueType=float,
                              orientation="horizontal")

            gui.comboBox(self.use_roughness_box,
                         self,
                         "roughness_fit_data",
                         label="Fit numeric data with power law",
                         items=["No", "Yes"],
                         labelWidth=240,
                         sendSelectedValue=False,
                         orientation="horizontal")

            self.set_UseRoughness()

        # ---------------------------------------------------------------------------

        calculation_box = oasysgui.widgetBox(self.tab_pro,
                                             "Calculation Parameters",
                                             orientation="vertical",
                                             width=self.CONTROL_AREA_WIDTH -
                                             20)

        gui.comboBox(calculation_box,
                     self,
                     "calculation_type",
                     label="Numeric Integration",
                     items=[
                         "Automatic Number of Points",
                         "User Defined Number of Points"
                     ],
                     labelWidth=140,
                     callback=self.set_CalculationType,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.empty_box = oasysgui.widgetBox(calculation_box,
                                            "",
                                            orientation="vertical",
                                            width=self.CONTROL_AREA_WIDTH - 40,
                                            height=50)
        self.number_box = oasysgui.widgetBox(calculation_box,
                                             "",
                                             orientation="vertical",
                                             width=self.CONTROL_AREA_WIDTH -
                                             40,
                                             height=50)

        oasysgui.lineEdit(self.number_box,
                          self,
                          "number_of_points",
                          "Number of Points",
                          labelWidth=240,
                          valueType=int,
                          orientation="horizontal")

        self.set_CalculationType()

        parallel_box = oasysgui.widgetBox(self.tab_pro,
                                          "Parallel Computing",
                                          orientation="vertical",
                                          width=self.CONTROL_AREA_WIDTH - 20)

        gui.comboBox(parallel_box,
                     self,
                     "use_multipool",
                     label="Use Parallel Processing",
                     items=["No", "Yes"],
                     labelWidth=240,
                     callback=self.set_Multipool,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.use_multipool_box = oasysgui.widgetBox(
            parallel_box,
            "",
            addSpace=False,
            orientation="vertical",
            height=100,
            width=self.CONTROL_AREA_WIDTH - 40)
        self.use_multipool_box_empty = oasysgui.widgetBox(
            parallel_box,
            "",
            addSpace=False,
            orientation="vertical",
            height=100,
            width=self.CONTROL_AREA_WIDTH - 40)

        oasysgui.lineEdit(self.use_multipool_box,
                          self,
                          "n_pools",
                          "Nr. Parallel Processes",
                          labelWidth=240,
                          valueType=int,
                          orientation="horizontal")

        gui.separator(self.use_multipool_box)

        gui.comboBox(self.use_multipool_box,
                     self,
                     "force_cpus",
                     label="Ignore Nr. Processes > Nr. CPUs",
                     items=["No", "Yes"],
                     labelWidth=240,
                     sendSelectedValue=False,
                     orientation="horizontal")

        le = oasysgui.lineEdit(self.use_multipool_box,
                               self,
                               "number_of_cpus",
                               "Nr. Available CPUs",
                               labelWidth=240,
                               valueType=float,
                               orientation="horizontal")
        le.setReadOnly(True)
        font = QFont(le.font())
        font.setBold(True)
        le.setFont(font)
        palette = QPalette(le.palette())
        palette.setColor(QPalette.Text, QColor('dark blue'))
        palette.setColor(QPalette.Base, QColor(243, 240, 140))
        le.setPalette(palette)

        self.set_Multipool()

    def selectFigureErrorFile(self):
        self.le_figure_error_file.setText(
            oasysgui.selectFileFromDialog(
                self,
                self.figure_error_file,
                "Select File",
                file_extension_filter="Data Files (*.dat *.txt)"))

    def selectRoughnessFile(self):
        self.le_roughness_file.setText(
            oasysgui.selectFileFromDialog(
                self,
                self.roughness_file,
                "Select File",
                file_extension_filter="Data Files (*.dat *.txt)"))

    def set_FigureErrorPlot(self):
        if self.use_figure_error == 1:
            self.tab[2].setEnabled(True)
            self.plot_canvas[2]._backend.fig.set_facecolor("#FEFEFE")
        else:
            self.tab[2].setEnabled(False)
            self.plot_canvas[2]._backend.fig.set_facecolor("#D7DBDD")

    def set_UseFigureError(self):
        self.use_figure_error_box.setVisible(self.use_figure_error == 1)
        self.use_figure_error_box_empty.setVisible(self.use_figure_error == 0)

    def set_UseRoughness(self):
        self.use_roughness_box.setVisible(self.use_roughness == 1)
        self.use_roughness_box_empty.setVisible(self.use_roughness == 0)

    def set_UseSmallDisplacement(self):
        self.use_small_displacements_box.setVisible(
            self.use_small_displacements == 1)
        self.use_small_displacements_box_empty.setVisible(
            self.use_small_displacements == 0)

    def set_CalculationType(self):
        self.empty_box.setVisible(self.calculation_type == 0)
        self.number_box.setVisible(self.calculation_type == 1)

    def set_Multipool(self):
        self.use_multipool_box.setVisible(self.use_multipool == 1)
        self.use_multipool_box_empty.setVisible(self.use_multipool == 0)

    def after_change_workspace_units(self):
        super(OWOpticalElement, self).after_change_workspace_units()

        label = self.le_length.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        if self.has_figure_error_box:
            label = self.le_figure_error_step.parent().layout().itemAt(
                0).widget()
            label.setText(label.text() + " [" + self.workspace_units_label +
                          "]")
        label = self.le_transverse.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_longitudinal.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

    def build_mirror_specific_gui(self, container_box):
        raise NotImplementedError()

    def set_input(self, input_data):
        self.setStatusMessage("")

        if not input_data is None:
            try:
                if input_data.wise_beamline is None or input_data.wise_beamline.get_propagation_elements_number(
                ) == 0:
                    if input_data.wise_wavefront is None:
                        raise ValueError(
                            "Input Data contains no wavefront and/or no source to perform wavefront propagation"
                        )

                self.input_data = input_data.duplicate()

                if self.is_automatic_run: self.compute()
            except Exception as e:
                QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)

                self.setStatusMessage("Error")

    def set_pre_input(self, data):
        if data is not None:
            try:
                if data.figure_error_file != WisePreInputData.NONE:
                    self.figure_error_file = data.figure_error_file
                    self.figure_error_step = data.figure_error_step
                    self.figure_error_um_conversion = data.figure_user_units_to_m
                    self.use_figure_error = 1

                    self.set_UseFigureError()

                if data.roughness_file != WisePreInputData.NONE:
                    self.roughness_file = data.roughness_file
                    self.roughness_x_scaling = data.roughness_x_scaling
                    self.roughness_y_scaling = data.roughness_y_scaling
                    self.use_roughness = 1

                    self.set_UseRoughness()
            except Exception as e:
                QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)

                self.setStatusMessage("Error")

    def check_fields(self):
        self.alpha = congruence.checkAngle(self.alpha, "Incidence Angle")
        self.length = congruence.checkStrictlyPositiveNumber(
            self.length, "Length")

        if self.use_figure_error == 1:
            congruence.checkFileName(self.figure_error_file)

        if self.use_roughness == 1:
            congruence.checkFileName(self.roughness_file)

        if self.calculation_type == 1:
            congruence.checkStrictlyPositiveNumber(self.number_of_points,
                                                   "Number of Points")

        if self.use_multipool == 1:
            congruence.checkStrictlyPositiveNumber(self.n_pools,
                                                   "Nr. Parallel Processes")

            if self.force_cpus == 0:
                if self.number_of_cpus == 1:
                    raise Exception(
                        "Parallel processing not available with 1 CPU")
                elif self.n_pools >= self.number_of_cpus:
                    raise Exception(
                        "Max number of parallel processes allowed on this computer ("
                        + str(self.number_of_cpus) + ")")

    def do_wise_calculation(self):
        if self.input_data is None:
            raise Exception("No Input Data!")

        optical_element = self.get_optical_element(
            self.get_inner_wise_optical_element())

        wise_optical_element = optical_element.wise_optical_element

        wise_optical_element.CoreOptics.ComputationSettings.Ignore = (
            self.ignore == 1)

        if self.use_small_displacements == 1:
            wise_optical_element.CoreOptics.ComputationSettings.UseSmallDisplacements = True  # serve per traslare/ruotare l'EO
            wise_optical_element.CoreOptics.SmallDisplacements.Rotation = numpy.deg2rad(
                self.rotation)
            wise_optical_element.CoreOptics.SmallDisplacements.Trans = self.transverse * self.workspace_units_to_m  # Transverse displacement (rispetto al raggio uscente, magari faremo scegliere)
            wise_optical_element.CoreOptics.SmallDisplacements.Long = self.longitudinal * self.workspace_units_to_m  # Longitudinal displacement (idem)
        else:
            wise_optical_element.CoreOptics.ComputationSettings.UseSmallDisplacements = False
            wise_optical_element.CoreOptics.SmallDisplacements.Rotation = 0.0
            wise_optical_element.CoreOptics.SmallDisplacements.Trans = 0.0
            wise_optical_element.CoreOptics.SmallDisplacements.Long = 0.0

        if self.use_figure_error == 1:
            wise_optical_element.CoreOptics.ComputationSettings.UseFigureError = True

            wise_optical_element.CoreOptics.FigureErrorLoad(
                File=self.figure_error_file,
                Step=self.figure_error_step *
                self.workspace_units_to_m,  # passo del file
                AmplitudeScaling=self.figure_error_amplitude_scaling *
                self.figure_error_um_conversion  # fattore di scala
            )
        else:
            wise_optical_element.CoreOptics.ComputationSettings.UseFigureError = False

        if self.use_roughness == 1:
            self.use_roughness = 0
            self.set_UseRoughness()

            raise NotImplementedError("Roughness Not yet supported")
        else:
            wise_optical_element.CoreOptics.ComputationSettings.UseRoughness = False

        if self.calculation_type == 0:
            wise_optical_element.ComputationSettings.UseCustomSampling = False
        else:
            # l'utente decide di impostare a mano il campionamento
            wise_optical_element.ComputationSettings.UseCustomSampling = True
            wise_optical_element.ComputationSettings.NSamples = self.number_of_points

        output_data = self.input_data.duplicate()
        input_wavefront = output_data.wise_wavefront

        if output_data.wise_beamline is None:
            output_data.wise_beamline = WisePropagationElements()

        output_data.wise_beamline.add_beamline_element(
            WiseBeamlineElement(optical_element=optical_element))

        parameters = PropagationParameters(
            wavefront=input_wavefront if not input_wavefront is None else
            WiseWavefront(wise_computation_results=None),
            propagation_elements=output_data.wise_beamline)

        parameters.set_additional_parameters(
            "single_propagation",
            True if PropagationManager.Instance().get_propagation_mode(
                WISE_APPLICATION) == PropagationMode.STEP_BY_STEP else
            (not self.is_full_propagator))
        parameters.set_additional_parameters(
            "NPools", self.n_pools if self.use_multipool == 1 else 1)
        parameters.set_additional_parameters("is_full_propagator",
                                             self.is_full_propagator)

        output_data.wise_wavefront = PropagationManager.Instance(
        ).do_propagation(propagation_parameters=parameters,
                         handler_name=WisePropagator.HANDLER_NAME)

        return output_data

    def get_inner_wise_optical_element(self):
        raise NotImplementedError()

    def get_optical_element(self, inner_wise_optical_element):
        raise NotImplementedError()

    def getTabTitles(self):
        return ["Field Intensity (O.E.)", "Phase (O.E.)", "Figure Error"]

    def getTitles(self):
        return ["Field Intensity (O.E.)", "Phase (O.E.)", "Figure Error"]

    def getXTitles(self):
        return [
            "S [" + self.workspace_units_label + "]",
            "S [" + self.workspace_units_label + "]",
            "S [" + self.workspace_units_label + "]"
        ]

    def getYTitles(self):
        return ["|E0|**2", "Phase", "Height Error [nm]"]

    def getVariablesToPlot(self):
        return [(0, 1), (0, 2), (0, 1)]

    def getLogPlot(self):
        return [(False, False), (False, False), (False, False)]

    def extract_plot_data_from_calculation_output(self, calculation_output):
        output_wavefront = calculation_output.wise_wavefront

        if not output_wavefront is None and not output_wavefront.wise_computation_result is None:
            wise_optical_element = calculation_output.wise_beamline.get_wise_propagation_element(
                -1)

            S = output_wavefront.wise_computation_result.S
            E = output_wavefront.wise_computation_result.Field
            I = abs(E)**2
            norm = max(I)
            norm = 1.0 if norm == 0.0 else norm
            I = I / norm

            #------------------------------------------------------------

            data_to_plot = numpy.zeros((3, len(S)))
            data_to_plot[0, :] = S / self.workspace_units_to_m
            data_to_plot[1, :] = I
            data_to_plot[2, :] = numpy.imag(E)

            self.is_tab_2_enabled = False

            if not wise_optical_element.CoreOptics.FigureErrors is None and len(
                    wise_optical_element.CoreOptics.FigureErrors) > 0:
                self.is_tab_2_enabled = True
                figure_error_x = numpy.linspace(
                    0, self.length,
                    len(wise_optical_element.CoreOptics.FigureErrors[0]))
                data_to_plot_fe = numpy.zeros((2, len(figure_error_x)))

                data_to_plot_fe[0, :] = figure_error_x
                data_to_plot_fe[
                    1, :] = wise_optical_element.CoreOptics.FigureErrors[
                        0] * 1e9  # nm
            else:
                data_to_plot_fe = numpy.zeros((2, 1))

                data_to_plot_fe[0, :] = numpy.zeros(1)
                data_to_plot_fe[1, :] = numpy.zeros(1)

            return data_to_plot, data_to_plot_fe
        else:
            return None, None

    def plot_results(self, plot_data, progressBarValue=80):
        if not self.view_type == 0:
            if not plot_data is None:

                plot_data_1 = plot_data[0]
                plot_data_2 = plot_data[1]

                self.view_type_combo.setEnabled(False)

                titles = self.getTitles()
                xtitles = self.getXTitles()
                ytitles = self.getYTitles()

                progress_bar_step = (100 - progressBarValue) / len(titles)

                for index in range(0, len(titles)):
                    x_index, y_index = self.getVariablesToPlot()[index]
                    log_x, log_y = self.getLogPlot()[index]

                    try:
                        if index < 2:
                            if not plot_data_1 is None:
                                self.plot_histo(
                                    plot_data_1[x_index, :],
                                    plot_data_1[y_index, :],
                                    progressBarValue +
                                    ((index + 1) * progress_bar_step),
                                    tabs_canvas_index=index,
                                    plot_canvas_index=index,
                                    title=titles[index],
                                    xtitle=xtitles[index],
                                    ytitle=ytitles[index],
                                    log_x=log_x,
                                    log_y=log_y)
                        else:
                            if not plot_data_2 is None:
                                self.plot_histo(
                                    plot_data_2[x_index, :],
                                    plot_data_2[y_index, :],
                                    progressBarValue +
                                    ((index + 1) * progress_bar_step),
                                    tabs_canvas_index=index,
                                    plot_canvas_index=index,
                                    title=titles[index],
                                    xtitle=xtitles[index],
                                    ytitle=ytitles[index],
                                    log_x=log_x,
                                    log_y=log_y)

                                if index == 2: self.set_FigureErrorPlot()

                    except Exception as e:
                        self.view_type_combo.setEnabled(True)

                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                self.tabs.setCurrentIndex(0)
                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def receive_syned_data(self, data):
        if not data is None:
            try:
                beamline_element = data.get_beamline_element_at(-1)

                if beamline_element is None:
                    raise Exception(
                        "Syned Data not correct: Empty Beamline Element")

                optical_element = beamline_element._optical_element

                if optical_element is None:
                    raise Exception(
                        "Syned Data not correct: Empty Optical Element")

                if not isinstance(optical_element, Mirror):
                    raise Exception(
                        "Syned Data not correct: Optical Element is not a Mirror"
                    )

                self.check_syned_shape(optical_element)

                self.alpha = round(
                    numpy.degrees(0.5 * numpy.pi -
                                  beamline_element._coordinates._angle_radial),
                    4)

                boundaries = optical_element._boundary_shape.get_boundaries()

                tangential_size = round(
                    abs(boundaries[3] - boundaries[2]) /
                    self.workspace_units_to_m, 6)
                sagittal_size = round(
                    abs(boundaries[1] - boundaries[0]) /
                    self.workspace_units_to_m, 6)

                axis = QInputDialog.getItem(self, "Projection Axis",
                                            "Select Direction",
                                            ("Horizontal", "Vertical"), 0,
                                            False)

                if axis == 0:
                    self.length = sagittal_size
                else:
                    self.length = tangential_size

                self.receive_specific_syned_data(optical_element)
            except Exception as e:
                QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)

                self.setStatusMessage("Error")

    def check_syned_shape(self, optical_element):
        raise NotImplementedError()

    def receive_specific_syned_data(self, optical_element):
        raise NotImplementedError()
Exemple #21
0
class OWSRWSource(SRWWavefrontViewer, WidgetDecorator):

    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    category = "Sources"
    keywords = ["data", "file", "load", "read"]

    inputs = WidgetDecorator.syned_input_data()
    inputs.append(("SynedData#2", Beamline, "receive_syned_data"))
    inputs.append(("Trigger", TriggerOut, "sendNewWavefront"))

    outputs = [{"name":"SRWData",
                "type":SRWData,
                "doc":"SRW Source Data",
                "id":"data"}]

    want_main_area=1

    source_name = None

    electron_energy_in_GeV = Setting(2.0)
    electron_energy_spread = Setting(0.0007)
    ring_current = Setting(0.4)
    electron_beam_size_h = Setting(5.5453e-05)
    electron_beam_size_v = Setting(2.784e-06)
    electron_beam_divergence_h = Setting(4.5083e-06)
    electron_beam_divergence_v = Setting(8.98e-07)

    moment_x = Setting(0.0)
    moment_y = Setting(0.0)
    moment_z = Setting(0.0)
    moment_xp = Setting(0.0)
    moment_yp = Setting(0.0)

    moment_xx           = Setting((0.05545e-3)**2)
    moment_xxp          = Setting(0.0)
    moment_xpxp         = Setting((4.5083e-06)**2)
    moment_yy           = Setting((2.784e-6)**2)
    moment_yyp          = Setting(0.0)
    moment_ypyp         = Setting((8.98e-07)**2)

    horizontal_emittance = Setting(0.0)
    horizontal_beta = Setting(0.0)
    horizontal_alpha = Setting(0.0)
    horizontal_eta = Setting(0.0)
    horizontal_etap   = Setting(0.0)
    vertical_emittance= Setting(0.0)
    vertical_beta     = Setting(0.0)
    vertical_alpha    = Setting(0.0)
    vertical_eta = Setting(0.0)
    vertical_etap = Setting(0.0)

    type_of_properties = Setting(1)
    type_of_initialization = Setting(0)

    wf_photon_energy = Setting(8000.0)
    wf_h_slit_gap = Setting(0.001)
    wf_v_slit_gap =Setting( 0.001)
    wf_h_slit_points=Setting(100)
    wf_v_slit_points=Setting(100)
    wf_distance = Setting(10.0)

    wf_sr_method = Setting(1)
    wf_relative_precision = Setting(0.01)
    wf_start_integration_longitudinal_position = Setting(0.0) 
    wf_end_integration_longitudinal_position = Setting(0.0) 
    wf_number_of_points_for_trajectory_calculation = Setting(50000)
    wf_use_terminating_terms = Setting(1)
    wf_sampling_factor_for_adjusting_nx_ny = Setting(0.0)

    TABS_AREA_HEIGHT = 618
    CONTROL_AREA_WIDTH = 405

    def __init__(self):
        super().__init__(show_general_option_box=False, show_automatic_box=False)

        self.runaction = widget.OWAction("Run SRW", self)
        self.runaction.triggered.connect(self.runSRWSource)
        self.addAction(self.runaction)

        button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")

        button = gui.button(button_box, self, "Run SRW Source", callback=self.runSRWSource)
        font = QFont(button.font())
        font.setBold(True)
        button.setFont(font)
        palette = QPalette(button.palette()) # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Blue'))
        button.setPalette(palette) # assign new palette
        button.setFixedHeight(45)

        button = gui.button(button_box, self, "Reset Fields", callback=self.callResetSettings)
        font = QFont(button.font())
        font.setItalic(True)
        button.setFont(font)
        palette = QPalette(button.palette()) # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Red'))
        button.setPalette(palette) # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(150)

        gui.separator(self.controlArea)

        self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)

        self.tabs_setting = oasysgui.tabWidget(self.controlArea)
        self.tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT)
        self.tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5)

        self.tab_source = oasysgui.createTabPage(self.tabs_setting, "Light Source Setting")

        left_box_1 = oasysgui.widgetBox(self.tab_source, "Electron Beam Parameters", addSpace=True, orientation="vertical", height=380)

        oasysgui.lineEdit(left_box_1, self, "electron_energy_in_GeV", "Energy [GeV]", labelWidth=260, valueType=float, orientation="horizontal", callback=self.callback_electron_energy)
        oasysgui.lineEdit(left_box_1, self, "electron_energy_spread", "Energy Spread", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_1, self, "ring_current", "Ring Current [A]", labelWidth=260, valueType=float, orientation="horizontal")

        tab_electron = oasysgui.tabWidget(left_box_1)

        tab_beam = oasysgui.createTabPage(tab_electron, "Beam")
        tab_traj = oasysgui.createTabPage(tab_electron, "Trajectory")

        gui.separator(tab_beam)

        gui.comboBox(tab_beam, self, "type_of_properties", label="Electron Beam Properties", labelWidth=350,
                     items=["From 2nd Moments", "From Size/Divergence", "From Twiss"],
                     callback=self.set_TypeOfProperties,
                     sendSelectedValue=False, orientation="horizontal")

        self.left_box_2_1 = oasysgui.widgetBox(tab_beam, "", addSpace=False, orientation="vertical", height=185)

        gui.separator(self.left_box_2_1)

        oasysgui.lineEdit(self.left_box_2_1, self, "moment_xx", "\u03c3x\u22c5\u03c3x   [m\u00b2]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_1, self, "moment_xxp", "\u03c3x\u22c5\u03c3x'  [m\u22c5rad]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_1, self, "moment_xpxp", "\u03c3x'\u22c5\u03c3x' [rad\u00b2]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_1, self, "moment_yy", "\u03c3y\u22c5\u03c3y   [m\u00b2]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_1, self, "moment_yyp", "\u03c3y\u22c5\u03c3y'  [m\u22c5rad]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_1, self, "moment_ypyp", "\u03c3y'\u22c5\u03c3y' [rad\u00b2]", labelWidth=200, valueType=float, orientation="horizontal")

        self.left_box_2_2 = oasysgui.widgetBox(tab_beam, "", addSpace=False, orientation="vertical", height=185)

        gui.separator(self.left_box_2_2)

        oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_size_h",       "\u03c3x [m]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_size_v",       "\u03c3y [m]",  labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_divergence_h", "\u03c3x' [rad]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_divergence_v", "\u03c3y' [rad]", labelWidth=200, valueType=float, orientation="horizontal")

        self.left_box_2_3 = oasysgui.widgetBox(tab_beam, "", addSpace=False, orientation="horizontal", height=185)

        left_box_2_3_l = oasysgui.widgetBox(self.left_box_2_3, "", addSpace=False, orientation="vertical", height=185)
        left_box_2_3_r = oasysgui.widgetBox(self.left_box_2_3, "", addSpace=False, orientation="vertical", height=185)

        gui.separator(left_box_2_3_l)
        gui.separator(left_box_2_3_r)

        oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_emittance", "Emittance x [m]", labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_beta"     , "\u03B2x [m]"    , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_alpha"    , "\u03B1x [rad]"    , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_eta"      , "\u03B7x [m]"    , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_etap"     , "\u03B7x' [rad]"   , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_r, self, "vertical_emittance"  , "Emittance y [m]", labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_r, self, "vertical_beta"       , "\u03B2y [m]"    , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_r, self, "vertical_alpha"      , "\u03B1y [rad]"    , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_r, self, "vertical_eta"        , "\u03B7y [m]"    , labelWidth=100, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(left_box_2_3_r, self, "vertical_etap"       , "\u03B7y' [rad]"   , labelWidth=100, valueType=float, orientation="horizontal")

        self.set_TypeOfProperties()

        gui.comboBox(tab_traj, self, "type_of_initialization", label="Trajectory Initialization", labelWidth=140,
                     items=["At Zero Point", "At Fixed Position", "Sampled from Phase Space"],
                     callback=self.set_TypeOfInitialization,
                     sendSelectedValue=False, orientation="horizontal")

        self.left_box_3_1 = oasysgui.widgetBox(tab_traj, "", addSpace=False, orientation="vertical", height=160)
        self.left_box_3_2 = oasysgui.widgetBox(tab_traj, "", addSpace=False, orientation="vertical", height=160)

        oasysgui.lineEdit(self.left_box_3_1, self, "moment_x", "x\u2080 [m]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_3_1, self, "moment_y", "y\u2080 [m]", labelWidth=200, valueType=float, orientation="horizontal")

        box = oasysgui.widgetBox(self.left_box_3_1, "", addSpace=False, orientation="horizontal")

        oasysgui.lineEdit(box, self, "moment_z", "z\u2080 [m]", labelWidth=160, valueType=float, orientation="horizontal")
        gui.button(box, self, "Auto", width=35, callback=self.set_z0Default)


        oasysgui.lineEdit(self.left_box_3_1, self, "moment_xp", "x'\u2080 [rad]", labelWidth=200, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.left_box_3_1, self, "moment_yp", "y'\u2080 [rad]", labelWidth=200, valueType=float, orientation="horizontal")

        self.set_TypeOfInitialization()

        self.tab_plots = oasysgui.createTabPage(self.tabs_setting, "Wavefront Setting")

        self.tabs_plots_setting = oasysgui.tabWidget(self.tab_plots)
        
        # PROPAGATION -------------------------------------------
        
        tab_wav = oasysgui.createTabPage(self.tabs_plots_setting, "Propagation")

        wav_box = oasysgui.widgetBox(tab_wav, "Wavefront Parameters", addSpace=True, orientation="vertical")

        self.build_wf_photon_energy_box(wav_box)
        oasysgui.lineEdit(wav_box, self, "wf_h_slit_gap", "H Slit Gap [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(wav_box, self, "wf_v_slit_gap", "V Slit Gap [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(wav_box, self, "wf_h_slit_points", "H Slit Points", labelWidth=260, valueType=int, orientation="horizontal")
        oasysgui.lineEdit(wav_box, self, "wf_v_slit_points", "V Slit Points", labelWidth=260, valueType=int, orientation="horizontal")
        oasysgui.lineEdit(wav_box, self, "wf_distance", "Propagation Distance [m]", labelWidth=260, valueType=float, orientation="horizontal")

        pre_box = oasysgui.widgetBox(tab_wav, "Precision Parameters", addSpace=False, orientation="vertical")

        gui.comboBox(pre_box, self, "wf_sr_method", label="Calculation Method",
                     items=["Manual", "Auto"], labelWidth=260,
                     sendSelectedValue=False, orientation="horizontal")

        oasysgui.lineEdit(pre_box, self, "wf_relative_precision", "Relative Precision", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(pre_box, self, "wf_start_integration_longitudinal_position", "Longitudinal position to start integration\n(effective if < zEndInteg) [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(pre_box, self, "wf_end_integration_longitudinal_position", "Longitudinal position to finish integration\n(effective if > zStartInteg) [m]", labelWidth=260, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(pre_box, self, "wf_number_of_points_for_trajectory_calculation", "Number of points for trajectory calculation", labelWidth=260, valueType=int, orientation="horizontal")

        gui.comboBox(pre_box, self, "wf_use_terminating_terms", label="Use \"terminating terms\"\n(i.e. asymptotic expansions at zStartInteg\nand zEndInteg) or not",
                     items=["No", "Yes"], labelWidth=260,
                     sendSelectedValue=False, orientation="horizontal")

        oasysgui.lineEdit(pre_box, self, "wf_sampling_factor_for_adjusting_nx_ny", "Sampling factor for adjusting nx/ny\n(effective if > 0)", labelWidth=260, valueType=int, orientation="horizontal")

        gui.rubber(self.controlArea)

    def set_TypeOfProperties(self):
        self.left_box_2_1.setVisible(self.type_of_properties==0)
        self.left_box_2_2.setVisible(self.type_of_properties==1)
        self.left_box_2_3.setVisible(self.type_of_properties==2)

    def set_TypeOfInitialization(self):
        self.left_box_3_1.setVisible(self.type_of_initialization==1)
        self.left_box_3_2.setVisible(self.type_of_initialization!=1)

    def build_wf_photon_energy_box(self, box):
        oasysgui.lineEdit(box, self, "wf_photon_energy", "Photon Energy [eV]", labelWidth=260, valueType=float, orientation="horizontal")

    def runSRWSource(self):
        self.setStatusMessage("")
        self.progressBarInit()

        try:
            self.checkFields()

            srw_source = self.get_srw_source(self.get_electron_beam())
            srw_source.name = self.source_name if not self.source_name is None else self.windowTitle(),

            self.progressBarSet(10)

            self.setStatusMessage("Running SRW")

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.print_specific_infos(srw_source)

            self.progressBarSet(20)

            self.setStatusMessage("")

            beamline = SRWBeamline(light_source=srw_source)
            self.output_wavefront = self.calculate_wavefront_propagation(srw_source)


            if self.is_do_plots():
                self.setStatusMessage("Plotting Results")

                tickets = []

                self.run_calculation_for_plots(tickets, 50)

                self.plot_results(tickets, 80)

            self.setStatusMessage("")

            self.send("SRWData", SRWData(srw_beamline=beamline, srw_wavefront=self.output_wavefront))

        except Exception as exception:
            QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)

            if self.IS_DEVELOP: raise exception

        self.progressBarFinished()

    def sendNewWavefront(self, trigger):
        if trigger and trigger.new_object == True:
            self.runSRWSource()

    def get_electron_beam(self):
        if self.type_of_initialization == 2:
            electron_beam = SRWElectronBeam(energy_in_GeV=numpy.random.normal(self.electron_energy_in_GeV,
                                                                              self.electron_energy_spread*self.electron_energy_in_GeV),
                                            energy_spread=self.electron_energy_spread,
                                            current=self.ring_current)
        else:
            electron_beam = SRWElectronBeam(energy_in_GeV=self.electron_energy_in_GeV,
                                            energy_spread=self.electron_energy_spread,
                                            current=self.ring_current)

        if self.type_of_properties == 0:
            electron_beam._moment_xx = self.moment_xx
            electron_beam._moment_xxp = self.moment_xxp
            electron_beam._moment_xpxp = self.moment_xpxp
            electron_beam._moment_yy = self.moment_yy
            electron_beam._moment_yyp = self.moment_yyp
            electron_beam._moment_ypyp = self.moment_ypyp

            x, xp, y, yp = electron_beam.get_sigmas_all()

            self.electron_beam_size_h = x
            self.electron_beam_size_v = y
            self.electron_beam_divergence_h = xp
            self.electron_beam_divergence_v = yp
        elif self.type_of_properties == 1:
            electron_beam.set_sigmas_all(sigma_x=self.electron_beam_size_h,
                                         sigma_y=self.electron_beam_size_v,
                                         sigma_xp=self.electron_beam_divergence_h,
                                         sigma_yp=self.electron_beam_divergence_v)

            self.moment_xx = electron_beam._moment_xx
            self.moment_xpxp = electron_beam._moment_xpxp
            self.moment_yy = electron_beam._moment_yy
            self.moment_ypyp = electron_beam._moment_ypyp

        elif self.type_of_properties == 2:
            electron_beam.set_moments_from_twiss(horizontal_emittance = self.horizontal_emittance,
                                                 horizontal_beta      = self.horizontal_beta,
                                                 horizontal_alpha     = self.horizontal_alpha,
                                                 horizontal_eta       = self.horizontal_eta,
                                                 horizontal_etap      = self.horizontal_etap,
                                                 vertical_emittance   = self.vertical_emittance,
                                                 vertical_beta        = self.vertical_beta,
                                                 vertical_alpha       = self.vertical_alpha,
                                                 vertical_eta         = self.vertical_eta,
                                                 vertical_etap        = self.vertical_etap)

            self.moment_xx = electron_beam._moment_xx
            self.moment_xpxp = electron_beam._moment_xpxp
            self.moment_yy = electron_beam._moment_yy
            self.moment_ypyp = electron_beam._moment_ypyp

            x, xp, y, yp = electron_beam.get_sigmas_all()

            self.electron_beam_size_h = round(x, 9)
            self.electron_beam_size_v = round(y, 9)
            self.electron_beam_divergence_h = round(xp, 10)
            self.electron_beam_divergence_v = round(yp, 10)

        if self.type_of_initialization == 0: # zero
            self.moment_x = 0.0
            self.moment_y = 0.0
            self.moment_z = self.get_default_initial_z()
            self.moment_xp = 0.0
            self.moment_yp = 0.0
        elif self.type_of_initialization == 2: # sampled
            self.moment_x = numpy.random.normal(0.0, self.electron_beam_size_h)
            self.moment_y = numpy.random.normal(0.0, self.electron_beam_size_v)
            self.moment_z = self.get_default_initial_z()
            self.moment_xp = numpy.random.normal(0.0, self.electron_beam_divergence_h)
            self.moment_yp = numpy.random.normal(0.0, self.electron_beam_divergence_v)

        electron_beam._moment_x = self.moment_x
        electron_beam._moment_y = self.moment_y
        electron_beam._moment_z = self.moment_z
        electron_beam._moment_xp = self.moment_xp
        electron_beam._moment_yp = self.moment_yp

        print("\n", "Electron Trajectory Initialization:")
        print("X0: ", electron_beam._moment_x)
        print("Y0: ", electron_beam._moment_y)
        print("Z0: ", electron_beam._moment_z)
        print("XP0: ", electron_beam._moment_xp)
        print("YP0: ", electron_beam._moment_yp)
        print("E0: ", electron_beam._energy_in_GeV, "\n")

        return electron_beam

    def set_z0Default(self):
        self.moment_z = self.get_default_initial_z()

    def get_default_initial_z(self):
        return NotImplementedError()

    def get_srw_source(self, electron_beam=ElectronBeam()):
        raise NotImplementedError()

    def checkFields(self):
        congruence.checkStrictlyPositiveNumber(self.electron_energy_in_GeV, "Energy")
        congruence.checkPositiveNumber(self.electron_energy_spread, "Energy Spread")
        congruence.checkStrictlyPositiveNumber(self.ring_current, "Ring Current")

        if self.type_of_properties == 0:
            congruence.checkPositiveNumber(self.moment_xx   , "Moment xx")
            congruence.checkPositiveNumber(self.moment_xpxp , "Moment xpxp")
            congruence.checkPositiveNumber(self.moment_yy   , "Moment yy")
            congruence.checkPositiveNumber(self.moment_ypyp , "Moment ypyp")
        elif self.type_of_properties == 1:
            congruence.checkPositiveNumber(self.electron_beam_size_h       , "Horizontal Beam Size")
            congruence.checkPositiveNumber(self.electron_beam_divergence_h , "Vertical Beam Size")
            congruence.checkPositiveNumber(self.electron_beam_size_v       , "Horizontal Beam Divergence")
            congruence.checkPositiveNumber(self.electron_beam_divergence_v , "Vertical Beam Divergence")
        elif self.type_of_properties == 2:
            congruence.checkPositiveNumber(self.horizontal_emittance       , "Horizontal Emittance")
            congruence.checkPositiveNumber(self.vertical_emittance         , "Vertical Emittance")

        self.checkLightSourceSpecificFields()

        if self.type_of_initialization == 2:
            congruence.checkNumber(self.moment_x   , "x0")
            congruence.checkNumber(self.moment_xp , "xp0")
            congruence.checkNumber(self.moment_y   , "y0")
            congruence.checkNumber(self.moment_yp , "yp0")
            congruence.checkNumber(self.moment_z , "z0")


        # WAVEFRONT

        self.checkWavefrontPhotonEnergy()

        congruence.checkStrictlyPositiveNumber(self.wf_h_slit_gap, "Wavefront Propagation H Slit Gap")
        congruence.checkStrictlyPositiveNumber(self.wf_v_slit_gap, "Wavefront Propagation V Slit Gap")
        congruence.checkStrictlyPositiveNumber(self.wf_h_slit_points, "Wavefront Propagation H Slit Points")
        congruence.checkStrictlyPositiveNumber(self.wf_v_slit_points, "Wavefront Propagation V Slit Points")
        congruence.checkGreaterOrEqualThan(self.wf_distance, self.get_minimum_propagation_distance(),
                                           "Wavefront Propagation Distance", "Minimum Distance out of the Source: " + str(self.get_minimum_propagation_distance()))

        congruence.checkStrictlyPositiveNumber(self.wf_relative_precision, "Wavefront Propagation Relative Precision")
        congruence.checkStrictlyPositiveNumber(self.wf_number_of_points_for_trajectory_calculation, "Wavefront Propagation Number of points for trajectory calculation")
        congruence.checkPositiveNumber(self.wf_sampling_factor_for_adjusting_nx_ny, "Wavefront Propagation Sampling Factor for adjusting nx/ny")

    def checkLightSourceSpecificFields(self):
        raise NotImplementedError()


    def checkWavefrontPhotonEnergy(self):
        congruence.checkStrictlyPositiveNumber(self.wf_photon_energy, "Wavefront Propagation Photon Energy")

    def run_calculation_for_plots(self, tickets, progress_bar_value):
        if not self.output_wavefront is None:
            if self.view_type == 1:
                e, h, v, i = self.output_wavefront.get_intensity(multi_electron=False)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                self.progressBarSet(progress_bar_value)

                e, h, v, i = self.output_wavefront.get_phase()

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                self.progressBarSet(progress_bar_value + 10)

                e, h, v, i = self.output_wavefront.get_intensity(multi_electron=True)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                self.progressBarSet(progress_bar_value + 20)
            elif self.view_type == 2:
                e, h, v, i = self.output_wavefront.get_intensity(multi_electron=False, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_HORIZONTAL)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                self.progressBarSet(progress_bar_value)

                #--

                e, h, v, i = self.output_wavefront.get_intensity(multi_electron=False, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_VERTICAL)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                #--

                e, h, v, i = self.output_wavefront.get_phase(polarization_component_to_be_extracted=PolarizationComponent.LINEAR_HORIZONTAL)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                self.progressBarSet(progress_bar_value + 10)

                e, h, v, i = self.output_wavefront.get_phase(polarization_component_to_be_extracted=PolarizationComponent.LINEAR_VERTICAL)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                #--

                e, h, v, i = self.output_wavefront.get_intensity(multi_electron=True, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_HORIZONTAL)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))

                self.progressBarSet(progress_bar_value + 20)

                e, h, v, i = self.output_wavefront.get_intensity(multi_electron=True, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_VERTICAL)

                tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)]))


    def get_automatic_sr_method(self):
        raise NotImplementedError()

    def calculate_wavefront_propagation(self, srw_source):
        photon_energy = self.get_photon_energy_for_wavefront_propagation(srw_source)

        wf_parameters = WavefrontParameters(photon_energy_min = photon_energy,
                                            photon_energy_max = photon_energy,
                                            photon_energy_points=1,
                                            h_slit_gap = self.wf_h_slit_gap,
                                            v_slit_gap = self.wf_v_slit_gap,
                                            h_slit_points=self.wf_h_slit_points,
                                            v_slit_points=self.wf_v_slit_points,
                                            distance = self.wf_distance,
                                            wavefront_precision_parameters=WavefrontPrecisionParameters(sr_method=0 if self.wf_sr_method == 0 else self.get_automatic_sr_method(),
                                                                                                        relative_precision=self.wf_relative_precision,
                                                                                                        start_integration_longitudinal_position=self.wf_start_integration_longitudinal_position,
                                                                                                        end_integration_longitudinal_position=self.wf_end_integration_longitudinal_position,
                                                                                                        number_of_points_for_trajectory_calculation=self.wf_number_of_points_for_trajectory_calculation,
                                                                                                        use_terminating_terms=self.wf_use_terminating_terms,
                                                                                                        sampling_factor_for_adjusting_nx_ny=self.wf_sampling_factor_for_adjusting_nx_ny))
        return srw_source.get_SRW_Wavefront(source_wavefront_parameters=wf_parameters)

    def get_photon_energy_for_wavefront_propagation(self, srw_source):
        return self.wf_photon_energy

    def get_minimum_propagation_distance(self):
        return round(self.get_source_length()*1.01, 6)

    def get_source_length(self):
        raise NotImplementedError()

    def receive_syned_data(self, data):
        if not data is None:
            try:
                if data.get_beamline_elements_number() > 0:
                    slit_element = data.get_beamline_element_at(0)
                    slit = slit_element.get_optical_element()
                    coordinates = slit_element.get_coordinates()

                    if isinstance(slit, Slit) and isinstance(slit.get_boundary_shape(), Rectangle):
                        rectangle = slit.get_boundary_shape()

                        self.wf_h_slit_gap = rectangle._x_right - rectangle._x_left
                        self.wf_v_slit_gap = rectangle._y_top - rectangle._y_bottom
                        self.wf_distance = coordinates.p()

                        self.int_h_slit_gap = rectangle._x_right - rectangle._x_left
                        self.int_v_slit_gap = rectangle._y_top - rectangle._y_bottom
                        self.int_distance = coordinates.p()

                        self.spe_h_slit_gap = rectangle._x_right - rectangle._x_left
                        self.spe_v_slit_gap = rectangle._y_top - rectangle._y_bottom
                        self.spe_distance = coordinates.p()
                elif not data._light_source is None and isinstance(data._light_source, LightSource):
                    light_source = data._light_source

                    self.source_name = light_source._name
                    self.electron_energy_in_GeV = light_source._electron_beam._energy_in_GeV
                    self.electron_energy_spread = light_source._electron_beam._energy_spread
                    self.ring_current = light_source._electron_beam._current

                    self.moment_xx = light_source._electron_beam._moment_xx
                    self.moment_xxp = light_source._electron_beam._moment_xxp
                    self.moment_xpxp = light_source._electron_beam._moment_xpxp
                    self.moment_yy = light_source._electron_beam._moment_yy
                    self.moment_yyp = light_source._electron_beam._moment_yyp
                    self.moment_ypyp = light_source._electron_beam._moment_ypyp

                    x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                    self.electron_beam_size_h = round(x, 9)
                    self.electron_beam_size_v = round(y, 9)
                    self.electron_beam_divergence_h = round(xp, 10)
                    self.electron_beam_divergence_v = round(yp, 10)

                    self.type_of_properties = 0

                    self.set_TypeOfProperties()

                    self.receive_specific_syned_data(data)
                else:
                    raise ValueError("Syned data not correct")
            except Exception as exception:
                QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)

    def receive_specific_syned_data(self, data):
        raise NotImplementedError()

    def callback_electron_energy(self):
        pass
class OWundulator_power_density(XoppyWidget, WidgetDecorator):
    name = "Undulator Power Density"
    id = "orange.widgets.dataundulator_power_density"
    description = "Undulator Power Density"
    icon = "icons/xoppy_undulator_power_density.png"
    priority = 3
    category = ""
    keywords = ["xoppy", "undulator_power_density"]

    USEEMITTANCES = Setting(1)
    ELECTRONENERGY = Setting(6.04)
    ELECTRONENERGYSPREAD = Setting(0.001)
    ELECTRONCURRENT = Setting(0.2)
    ELECTRONBEAMSIZEH = Setting(0.000395)
    ELECTRONBEAMSIZEV = Setting(9.9e-06)
    ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05)
    ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06)
    PERIODID = Setting(0.018)
    NPERIODS = Setting(222)
    KV = Setting(1.68)
    KH = Setting(0.0)
    KPHASE = Setting(0.0)
    DISTANCE = Setting(30.0)
    GAPH = Setting(0.01)
    GAPV = Setting(0.01)
    HSLITPOINTS = Setting(41)
    VSLITPOINTS = Setting(41)
    METHOD = Setting(2)
    MASK_FLAG = Setting(0)
    MASK_ROT_H_DEG = Setting(0.0)
    MASK_ROT_V_DEG = Setting(0.0)
    MASK_H_MIN = Setting(-1000.0)
    MASK_H_MAX = Setting(1000.0)
    MASK_V_MIN = Setting(-1000.0)
    MASK_V_MAX = Setting(1000.0)

    H5_FILE_DUMP = Setting(0)
    inputs = WidgetDecorator.syned_input_data()

    def __init__(self):
        super().__init__(show_script_tab=True)

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1
        #
        #
        #
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "USEEMITTANCES",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        # self.id_ELECTRONENERGY = oasysgui.lineEdit(box1, self, "ELECTRONENERGY",
        #              label=self.unitLabels()[idx], addSpace=False,
        #             valueType=float, orientation="horizontal", labelWidth=250)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGY",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)

        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGYSPREAD",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONCURRENT",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMSIZEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEH",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONBEAMDIVERGENCEV",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1,
                                             self,
                                             "PERIODID",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1,
                                             self,
                                             "NPERIODS",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=int,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1,
                                       self,
                                       "KV",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9 B
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KH = oasysgui.lineEdit(box1,
                                       self,
                                       "KH",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9 C
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KPHASE = oasysgui.lineEdit(box1,
                                           self,
                                           "KPHASE",
                                           label=self.unitLabels()[idx],
                                           addSpace=False,
                                           valueType=float,
                                           orientation="horizontal",
                                           labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "DISTANCE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPH",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "GAPV",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "VSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "METHOD",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['US', 'URGENT', 'SRW'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #
        # Mask
        #

        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "MASK_FLAG",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 17
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MASK_ROT_H_DEG",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 18
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MASK_ROT_V_DEG",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 19
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MASK_H_MIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 20
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MASK_H_MAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 21
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MASK_V_MIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 22
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "MASK_V_MAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 23
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "H5_FILE_DUMP",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['No', 'Yes: undulator_power_density.h5'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return ["Use emittances","Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]",\
                "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", \
                "Period ID [m]", "Number of periods", "Kv [K value vertical field]", \
                "Kh [K value horizontal field]","Kphase [Phase diff Kh-Kv in rad]",\
                "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "Number of slit mesh points in H", "Number of slit mesh points in V",\
                "calculation code",\
                "modify slit","Rotation around H axis [deg]","Rotation around V axis [deg]","Mask H min [mm]","Mask H max [mm]",'Mask V min [mm]',"Mask V max [mm]",\
                "Dump hdf5 file"]

    def unitFlags(self):
        return ["True","True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True",\
                "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", \
                "True", "True", "True",\
                "self.METHOD != 0","self.METHOD != 0",\
                "True", "True", "True", "True", "True",\
                "True",\
                "True","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1",\
                "True"]

    def get_help_name(self):
        return 'undulator_power_density'

    def check_fields(self):

        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONENERGY, "Electron Energy")
        if not self.METHOD == 1:
            self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(
                self.ELECTRONENERGYSPREAD, "Electron Energy Spread")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONCURRENT, "Electron Current")
        self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEH, "Electron Beam Size H")
        self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMSIZEV, "Electron Beam Size V")
        self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H")
        self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber(
            self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V")
        self.PERIODID = congruence.checkStrictlyPositiveNumber(
            self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(
            self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.KH = congruence.checkPositiveNumber(self.KH, "Kh")
        self.KPHASE = congruence.checkNumber(self.KPHASE, "Kphase")
        self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE,
                                                       "Distance to slit")
        self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H")
        self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V")
        self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.HSLITPOINTS, "Number of slit mesh points in H")
        self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.VSLITPOINTS, "Number of slit mesh points in V")

        if self.METHOD == 1:  # URGENT
            congruence.checkLessOrEqualThan(
                self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT ",
                " 51")
            congruence.checkLessOrEqualThan(
                self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT ",
                " 51")

        # if sys.platform == 'linux' and self.METHOD == 2:
        #     raise Exception("SRW calculation code not supported under Linux")

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:

                self.initializeTabs(
                )  # added by srio to avoid overlapping graphs

                self.view_type_combo.setEnabled(False)

                data = calculated_data.get_content("xoppy_data")
                code = calculated_data.get_content("xoppy_code")

                h = data[0]
                v = data[1]
                p = data[2]

                try:

                    print("\nResult arrays (shapes): ", h.shape, v.shape,
                          p.shape)

                    self.plot_data2D(p,
                                     h,
                                     v,
                                     0,
                                     0,
                                     xtitle='H [mm]',
                                     ytitle='V [mm]',
                                     title='Code ' + code +
                                     '; Power density [W/mm^2]')

                except Exception as e:
                    self.view_type_combo.setEnabled(True)

                    raise Exception("Data not plottable: bad content\n" +
                                    str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def do_xoppy_calculation(self):
        if self.H5_FILE_DUMP == 0:
            h5_file = ""
        else:
            h5_file = "undulator_power_density.h5"

        h5_parameters = {
            "ELECTRONENERGY": self.ELECTRONENERGY,
            "ELECTRONENERGYSPREAD": self.ELECTRONENERGYSPREAD,
            "ELECTRONCURRENT": self.ELECTRONCURRENT,
            "ELECTRONBEAMSIZEH": self.ELECTRONBEAMSIZEH,
            "ELECTRONBEAMSIZEV": self.ELECTRONBEAMSIZEV,
            "ELECTRONBEAMDIVERGENCEH": self.ELECTRONBEAMDIVERGENCEH,
            "ELECTRONBEAMDIVERGENCEV": self.ELECTRONBEAMDIVERGENCEV,
            "PERIODID": self.PERIODID,
            "NPERIODS": self.NPERIODS,
            "KV": self.KV,
            "KH": self.KH,
            "KPHASE": self.KPHASE,
            "DISTANCE": self.DISTANCE,
            "GAPH": self.GAPH,
            "GAPV": self.GAPV,
            "HSLITPOINTS": self.HSLITPOINTS,
            "VSLITPOINTS": self.VSLITPOINTS,
            "METHOD": self.METHOD,
            "USEEMITTANCES": self.USEEMITTANCES,
            "MASK_FLAG": self.MASK_FLAG,
            "MASK_ROT_H_DEG": self.MASK_ROT_H_DEG,
            "MASK_ROT_V_DEG": self.MASK_ROT_V_DEG,
            "MASK_H_MIN": self.MASK_H_MIN,
            "MASK_H_MAX": self.MASK_H_MAX,
            "MASK_V_MIN": self.MASK_V_MIN,
            "MASK_V_MAX": self.MASK_V_MAX,
        }

        h, v, p, code = xoppy_calc_undulator_power_density(
            ELECTRONENERGY=self.ELECTRONENERGY,
            ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD,
            ELECTRONCURRENT=self.ELECTRONCURRENT,
            ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH,
            ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV,
            ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH,
            ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV,
            PERIODID=self.PERIODID,
            NPERIODS=self.NPERIODS,
            KV=self.KV,
            KH=self.KH,
            KPHASE=self.KPHASE,
            DISTANCE=self.DISTANCE,
            GAPH=self.GAPH,
            GAPV=self.GAPV,
            HSLITPOINTS=self.HSLITPOINTS,
            VSLITPOINTS=self.VSLITPOINTS,
            METHOD=self.METHOD,
            USEEMITTANCES=self.USEEMITTANCES,
            MASK_FLAG=self.MASK_FLAG,
            MASK_ROT_H_DEG=self.MASK_ROT_H_DEG,
            MASK_ROT_V_DEG=self.MASK_ROT_V_DEG,
            MASK_H_MIN=self.MASK_H_MIN,
            MASK_H_MAX=self.MASK_H_MAX,
            MASK_V_MIN=self.MASK_V_MIN,
            MASK_V_MAX=self.MASK_V_MAX,
            h5_file=h5_file,
            h5_entry_name="XOPPY_POWERDENSITY",
            h5_initialize=True,
            h5_parameters=h5_parameters,
        )

        self.xoppy_script.set_code(
            self.script_template().format_map(h5_parameters))

        return h, v, p, code

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:undulator_spectrum)
#
from orangecontrib.xoppy.util.xoppy_undulators import xoppy_calc_undulator_power_density

h5_parameters = dict()
h5_parameters["ELECTRONENERGY"]=           {ELECTRONENERGY}
h5_parameters["ELECTRONENERGYSPREAD"]=     {ELECTRONENERGYSPREAD}
h5_parameters["ELECTRONCURRENT"]=          {ELECTRONCURRENT}
h5_parameters["ELECTRONBEAMSIZEH"]=        {ELECTRONBEAMSIZEH}
h5_parameters["ELECTRONBEAMSIZEV"]=        {ELECTRONBEAMSIZEV}
h5_parameters["ELECTRONBEAMDIVERGENCEH"]=  {ELECTRONBEAMDIVERGENCEH}
h5_parameters["ELECTRONBEAMDIVERGENCEV"]=  {ELECTRONBEAMDIVERGENCEV}
h5_parameters["PERIODID"]=                 {PERIODID}
h5_parameters["NPERIODS"]=                 {NPERIODS}
h5_parameters["KV"]=                       {KV}
h5_parameters["KH"]=                       {KH}
h5_parameters["KPHASE"]=                   {KPHASE}
h5_parameters["DISTANCE"]=                 {DISTANCE}
h5_parameters["GAPH"]=                     {GAPH}
h5_parameters["GAPV"]=                     {GAPV}
h5_parameters["HSLITPOINTS"]=              {HSLITPOINTS}
h5_parameters["VSLITPOINTS"]=              {VSLITPOINTS}
h5_parameters["METHOD"]=                   {METHOD}
h5_parameters["USEEMITTANCES"]=            {USEEMITTANCES}
h5_parameters["MASK_FLAG"]=                {MASK_FLAG}
h5_parameters["MASK_ROT_H_DEG"]=           {MASK_ROT_H_DEG}
h5_parameters["MASK_ROT_V_DEG"]=           {MASK_ROT_V_DEG}
h5_parameters["MASK_H_MIN"]=               {MASK_H_MIN}
h5_parameters["MASK_H_MAX"]=               {MASK_H_MAX}
h5_parameters["MASK_V_MIN"]=               {MASK_V_MIN}
h5_parameters["MASK_V_MAX"]=               {MASK_V_MAX}

        
h, v, p, code = xoppy_calc_undulator_power_density(
    ELECTRONENERGY           =  h5_parameters["ELECTRONENERGY"],
    ELECTRONENERGYSPREAD     =  h5_parameters["ELECTRONENERGYSPREAD"],
    ELECTRONCURRENT          =  h5_parameters["ELECTRONCURRENT"],
    ELECTRONBEAMSIZEH        =  h5_parameters["ELECTRONBEAMSIZEH"],
    ELECTRONBEAMSIZEV        =  h5_parameters["ELECTRONBEAMSIZEV"],
    ELECTRONBEAMDIVERGENCEH  =  h5_parameters["ELECTRONBEAMDIVERGENCEH"],
    ELECTRONBEAMDIVERGENCEV  =  h5_parameters["ELECTRONBEAMDIVERGENCEV"],
    PERIODID                 =  h5_parameters["PERIODID"],
    NPERIODS                 =  h5_parameters["NPERIODS"],
    KV                       =  h5_parameters["KV"],
    KH                       =  h5_parameters["KH"],
    KPHASE                   =  h5_parameters["KPHASE"],
    DISTANCE                 =  h5_parameters["DISTANCE"],
    GAPH                     =  h5_parameters["GAPH"],
    GAPV                     =  h5_parameters["GAPV"],
    HSLITPOINTS              =  h5_parameters["HSLITPOINTS"],
    VSLITPOINTS              =  h5_parameters["VSLITPOINTS"],
    METHOD                   =  h5_parameters["METHOD"],
    USEEMITTANCES            =  h5_parameters["USEEMITTANCES"],
    MASK_FLAG                =  h5_parameters["MASK_FLAG"],
    MASK_ROT_H_DEG           =  h5_parameters["MASK_ROT_H_DEG"],
    MASK_ROT_V_DEG           =  h5_parameters["MASK_ROT_V_DEG"],
    MASK_H_MIN               =  h5_parameters["MASK_H_MIN"],
    MASK_H_MAX               =  h5_parameters["MASK_H_MAX"],
    MASK_V_MIN               =  h5_parameters["MASK_V_MIN"],
    MASK_V_MAX               =  h5_parameters["MASK_V_MAX"],
    h5_file                  =  "undulator_power_density.h5",
    h5_entry_name            =  "XOPPY_POWERDENSITY",
    h5_initialize            =  True,
    h5_parameters            =  h5_parameters,
    )
# example plot
from srxraylib.plot.gol import plot_image
plot_image(p,h,v,xtitle="H [mm]",ytitle="V [mm]",title="Power density W/mm2")
#
# end script
#
"""

    def extract_data_from_xoppy_output(self, calculation_output):
        h, v, p, code = calculation_output

        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())

        calculated_data.add_content("xoppy_data", [h, v, p])
        calculated_data.add_content("xoppy_code", code)

        return calculated_data

    def get_data_exchange_widget_name(self):
        return "UNDULATOR_POWER_DENSITY"

    def getTitles(self):
        return ['Undulator Power Density']

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread
                self.ELECTRONCURRENT = light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.ELECTRONBEAMSIZEH = x
                self.ELECTRONBEAMSIZEV = y
                self.ELECTRONBEAMDIVERGENCEH = xp
                self.ELECTRONBEAMDIVERGENCEV = yp
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KV = light_source._magnetic_structure._K_vertical
                self.KH = light_source._magnetic_structure._K_horizontal
                # TODO self.KPHASE = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):
        if value == True:
            self.id_ELECTRONENERGY.setEnabled(True)
            self.id_ELECTRONENERGYSPREAD.setEnabled(True)
            self.id_ELECTRONBEAMSIZEH.setEnabled(True)
            self.id_ELECTRONBEAMSIZEV.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True)
            self.id_ELECTRONCURRENT.setEnabled(True)
            self.id_PERIODID.setEnabled(True)
            self.id_NPERIODS.setEnabled(True)
            self.id_KV.setEnabled(True)
            self.id_KH.setEnabled(True)
            self.id_KPHASE.setEnabled(True)
        else:
            self.id_ELECTRONENERGY.setEnabled(False)
            self.id_ELECTRONENERGYSPREAD.setEnabled(False)
            self.id_ELECTRONBEAMSIZEH.setEnabled(False)
            self.id_ELECTRONBEAMSIZEV.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False)
            self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False)
            self.id_ELECTRONCURRENT.setEnabled(False)
            self.id_PERIODID.setEnabled(False)
            self.id_NPERIODS.setEnabled(False)
            self.id_KV.setEnabled(False)
            self.id_KH.setEnabled(False)
            self.id_KPHASE.setEnabled(False)
Exemple #23
0
class OWxtc(XoppyWidget):
    name = "TC"
    id = "orange.widgets.dataxtc"
    description = "Undulator Tuning Curves"
    icon = "icons/xoppy_xtc.png"
    priority = 7
    category = ""
    keywords = ["xoppy", "xtc"]

    #19 variables (minus one: TITLE removed)
    ENERGY = Setting(7.0)
    CURRENT = Setting(100.0)
    ENERGY_SPREAD = Setting(0.00096)
    SIGX = Setting(0.274)
    SIGY = Setting(0.011)
    SIGX1 = Setting(0.0113)
    SIGY1 = Setting(0.0036)
    PERIOD = Setting(3.23)
    NP = Setting(70)
    EMIN = Setting(2950.0)
    EMAX = Setting(13500.0)
    N = Setting(40)
    HARMONIC_FROM = Setting(1)
    HARMONIC_TO = Setting(15)
    HARMONIC_STEP = Setting(2)
    HELICAL = Setting(0)
    METHOD = Setting(1)
    NEKS = Setting(100)

    inputs = WidgetDecorator.syned_input_data()

    def build_gui(self):

        self.IMAGE_WIDTH = 850

        box = oasysgui.widgetBox(self.controlArea,
                                 self.name + " Input Parameters",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 5)

        idx = -1

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ENERGY = oasysgui.lineEdit(box1,
                                           self,
                                           "ENERGY",
                                           label=self.unitLabels()[idx],
                                           addSpace=False,
                                           valueType=float,
                                           validator=QDoubleValidator(),
                                           orientation="horizontal",
                                           labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_CURRENT = oasysgui.lineEdit(box1,
                                            self,
                                            "CURRENT",
                                            label=self.unitLabels()[idx],
                                            addSpace=False,
                                            valueType=float,
                                            validator=QDoubleValidator(),
                                            orientation="horizontal",
                                            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ENERGY_SPREAD = oasysgui.lineEdit(box1,
                                                  self,
                                                  "ENERGY_SPREAD",
                                                  label=self.unitLabels()[idx],
                                                  addSpace=False,
                                                  valueType=float,
                                                  validator=QDoubleValidator(),
                                                  orientation="horizontal",
                                                  labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_SIGX = oasysgui.lineEdit(box1,
                                         self,
                                         "SIGX",
                                         label=self.unitLabels()[idx],
                                         addSpace=False,
                                         valueType=float,
                                         validator=QDoubleValidator(),
                                         orientation="horizontal",
                                         labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_SIGY = oasysgui.lineEdit(box1,
                                         self,
                                         "SIGY",
                                         label=self.unitLabels()[idx],
                                         addSpace=False,
                                         valueType=float,
                                         validator=QDoubleValidator(),
                                         orientation="horizontal",
                                         labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_SIGX1 = oasysgui.lineEdit(box1,
                                          self,
                                          "SIGX1",
                                          label=self.unitLabels()[idx],
                                          addSpace=False,
                                          valueType=float,
                                          validator=QDoubleValidator(),
                                          orientation="horizontal",
                                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_SIGY1 = oasysgui.lineEdit(box1,
                                          self,
                                          "SIGY1",
                                          label=self.unitLabels()[idx],
                                          addSpace=False,
                                          valueType=float,
                                          validator=QDoubleValidator(),
                                          orientation="horizontal",
                                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIOD = oasysgui.lineEdit(box1,
                                           self,
                                           "PERIOD",
                                           label=self.unitLabels()[idx],
                                           addSpace=False,
                                           valueType=float,
                                           validator=QDoubleValidator(),
                                           orientation="horizontal",
                                           labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NP = oasysgui.lineEdit(box1,
                                       self,
                                       "NP",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=int,
                                       validator=QIntValidator(),
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "EMIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "EMAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          validator=QDoubleValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 15
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "N",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 17
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HARMONIC_FROM",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 18
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HARMONIC_TO",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 19
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HARMONIC_STEP",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 21
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "HELICAL",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Planar undulator', 'Helical undulator'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 22
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "METHOD",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Finite-N', 'Infinite N with convolution'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 24
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "NEKS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          validator=QIntValidator(),
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return [
            'Electron energy (GeV)', 'Current (mA)', 'Energy Spread (DE/E)',
            'Sigma X (mm)', 'Sigma Y (mm)', "Sigma X' (mrad)",
            "Sigma Y' (mrad)", 'Period length (cm)', 'Number of periods',
            'E1 minimum energy (eV)', 'E1 maximum energy (eV)',
            'Number of energy-points', 'Minimum harmonic number',
            'Maximum harmonic number', 'Harmonic step size', 'Mode', 'Method',
            'Intrinsic NEKS'
        ]

    def unitFlags(self):
        return ['True' for i in range(19)]

    def get_help_name(self):
        return 'tc'

    def check_fields(self):
        self.ENERGY = congruence.checkStrictlyPositiveNumber(
            self.ENERGY, "Electron Energy")
        self.CURRENT = congruence.checkStrictlyPositiveNumber(
            self.CURRENT, "Current")
        self.ENERGY_SPREAD = congruence.checkStrictlyPositiveNumber(
            self.ENERGY_SPREAD, "Energy Spread")
        self.SIGX = congruence.checkPositiveNumber(self.SIGX, "Sigma X")
        self.SIGY = congruence.checkPositiveNumber(self.SIGY, "Sigma Y")
        self.SIGX1 = congruence.checkPositiveNumber(self.SIGX1, "Sigma X'")
        self.SIGY1 = congruence.checkPositiveNumber(self.SIGY1, "Sigma Y'")
        self.PERIOD = congruence.checkStrictlyPositiveNumber(
            self.PERIOD, "Period length")
        self.NP = congruence.checkStrictlyPositiveNumber(
            self.NP, "Number of periods")
        self.EMIN = congruence.checkPositiveNumber(self.EMIN,
                                                   "E1 minimum energy")
        self.EMAX = congruence.checkStrictlyPositiveNumber(
            self.EMAX, "E1 maximum energy")
        congruence.checkLessThan(self.EMIN, self.EMAX, "E1 minimum energy",
                                 "E1 maximum energy")
        self.N = congruence.checkStrictlyPositiveNumber(
            self.N, "Number of Energy Points")
        self.HARMONIC_FROM = congruence.checkStrictlyPositiveNumber(
            self.HARMONIC_FROM, "Minimum harmonic number")
        self.HARMONIC_TO = congruence.checkStrictlyPositiveNumber(
            self.HARMONIC_TO, "Maximum harmonic number")
        congruence.checkLessThan(self.HARMONIC_FROM, self.HARMONIC_TO,
                                 "Minimum harmonic number",
                                 "Maximum harmonic number")
        self.HARMONIC_STEP = congruence.checkStrictlyPositiveNumber(
            self.HARMONIC_STEP, "Harmonic step size")
        self.NEKS = congruence.checkPositiveNumber(self.NEKS, "Intrinsic NEKS")

    def do_xoppy_calculation(self):
        return self.xoppy_calc_xtc()

    def extract_data_from_xoppy_output(self, calculation_output):
        return calculation_output

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:
                self.view_type_combo.setEnabled(False)

                xoppy_data_harmonics = calculated_data.get_content(
                    "xoppy_data_harmonics")

                titles = self.getTitles()
                xtitles = self.getXTitles()
                ytitles = self.getYTitles()

                progress_bar_step = (100 - progressBarValue) / len(titles)

                for index in range(0, len(titles)):
                    x_index, y_index = self.getVariablesToPlot()[index]
                    log_x, log_y = self.getLogPlot()[index]

                    if not self.plot_canvas[index] is None:
                        self.plot_canvas[index].clear()

                    try:
                        for h_index in range(0, len(xoppy_data_harmonics)):

                            self.plot_histo(
                                xoppy_data_harmonics[h_index][1][:, x_index],
                                xoppy_data_harmonics[h_index][1][:, y_index],
                                progressBarValue +
                                ((index + 1) * progress_bar_step),
                                tabs_canvas_index=index,
                                plot_canvas_index=index,
                                title=titles[index],
                                xtitle=xtitles[index],
                                ytitle=ytitles[index],
                                log_x=log_x,
                                log_y=log_y,
                                harmonic=xoppy_data_harmonics[h_index][0],
                                control=True)

                        self.plot_canvas[index].addCurve(
                            numpy.zeros(1),
                            numpy.array([
                                max(xoppy_data_harmonics[h_index][1][:,
                                                                     y_index])
                            ]),
                            "Click on curve to highlight it",
                            xlabel=xtitles[index],
                            ylabel=ytitles[index],
                            symbol='',
                            color='white')

                        self.plot_canvas[index].setActiveCurve(
                            "Click on curve to highlight it")
                        self.plot_canvas[index].getLegendsDockWidget(
                        ).setFixedHeight(150)
                        self.plot_canvas[index].getLegendsDockWidget(
                        ).setVisible(True)

                        self.tabs.setCurrentIndex(index)
                    except Exception as e:
                        self.view_type_combo.setEnabled(True)

                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                self.view_type_combo.setEnabled(True)
            else:
                raise Exception("Empty Data")

    def plot_histo(self,
                   x,
                   y,
                   progressBarValue,
                   tabs_canvas_index,
                   plot_canvas_index,
                   title="",
                   xtitle="",
                   ytitle="",
                   log_x=False,
                   log_y=False,
                   harmonic=1,
                   color='blue',
                   control=True):
        h_title = "Harmonic " + str(harmonic)

        hex_r = hex(min(255, 128 + harmonic * 10))[2:].upper()
        hex_g = hex(min(255, 20 + harmonic * 15))[2:].upper()
        hex_b = hex(min(255, harmonic * 10))[2:].upper()
        if len(hex_r) == 1: hex_r = "0" + hex_r
        if len(hex_g) == 1: hex_g = "0" + hex_g
        if len(hex_b) == 1: hex_b = "0" + hex_b

        super().plot_histo(x,
                           y,
                           progressBarValue,
                           tabs_canvas_index,
                           plot_canvas_index,
                           h_title,
                           xtitle,
                           ytitle,
                           log_x,
                           log_y,
                           color="#" + hex_r + hex_g + hex_b,
                           replace=False,
                           control=control)

        self.plot_canvas[plot_canvas_index].setGraphTitle(title)
        self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True)
        self.plot_canvas[plot_canvas_index].setDefaultPlotPoints(True)

    def get_data_exchange_widget_name(self):
        return "XTC"

    def getTitles(self):
        return ["Brilliance", "Ky", "Total Power", "Power density"]

    def getXTitles(self):
        return ["Energy (eV)", "Energy (eV)", "Energy (eV)", "Energy (eV)"]

    def getYTitles(self):
        return [
            "Brilliance (ph/s/mrad^2/mm^2/0.1%bw)", "Ky", "Total Power (W)",
            "Power density (W/mr^2)"
        ]

    def getVariablesToPlot(self):
        return [(1, 2), (1, 3), (1, 4), (1, 5)]

    def getLogPlot(self):
        return [(False, True), (False, False), (False, False), (False, False)]

    def xoppy_calc_xtc(self):

        for file in ["tc.inp", "tc.out"]:
            try:
                os.remove(os.path.join(locations.home_bin_run(), file))
            except:
                pass

        with open("tc.inp", "wt") as f:
            f.write("TS called from xoppy\n")
            f.write("%10.3f %10.2f %10.6f %s\n" %
                    (self.ENERGY, self.CURRENT, self.ENERGY_SPREAD,
                     "Ring-Energy(GeV) Current(mA) Beam-Energy-Spread"))
            f.write("%10.4f %10.4f %10.4f %10.4f %s\n" %
                    (self.SIGX, self.SIGY, self.SIGX1, self.SIGY1,
                     "Sx(mm) Sy(mm) Sx1(mrad) Sy1(mrad)"))
            f.write("%10.3f %d %s\n" % (self.PERIOD, self.NP, "Period(cm) N"))
            f.write("%10.1f %10.1f %d %s\n" %
                    (self.EMIN, self.EMAX, self.N, "Emin Emax Ne"))
            f.write("%d %d %d %s\n" % (self.HARMONIC_FROM, self.HARMONIC_TO,
                                       self.HARMONIC_STEP, "Hmin Hmax Hstep"))
            f.write("%d %d %d %d %s\n" %
                    (self.HELICAL, self.METHOD, 1, self.NEKS,
                     "Helical Method Print_K Neks"))
            f.write("foreground\n")

        if platform.system() == "Windows":
            command = os.path.join(locations.home_bin(), 'tc.exe')
        else:
            command = "'" + os.path.join(locations.home_bin(), 'tc') + "'"

        print("Running command '%s' in directory: %s " %
              (command, locations.home_bin_run()))
        print("\n--------------------------------------------------------\n")
        os.system(command)
        print("Output file: %s" % ("tc.out"))
        print("\n--------------------------------------------------------\n")

        #
        # parse result files to exchange object
        #

        with open("tc.out", "r") as f:
            lines = f.readlines()

        # print output file
        # for line in lines:
        #     print(line, end="")

        # remove returns
        lines = [line[:-1] for line in lines]
        harmonics_data = []

        # separate numerical data from text
        floatlist = []
        harmoniclist = []
        txtlist = []
        for line in lines:
            try:
                tmp = line.strip()

                if tmp.startswith("Harmonic"):
                    harmonic_number = int(tmp.split("Harmonic")[1].strip())

                    if harmonic_number != self.HARMONIC_FROM:
                        harmonics_data[-1][1] = harmoniclist
                        harmoniclist = []

                    harmonics_data.append([harmonic_number, None])

                tmp = float(line.strip()[0])

                floatlist.append(line)
                harmoniclist.append(line)
            except:
                txtlist.append(line)

        harmonics_data[-1][1] = harmoniclist

        data = numpy.loadtxt(floatlist)

        for index in range(0, len(harmonics_data)):
            # print (harmonics_data[index][0], harmonics_data[index][1])
            harmonics_data[index][1] = numpy.loadtxt(harmonics_data[index][1])

        #send exchange
        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())

        try:
            calculated_data.add_content("xoppy_data", data)
            calculated_data.add_content("xoppy_data_harmonics", harmonics_data)
            calculated_data.add_content("plot_x_col", 1)
            calculated_data.add_content("plot_y_col", 2)
        except:
            pass
        try:
            calculated_data.add_content("labels", [
                "Energy (eV) without emittance", "Energy (eV) with emittance",
                "Brilliance (ph/s/mrad^2/mm^2/0.1%bw)", "Ky",
                "Total Power (W)", "Power density (W/mr^2)"
            ])
        except:
            pass
        try:
            calculated_data.add_content("info", txtlist)
        except:
            pass

        return calculated_data

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ENERGY = light_source._electron_beam._energy_in_GeV
                self.ENERGY_SPREAD = light_source._electron_beam._energy_spread
                self.CURRENT = 1000.0 * light_source._electron_beam._current

                x, xp, y, yp = light_source._electron_beam.get_sigmas_all()

                self.SIGX = 1e3 * x
                self.SIGY = 1e3 * y
                self.SIGX1 = 1e3 * xp
                self.SIGY1 = 1e3 * yp
                self.PERIOD = 100.0 * light_source._magnetic_structure._period_length
                self.NP = light_source._magnetic_structure._number_of_periods

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):
        if value == True:
            self.id_ENERGY.setEnabled(True)
            self.id_ENERGY_SPREAD.setEnabled(True)
            self.id_SIGX.setEnabled(True)
            self.id_SIGX1.setEnabled(True)
            self.id_SIGY.setEnabled(True)
            self.id_SIGY1.setEnabled(True)
            self.id_CURRENT.setEnabled(True)
            self.id_PERIOD.setEnabled(True)
            self.id_NP.setEnabled(True)
        else:
            self.id_ENERGY.setEnabled(False)
            self.id_ENERGY_SPREAD.setEnabled(False)
            self.id_SIGX.setEnabled(False)
            self.id_SIGX1.setEnabled(False)
            self.id_SIGY.setEnabled(False)
            self.id_SIGY1.setEnabled(False)
            self.id_CURRENT.setEnabled(False)
            self.id_PERIOD.setEnabled(False)
            self.id_NP.setEnabled(False)
Exemple #24
0
class OWwiggler_radiation(XoppyWidget, WidgetDecorator):
    name = "Wiggler Radiation"
    id = "wiggler_radiation"
    description = "Wiggler Radiation"
    icon = "icons/xoppy_wiggler_radiation.png"
    priority = 12
    category = ""
    keywords = ["xoppy", "wiggler_radiation"]

    # overwrite from
    outputs = [{"name": "xoppy_data", "type": DataExchangeObject, "doc": ""}]

    ELECTRONENERGY = Setting(3.0)
    ELECTRONCURRENT = Setting(0.1)
    PERIODID = Setting(0.120)
    NPERIODS = Setting(37.0)
    KV = Setting(22.416)
    DISTANCE = Setting(30.0)
    HSLITPOINTS = Setting(500)
    VSLITPOINTS = Setting(500)
    PHOTONENERGYMIN = Setting(100.0)
    PHOTONENERGYMAX = Setting(100100.0)
    PHOTONENERGYPOINTS = Setting(101)
    H5_FILE_DUMP = Setting(0)
    NTRAJPOINTS = Setting(1001)
    FIELD = Setting(0)
    FILE = Setting("")
    POLARIZATION = Setting(0)

    h5_file = Setting("wiggler_radiation.h5", )
    h5_entry_name = Setting("XOPPY_RADIATION", )
    h5_initialize = Setting(True, )
    h5_parameters = Setting(None, )

    SHIFT_X_FLAG = Setting(0)
    SHIFT_X_VALUE = Setting(0.0)
    SHIFT_BETAX_FLAG = Setting(0)
    SHIFT_BETAX_VALUE = Setting(0.0)
    CONVOLUTION = Setting(1)
    PASSEPARTOUT = Setting(3.0)

    bm_magnetic_radius = Setting(10.0)
    bm_magnetic_field = Setting(1.001)
    bm_divergence = Setting(1.0e-3)

    inputs = WidgetDecorator.syned_input_data()

    filename = ""

    # IS_DEVELOP = False

    def __init__(self):
        super().__init__(show_script_tab=True)

    def build_gui(self):

        tabs_setting = oasysgui.tabWidget(self.controlArea)
        tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5)

        tab_1 = oasysgui.createTabPage(tabs_setting,
                                       self.name + " Input Parameters")
        tab_2 = oasysgui.createTabPage(tabs_setting, "Advanced Settings")

        box0 = oasysgui.widgetBox(tab_1,
                                  "",
                                  orientation="vertical",
                                  width=self.CONTROL_AREA_WIDTH - 15)

        idx = -1

        #
        #
        #

        box = oasysgui.widgetBox(box0,
                                 "Electron beam",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONENERGY = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONENERGY",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_ELECTRONCURRENT = oasysgui.lineEdit(
            box1,
            self,
            "ELECTRONCURRENT",
            label=self.unitLabels()[idx],
            addSpace=False,
            valueType=float,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        box = oasysgui.widgetBox(box0,
                                 "Wiggler",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_FIELD = self.id_FIELD = gui.comboBox(
            box1,
            self,
            "FIELD",
            label=self.unitLabels()[idx],
            addSpace=False,
            items=['Sinusoidal', 'B from file', 'Bending magnet (cte B)'],
            valueType=int,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_PERIODID = oasysgui.lineEdit(box1,
                                             self,
                                             "PERIODID",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_NPERIODS = oasysgui.lineEdit(box1,
                                             self,
                                             "NPERIODS",
                                             label=self.unitLabels()[idx],
                                             addSpace=False,
                                             valueType=float,
                                             orientation="horizontal",
                                             labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        self.id_KV = oasysgui.lineEdit(box1,
                                       self,
                                       "KV",
                                       label=self.unitLabels()[idx],
                                       addSpace=False,
                                       valueType=float,
                                       orientation="horizontal",
                                       labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        file_box = oasysgui.widgetBox(box1,
                                      "",
                                      addSpace=False,
                                      orientation="horizontal",
                                      height=25)
        self.le_file = oasysgui.lineEdit(file_box,
                                         self,
                                         "FILE",
                                         label=self.unitLabels()[idx],
                                         addSpace=False,
                                         orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        gui.button(file_box, self, "...", callback=self.selectFile)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "bm_magnetic_radius",
                          label=self.unitLabels()[idx],
                          labelWidth=250,
                          callback=self.calculateMagneticField,
                          tooltip=self.unitLabels()[idx],
                          valueType=float,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "bm_magnetic_field",
                          label=self.unitLabels()[idx],
                          labelWidth=250,
                          callback=self.calculateMagneticRadius,
                          tooltip=self.unitLabels()[idx],
                          valueType=float,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "bm_divergence",
                          label=self.unitLabels()[idx],
                          labelWidth=250,
                          tooltip=self.unitLabels()[idx],
                          valueType=float,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        box = oasysgui.widgetBox(box0,
                                 "Scan",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)
        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "DISTANCE",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "HSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 14
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "VSLITPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYMIN",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYMAX",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=float,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index <><>
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PHOTONENERGYPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        box = oasysgui.widgetBox(box0,
                                 "Output",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)
        #widget index 16
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "H5_FILE_DUMP",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'None', 'Write h5 file: wiggler_radiation.h5',
                         'Read from file...'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250,
                     callback=self.read_or_write_file)
        self.show_at(self.unitFlags()[idx], box1)

        #
        # advanced
        #
        box0 = oasysgui.widgetBox(tab_2,
                                  "",
                                  orientation="vertical",
                                  width=self.CONTROL_AREA_WIDTH - 15)

        box = oasysgui.widgetBox(box0,
                                 "Electron trajectory",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "NTRAJPOINTS",
                          label=self.unitLabels()[idx],
                          addSpace=False,
                          valueType=int,
                          orientation="horizontal",
                          labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "SHIFT_BETAX_FLAG",
                     label=self.unitLabels()[idx],
                     items=[
                         "No shift", "Half excursion", "Minimum", "Maximum",
                         "Value at zero", "User value"
                     ],
                     labelWidth=260,
                     valueType=float,
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "SHIFT_BETAX_VALUE",
                          label=self.unitLabels()[idx],
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "SHIFT_X_FLAG",
                     label=self.unitLabels()[idx],
                     items=[
                         "No shift", "Half excursion", "Minimum", "Maximum",
                         "Value at zero", "User value"
                     ],
                     labelWidth=260,
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "SHIFT_X_VALUE",
                          label=self.unitLabels()[idx],
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        box = oasysgui.widgetBox(box0,
                                 "Photon divergence",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)
        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "CONVOLUTION",
                     label=self.unitLabels()[idx],
                     items=["No", "Yes [default]"],
                     labelWidth=260,
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        oasysgui.lineEdit(box1,
                          self,
                          "PASSEPARTOUT",
                          label=self.unitLabels()[idx],
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        box = oasysgui.widgetBox(box0,
                                 "Photon Polarization",
                                 orientation="vertical",
                                 width=self.CONTROL_AREA_WIDTH - 15)
        #widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "POLARIZATION",
                     label=self.unitLabels()[idx],
                     items=["Total", "Parellel", "Perpendicular"],
                     labelWidth=260,
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

    def unitLabels(self):
        return [
            "Electron Energy [GeV]",
            "Electron Current [A]",
            "Magnetic field: ",
            "Period ID [m]",
            "Number of periods",
            "Kv [K value vertical field]",
            'File/Url with Magnetic Field',
            'BM Magnetic radius [m]',
            'BM Magnetic field [T]',
            'BM divergence [rad]',
            "Distance to slit [m]",
            "Number of slit mesh points in H",
            "Number of slit mesh points in V",
            "Photon Energy Min [eV]",
            "Photon Energy Max [eV]",
            "Number of Photon Energy Points",
            "hdf5 file",
            'Number of traj points per period',
            "Shift Transversal Velocity",
            "Value",
            "Shift Transversal Coordinate",
            "Value",
            "Convolution electron x' with photon div",
            "Passepartout in sigma' units at Emin",
            "Polarization",
        ]

    # TODO check energy spread flag: set to False (not used at all)!!
    def unitFlags(self):
        flags = ["True"] * len(self.unitLabels())
        flags[3] = "self.FIELD == 0"
        flags[4] = "self.FIELD == 0"
        flags[5] = "self.FIELD == 0"
        flags[6] = "self.FIELD == 1"
        flags[7] = "self.FIELD == 2"
        flags[8] = "self.FIELD == 2"
        flags[9] = "self.FIELD == 2"
        flags[19] = "self.SHIFT_BETAX_FLAG == 5"
        flags[21] = "self.SHIFT_X_FLAG == 5"
        return flags

    def get_help_name(self):
        return 'wiggler_radiation'

    def selectFile(self):
        self.le_file.setText(
            oasysgui.selectFileFromDialog(self, self.FILE,
                                          "Open File with B map"))

    def read_or_write_file(self):

        value = self.H5_FILE_DUMP

        if value == 0:
            return
        elif value == 1:  # write
            return
        elif value == 2:  # read

            self.H5_FILE_DUMP = 0

            use_silx_file_dialog = False  # silx dialog is freezing the linux system, change to traditional

            if use_silx_file_dialog:
                tmp = ConfirmDialog.confirmed(
                    self,
                    message=
                    "Please select in a hdf5 file a data block\n(such as XOPPY_RADIATION)\nthat contains a 'Radiation' entry",
                    title="Confirm Action")
                if tmp == False: return
                dialog = DataFileDialog(self)
                dialog.setFilterMode(DataFileDialog.FilterMode.ExistingGroup)
                result = dialog.exec_()
                if not result:
                    return
                print(dialog.selectedFile())
                print(dialog.selectedUrl())
                print(dialog.selectedDataUrl().data_path())
                calculation_output = self.extract_data_from_h5file(
                    dialog.selectedFile(),
                    dialog.selectedDataUrl().data_path())
                self.filename = dialog.selectedFile()
            else:
                tmp = ConfirmDialog.confirmed(
                    self,
                    message=
                    "Please select a hdf5 file containing a data block\n named XOPPY_RADIATION which includes 'Radiation' entry",
                    title="Confirm Action")
                if tmp == False: return

                self.filename = oasysgui.selectFileFromDialog(
                    self,
                    previous_file_path=self.filename,
                    message="Open hdf5 File",
                    start_directory="",
                    file_extension_filter="*.*5")
                if self.filename == "":
                    return

                try:
                    calculation_output = self.extract_data_from_h5file(
                        self.filename, "/XOPPY_RADIATION")
                except:
                    QMessageBox.critical(
                        self, "Error",
                        str("Failed to load hdf5 /XOPPY_RADIATION"),
                        QMessageBox.Ok)
                    calculation_output = None

            if calculation_output is None:
                QMessageBox.critical(self, "Error", str("Bad data from file."),
                                     QMessageBox.Ok)
            else:
                self.calculated_data = self.extract_data_from_xoppy_output(
                    calculation_output)
                try:
                    self.set_fields_from_h5file(self.filename,
                                                "/XOPPY_RADIATION")
                except:
                    QMessageBox.critical(
                        self, "Error",
                        "Failed to set fields hdf5 /XOPPY_RADIATION/parameters \n",
                        QMessageBox.Ok)

                # self.add_specific_content_to_calculated_data(self.calculated_data)
                #
                self.setStatusMessage("Plotting Results")

                self.plot_results(self.calculated_data, progressBarValue=60)

                self.setStatusMessage("")

                # p, e, h, v = self.calculated_data.get_content("xoppy_data")
                # traj = self.calculated_data.get_content("xoppy_data")
                # data_to_send = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name())
                # data_to_send.add_content("xoppy_data", [p, e, h, v, traj])
                self.send("xoppy_data", self.calculated_data)

            self.set_enabled(True)

    def extract_data_from_h5file(self, file_h5, subtitle):

        hf = h5py.File(file_h5, 'r')

        try:
            p = hf[subtitle + "/Radiation/stack_data"][:]
            e = hf[subtitle + "/Radiation/axis0"][:]
            h = hf[subtitle + "/Radiation/axis1"][:]
            v = hf[subtitle + "/Radiation/axis2"][:]
            traj = hf[subtitle + "/trajectory/traj"][:]
        except:
            QMessageBox.critical(self, "Error", "Failed to load hdf5 data\n",
                                 QMessageBox.Ok)

        hf.close()

        return e, h, v, p, traj

    def set_fields_from_h5file(self, file_h5, subtitle):

        hf = h5py.File(file_h5, 'r')

        self.ELECTRONENERGY = hf[subtitle + "/parameters/ELECTRONENERGY"].value
        self.ELECTRONCURRENT = hf[subtitle +
                                  "/parameters/ELECTRONCURRENT"].value
        self.PERIODID = hf[subtitle + "/parameters/PERIODID"].value
        self.NPERIODS = hf[subtitle + "/parameters/NPERIODS"].value
        self.KV = hf[subtitle + "/parameters/KV"].value
        self.DISTANCE = hf[subtitle + "/parameters/DISTANCE"].value
        self.HSLITPOINTS = hf[subtitle + "/parameters/HSLITPOINTS"].value
        self.VSLITPOINTS = hf[subtitle + "/parameters/VSLITPOINTS"].value
        self.PHOTONENERGYMIN = hf[subtitle +
                                  "/parameters/PHOTONENERGYMIN"].value
        self.PHOTONENERGYMAX = hf[subtitle +
                                  "/parameters/PHOTONENERGYMAX"].value
        self.PHOTONENERGYPOINTS = hf[subtitle +
                                     "/parameters/PHOTONENERGYPOINTS"].value

        self.FIELD = hf[subtitle + "/parameters/FIELD"].value
        self.FILE = hf[subtitle + "/parameters/FILE"].value
        self.POLARIZATION = hf[subtitle + "/parameters/POLARIZATION"].value
        self.CONVOLUTION = hf[subtitle + "/parameters/CONVOLUTION"].value
        self.PASSEPARTOUT = hf[subtitle + "/parameters/PASSEPARTOUT"].value

        self.SHIFT_X_FLAG = hf[subtitle + "/parameters/SHIFT_X_FLAG"].value
        self.SHIFT_BETAX_FLAG = hf[subtitle +
                                   "/parameters/SHIFT_BETAX_FLAG"].value
        self.SHIFT_X_VALUE = hf[subtitle + "/parameters/SHIFT_X_VALUE"].value
        self.SHIFT_BETAX_VALUE = hf[subtitle +
                                    "/parameters/SHIFT_BETAX_VALUE"].value

        hf.close()

    def check_fields(self):
        self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONENERGY, "Electron Energy")
        self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(
            self.ELECTRONCURRENT, "Electron Current")

        self.PERIODID = congruence.checkStrictlyPositiveNumber(
            self.PERIODID, "Period ID")
        self.NPERIODS = congruence.checkStrictlyPositiveNumber(
            self.NPERIODS, "Number of Periods")
        self.KV = congruence.checkPositiveNumber(self.KV, "Kv")
        self.DISTANCE = congruence.checkStrictlyPositiveNumber(
            self.DISTANCE, "Distance to slit")

        self.PHOTONENERGYMIN = congruence.checkNumber(self.PHOTONENERGYMIN,
                                                      "Photon Energy Min")
        self.PHOTONENERGYMAX = congruence.checkNumber(self.PHOTONENERGYMAX,
                                                      "Photon Energy Max")
        congruence.checkGreaterOrEqualThan(self.PHOTONENERGYPOINTS, 2,
                                           "Number of Photon Energy Points",
                                           " 2")

        self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.HSLITPOINTS, "Number of slit mesh points in H")
        self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber(
            self.VSLITPOINTS, "Number of slit mesh points in V")

        self.NTRAJPOINTS = congruence.checkStrictlyPositiveNumber(
            self.NTRAJPOINTS, "Number Trajectory points")

        self.PASSEPARTOUT = congruence.checkStrictlyPositiveNumber(
            self.PASSEPARTOUT, "Passepartout in units of sigma' at Emin")

    def plot_results(self, calculated_data, progressBarValue=80):
        if not self.view_type == 0:
            if not calculated_data is None:

                self.initializeTabs(
                )  # added by srio to avoid overlapping graphs

                self.view_type_combo.setEnabled(False)

                p, e, h, v = calculated_data.get_content("xoppy_data")
                traj = calculated_data.get_content("xoppy_trajectory")
                # code = calculated_data.get_content("xoppy_code")

                try:
                    self.plot_data3D(
                        p,
                        e,
                        h,
                        v,
                        0,
                        0,
                        xtitle='H [mm]',
                        ytitle='V [mm]',
                        title='Flux [photons/s/0.1%bw/mm^2]',
                    )

                    self.tabs.setCurrentIndex(0)
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)
                    if self.IS_DEVELOP:
                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                try:
                    if len(e) > 1:
                        energy_step = e[1] - e[0]
                    else:
                        energy_step = 1.0

                    self.plot_data2D(
                        p.sum(axis=0) * energy_step * codata.e * 1e3,
                        h,
                        v,
                        1,
                        0,
                        xtitle='H [mm]',
                        ytitle='V [mm]',
                        title='Power density [W/mm^2]',
                    )
                except Exception as exception:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(exception),
                                         QMessageBox.Ok)
                    if self.IS_DEVELOP: raise exception

                    # except Exception as exception:
                    #     QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)
                    #
                    #     if self.IS_DEVELOP: raise exception

                    return False

                try:
                    self.plot_data1D(
                        e,
                        p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) *
                        (v[1] - v[0]),
                        2,
                        0,
                        xtitle='Photon Energy [eV]',
                        ytitle='Flux [photons/s/0.1%bw]',
                        title='Flux',
                    )
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)
                    if self.IS_DEVELOP:
                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                try:
                    self.plot_data1D(
                        e,
                        p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) *
                        (v[1] - v[0]) * codata.e * 1e3,
                        3,
                        0,
                        xtitle='Photon Energy [eV]',
                        ytitle='Spectral power [W/eV]',
                        title='Spectral power',
                    )
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)
                    if self.IS_DEVELOP:
                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                try:
                    self.plot_data1D(
                        traj[1, :],
                        traj[0, :],
                        4,
                        0,
                        xtitle="s [m]",
                        ytitle="X [m]",
                        title="Transversal Trajectory X(s)",
                    )
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)
                    if self.IS_DEVELOP:
                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                try:
                    self.plot_data1D(
                        traj[1, :],
                        traj[3, :],
                        5,
                        0,
                        xtitle="s [m]",
                        ytitle="betaX [c units]",
                        title="Transversal velocity betaX(s)",
                    )
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)
                    if self.IS_DEVELOP:
                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                try:
                    self.plot_data1D(
                        traj[1, :],
                        traj[7, :],
                        6,
                        0,
                        xtitle="s [m]",
                        ytitle="Bz [T]",
                        title="Magnetic field Bz(s)",
                    )
                except Exception as e:
                    self.view_type_combo.setEnabled(True)
                    QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok)
                    if self.IS_DEVELOP:
                        raise Exception("Data not plottable: bad content\n" +
                                        str(e))

                self.view_type_combo.setEnabled(True)
            else:
                QMessageBox.critical(self, "Error", "Empty data",
                                     QMessageBox.Ok)
                if self.IS_DEVELOP: raise Exception("Empty Data")

    def do_xoppy_calculation(self):

        if self.H5_FILE_DUMP == 0:
            h5_file = ""
        else:
            h5_file = "wiggler_radiation.h5"

        if self.FIELD == 0:
            FILE = ""
            FIELD = 0
        elif self.FIELD == 1:
            FILE = self.FILE
            FIELD = 1
        elif self.FIELD == 2:
            FILE = "bending_magnet_field.dat"
            create_magnetic_field_for_bending_magnet(
                do_plot=False,
                filename=FILE,
                B0=self.bm_magnetic_field,
                divergence=self.bm_divergence,
                radius=self.bm_magnetic_radius,
                npoints=self.NTRAJPOINTS)
            FIELD = 1

        if self.H5_FILE_DUMP == 0:
            h5_file = ""
        else:
            h5_file = "wiggler_radiation.h5"

        dict_parameters = {
            "ELECTRONENERGY": self.ELECTRONENERGY,
            "ELECTRONCURRENT": self.ELECTRONCURRENT,
            "PERIODID": self.PERIODID,
            "NPERIODS": self.NPERIODS,
            "KV": self.KV,
            "DISTANCE": self.DISTANCE,
            "HSLITPOINTS": self.HSLITPOINTS,
            "VSLITPOINTS": self.VSLITPOINTS,
            "PHOTONENERGYMIN": self.PHOTONENERGYMIN,
            "PHOTONENERGYMAX": self.PHOTONENERGYMAX,
            "PHOTONENERGYPOINTS": self.PHOTONENERGYPOINTS,
            "FIELD": FIELD,
            "FILE": FILE,
            "POLARIZATION": self.POLARIZATION,
            "SHIFT_X_FLAG": self.SHIFT_X_FLAG,
            "SHIFT_X_VALUE": self.SHIFT_X_VALUE,
            "SHIFT_BETAX_FLAG": self.SHIFT_BETAX_FLAG,
            "SHIFT_BETAX_VALUE": self.SHIFT_BETAX_VALUE,
            "CONVOLUTION": self.CONVOLUTION,
            "PASSEPARTOUT": self.PASSEPARTOUT,
        }

        # write python script
        self.xoppy_script.set_code(
            self.script_template().format_map(dict_parameters))

        e, h, v, p, traj = xoppy_calc_wiggler_radiation(
            ELECTRONENERGY=self.ELECTRONENERGY,
            ELECTRONCURRENT=self.ELECTRONCURRENT,
            PERIODID=self.PERIODID,
            NPERIODS=self.NPERIODS,
            KV=self.KV,
            DISTANCE=self.DISTANCE,
            HSLITPOINTS=self.HSLITPOINTS,
            VSLITPOINTS=self.VSLITPOINTS,
            PHOTONENERGYMIN=self.PHOTONENERGYMIN,
            PHOTONENERGYMAX=self.PHOTONENERGYMAX,
            PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS,
            FIELD=FIELD,
            FILE=FILE,
            POLARIZATION=self.POLARIZATION,
            SHIFT_X_FLAG=self.SHIFT_X_FLAG,
            SHIFT_X_VALUE=self.SHIFT_X_VALUE,
            SHIFT_BETAX_FLAG=self.SHIFT_BETAX_FLAG,
            SHIFT_BETAX_VALUE=self.SHIFT_BETAX_VALUE,
            CONVOLUTION=self.CONVOLUTION,
            PASSEPARTOUT=self.PASSEPARTOUT,
            h5_file=h5_file,
            h5_entry_name="XOPPY_RADIATION",
            h5_initialize=True,
            h5_parameters=dict_parameters,
        )

        return e, h, v, p, traj

    def script_template(self):
        return """
#
# script to make the calculations (created by XOPPY:wiggler_radiation)
#

from orangecontrib.xoppy.util.xoppy_bm_wiggler import xoppy_calc_wiggler_radiation

h5_parameters = dict()
h5_parameters["ELECTRONENERGY"]          = {ELECTRONENERGY}
h5_parameters["ELECTRONCURRENT"]         = {ELECTRONCURRENT}
h5_parameters["PERIODID"]                = {PERIODID}
h5_parameters["NPERIODS"]                = {NPERIODS}
h5_parameters["KV"]                      = {KV}
h5_parameters["FIELD"]                   = {FIELD}   # 0= sinusoidal, 1=from file
h5_parameters["FILE"]                    = '{FILE}'
h5_parameters["POLARIZATION"]            = {POLARIZATION}  # 0=total, 1=s, 2=p
h5_parameters["DISTANCE"]                = {DISTANCE}
h5_parameters["HSLITPOINTS"]             = {HSLITPOINTS}
h5_parameters["VSLITPOINTS"]             = {VSLITPOINTS}
h5_parameters["PHOTONENERGYMIN"]         = {PHOTONENERGYMIN}
h5_parameters["PHOTONENERGYMAX"]         = {PHOTONENERGYMAX}
h5_parameters["PHOTONENERGYPOINTS"]      = {PHOTONENERGYPOINTS}
h5_parameters["SHIFT_X_FLAG"]            = {SHIFT_X_FLAG}
h5_parameters["SHIFT_X_VALUE"]           = {SHIFT_X_VALUE}
h5_parameters["SHIFT_BETAX_FLAG"]        = {SHIFT_BETAX_FLAG}
h5_parameters["SHIFT_BETAX_VALUE"]       = {SHIFT_BETAX_VALUE}
h5_parameters["CONVOLUTION"]             = {CONVOLUTION}
h5_parameters["PASSEPARTOUT"]            = {PASSEPARTOUT}

e, h, v, p, traj = xoppy_calc_wiggler_radiation(
        ELECTRONENERGY           = h5_parameters["ELECTRONENERGY"]         ,
        ELECTRONCURRENT          = h5_parameters["ELECTRONCURRENT"]        ,
        PERIODID                 = h5_parameters["PERIODID"]               ,
        NPERIODS                 = h5_parameters["NPERIODS"]               ,
        KV                       = h5_parameters["KV"]                     ,
        FIELD                    = h5_parameters["FIELD"]                  ,
        FILE                     = h5_parameters["FILE"]                   ,
        POLARIZATION             = h5_parameters["POLARIZATION"]           ,
        DISTANCE                 = h5_parameters["DISTANCE"]               ,
        HSLITPOINTS              = h5_parameters["HSLITPOINTS"]            ,
        VSLITPOINTS              = h5_parameters["VSLITPOINTS"]            ,
        PHOTONENERGYMIN          = h5_parameters["PHOTONENERGYMIN"]        ,
        PHOTONENERGYMAX          = h5_parameters["PHOTONENERGYMAX"]        ,
        PHOTONENERGYPOINTS       = h5_parameters["PHOTONENERGYPOINTS"]     ,
        SHIFT_X_FLAG             = h5_parameters["SHIFT_X_FLAG"]           ,
        SHIFT_X_VALUE            = h5_parameters["SHIFT_X_VALUE"]          ,
        SHIFT_BETAX_FLAG         = h5_parameters["SHIFT_BETAX_FLAG"]       ,
        SHIFT_BETAX_VALUE        = h5_parameters["SHIFT_BETAX_VALUE"]      ,
        CONVOLUTION              = h5_parameters["CONVOLUTION"]            ,
        PASSEPARTOUT             = h5_parameters["PASSEPARTOUT"]            ,
        h5_file                  = "wiggler_radiation.h5"                  ,
        h5_entry_name            = "XOPPY_RADIATION"                       ,
        h5_initialize            = True                                    ,
        h5_parameters            = h5_parameters                           ,
        )

# example plot
from srxraylib.plot.gol import plot_image
plot_image(p[0],h,v,title="Flux [photons/s] per 0.1 bw per mm2 at %9.3f eV"%({PHOTONENERGYMIN}),xtitle="H [mm]",ytitle="V [mm]")
#
# end script
#
"""

    def extract_data_from_xoppy_output(self, calculation_output):
        e, h, v, p, traj = calculation_output

        calculated_data = DataExchangeObject(
            "XOPPY", self.get_data_exchange_widget_name())

        calculated_data.add_content("xoppy_data", [p, e, h, v])
        calculated_data.add_content("xoppy_trajectory", traj)
        calculated_data.add_content("xoppy_code", "srfunc")
        return calculated_data

    def get_data_exchange_widget_name(self):
        return "WIGGLER_RADIATION"

    def getTitles(self):
        return [
            'Wiggler Flux vs E,X,Y', 'Wiggler Power Density vs X,Y',
            'Wiggler Flux vs E', 'Wiggler Spectral Power vs E',
            'e- trajectory', 'e- velocity', 'Bz'
        ]

    def receive_syned_data(self, data):

        if isinstance(data, synedb.Beamline):
            if not data._light_source is None and isinstance(
                    data._light_source._magnetic_structure,
                    synedid.InsertionDevice):
                light_source = data._light_source

                self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV
                self.ELECTRONCURRENT = light_source._electron_beam._current

                self.FIELD = 0
                self.PERIODID = light_source._magnetic_structure._period_length
                self.NPERIODS = light_source._magnetic_structure._number_of_periods
                self.KV = light_source._magnetic_structure._K_vertical

                self.set_enabled(False)

            else:
                self.set_enabled(True)
                # raise ValueError("Syned data not correct")
        else:
            self.set_enabled(True)
            # raise ValueError("Syned data not correct")

    def set_enabled(self, value):

        if value == True:
            self.id_ELECTRONENERGY.setEnabled(True)
            self.id_ELECTRONCURRENT.setEnabled(True)
            self.id_PERIODID.setEnabled(True)
            self.id_NPERIODS.setEnabled(True)
            self.id_KV.setEnabled(True)
            self.id_FIELD.setEnabled(True)
        else:
            self.id_ELECTRONENERGY.setEnabled(False)
            self.id_ELECTRONCURRENT.setEnabled(False)
            self.id_PERIODID.setEnabled(False)
            self.id_NPERIODS.setEnabled(False)
            self.id_KV.setEnabled(False)
            self.id_FIELD.setEnabled(False)

    def calculateMagneticField(self):
        self.bm_magnetic_field = numpy.round(
            (1e9 / codata.c) * self.ELECTRONENERGY / self.bm_magnetic_radius,
            3)

    def calculateMagneticRadius(self):
        self.bm_magnetic_radius = numpy.round(
            numpy.abs((1e9 / codata.c) * self.ELECTRONENERGY /
                      self.bm_magnetic_field), 3)