示例#1
0
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")
示例#2
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()
示例#3
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)
示例#4
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"
        ]
示例#5
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