class OWSRWEllipticalMirror(OWSRWMirror):

    name = "Elliptical Mirror"
    description = "SRW: Elliptical Mirror"
    icon = "icons/ellipsoid_mirror.png"
    priority = 5

    distance_from_first_focus_to_mirror_center = Setting(1.0)
    distance_from_mirror_center_to_second_focus = Setting(1.0)

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

    def get_mirror_instance(self):
        return SRWEllipticalMirror(
            distance_from_first_focus_to_mirror_center=self.
            distance_from_first_focus_to_mirror_center,
            distance_from_mirror_center_to_second_focus=self.
            distance_from_mirror_center_to_second_focus)

    def draw_specific_box(self):
        super().draw_specific_box()

        oasysgui.lineEdit(self.mirror_box,
                          self,
                          "distance_from_first_focus_to_mirror_center",
                          "1st focus to mirror center distance (p) [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.mirror_box,
                          self,
                          "distance_from_mirror_center_to_second_focus",
                          "Mirror center to 2nd focus distance (q) [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

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

        p, q = optical_element._surface_shape.get_p_q(
            numpy.radians(90 - self.angle_radial))

        self.distance_from_first_focus_to_mirror_center = numpy.round(p, 6)
        self.distance_from_mirror_center_to_second_focus = numpy.round(q, 6)

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

        congruence.checkStrictlyPositiveNumber(
            self.distance_from_first_focus_to_mirror_center,
            "Distance from first focus to mirror center (p)")
        congruence.checkStrictlyPositiveNumber(
            self.distance_from_mirror_center_to_second_focus,
            "Distance from mirror center to second focus (q)")
class Graph(BaseGraph):
    show_x_axis = Setting(True)
    show_y_axis = Setting(True)
    a_list = Setting([])
    a_set = Setting({1, 2, 3})
    a_dict = Setting({1: 2, 3: 4})

    def __init__(self):
        super().__init__()
        initialize_settings(self)
Exemplo n.º 3
0
class SimpleWidget(QObject):
    settings_version = 1

    setting = Setting(42)
    schema_only_setting = Setting(None, schema_only=True)

    context_setting = ContextSetting(42)
    settingsAboutToBePacked = Signal()

    migrate_settings = Mock()
    migrate_context = Mock()
Exemplo n.º 4
0
class OpticalElementSpaceWidget(widget.OWWidget):
    name = "Drift space"
    description = "Drift space"
    icon = "icons/drift_space.svg"

    want_main_area = False

    inputs = [("Optical beam", OpticalBeam, "onOpticalBeam", widget.Multiple)]
    outputs = [("Optical beam", OpticalBeam)]

    value_le_length = Setting(1.0)

    value_le_driver_settings = Setting("")

    def __init__(self, parent=None, signalManager=None):
        widget.OWWidget.__init__(self, parent, signalManager)

        self.__optical_space = OpticalElement("driftspace")

        self.le_length = gui.lineEdit(self.controlArea,
                                      self,
                                      "value_le_length",
                                      label="Length [m]",
                                      validator=QDoubleValidator(bottom=0.0))

        self.__driver_settings_widget = DriverSettingsWidget(
            self.__optical_space, self, "value_le_driver_settings")

        self.__optical_space.setOnSynchronize(self.synchronizeToOpticalElement)
        self.__optical_space.setOnCalculationStart(self.calculationStart)
        self.__optical_space.setOnCalculationFinished(self.calculationFinished)

    def calculationStart(self):
        self.progressBarInit()
        self.progressBarSet(0)
        QApplication.processEvents()

    def calculationFinished(self):
        self.progressBarSet(100)
        QApplication.processEvents()

    def synchronizeToOpticalElement(self):
        length = float(self.value_le_length)
        beamline_component = DriftSpace(length)
        self.__optical_space.setBeamlineComponent(
            beamline_component=beamline_component)

    def onOpticalBeam(self, optical_beam, sender):
        optical_beam.sender().addOutput(self.__optical_space)

        sender = OpticalBeam(self.__optical_space)
        self.send("Optical beam", sender)
Exemplo n.º 5
0
class OWSRWToroidallMirror(OWSRWMirror):

    name = "Toroidal Mirror"
    description = "SRW: Toroidal Mirror"
    icon = "icons/toroidal_mirror.png"
    priority = 5

    tangential_radius = Setting(1.0)
    sagittal_radius = Setting(1.0)

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

    def get_mirror_instance(self):
        return SRWToroidalMirror(tangential_radius=self.tangential_radius,
                                 sagittal_radius=self.sagittal_radius)

    def draw_specific_box(self):
        super().draw_specific_box()

        oasysgui.lineEdit(self.mirror_box,
                          self,
                          "tangential_radius",
                          "Tangential Radius [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.mirror_box,
                          self,
                          "sagittal_radius",
                          "Sagittal Radius [m]",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

    def receive_shape_specific_syned_data(self, optical_element):
        if not isinstance(optical_element._surface_shape, Toroidal):
            raise Exception(
                "Syned Data not correct: Mirror Surface Shape is not Toroidal")

        self.tangential_radius = numpy.round(
            optical_element._surface_shape._maj_radius, 6)
        self.sagittal_radius = numpy.round(
            optical_element._surface_shape._min_radius, 6)

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

        congruence.checkStrictlyPositiveNumber(self.tangential_radius,
                                               "Tangential Radius")
        congruence.checkStrictlyPositiveNumber(self.sagittal_radius,
                                               "Sagittal Radius")
Exemplo n.º 6
0
class OWWidgetNumber(OWBaseWidget):
    name = "Number"
    description = "Lets the user input a number"
    icon = "icons/Unknown.svg"
    priority = 10
    category = ""

    class Outputs:
        number = Output("Number", int)

    want_main_area = False

    number = Setting(42)

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

        gui.lineEdit(self.controlArea, self, "number", "Enter a number",
                     box="Number",
                     callback=self.number_changed,
                     valueType=int, validator=QIntValidator())
        self.number_changed()

    def number_changed(self):
        self.Outputs.number.send(self.number)
Exemplo n.º 7
0
class AutomaticWidget(OWWidget):

    is_automatic_execution = Setting(True)

    CONTROL_AREA_WIDTH = 405

    MAX_WIDTH = 1320
    MAX_HEIGHT = 700

    def __init__(self, is_automatic=True):
        super().__init__()

        geom = QApplication.desktop().availableGeometry()
        self.setGeometry(
            QRect(round(geom.width() * 0.05), round(geom.height() * 0.05),
                  round(min(geom.width() * 0.98, self.MAX_WIDTH)),
                  round(min(geom.height() * 0.95, self.MAX_HEIGHT))))

        self.setMaximumHeight(self.geometry().height())
        self.setMaximumWidth(self.geometry().width())

        self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)

        if is_automatic:
            self.general_options_box = gui.widgetBox(self.controlArea,
                                                     "General Options",
                                                     addSpace=True,
                                                     orientation="horizontal")

            gui.checkBox(self.general_options_box, self,
                         'is_automatic_execution', 'Automatic Execution')
        else:
            self.is_automatic_execution = False
class ScanVariableLoopPoint(AbstractScanVariableLoopPoint):

    name = "Scanning Variable Loop Point"
    description = "Tools: LoopPoint"
    icon = "icons/cycle_variable.png"
    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    priority = 1
    category = "User Defined"
    keywords = ["data", "file", "load", "read"]

    variable_name_id = Setting(11)

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

    def has_variable_list(self): return True

    def create_variable_list_box(self, box):
        gui.comboBox(box, self, "variable_name_id", label="Variable Name", labelWidth=120,
                     items=VARIABLES[:, 1],
                     callback=self.set_VariableName, sendSelectedValue=False, orientation="horizontal")

    def set_VariableName(self):
        self.variable_name = VARIABLES[self.variable_name_id, 0]
        self.variable_display_name = VARIABLES[self.variable_name_id, 1]
        self.variable_um = VARIABLES[self.variable_name_id, 2]
        self.variable_um = self.workspace_units_label if self.variable_um == "l" else self.variable_um
Exemplo n.º 9
0
class SimpleWidget(QObject):
    settings_version = 1

    setting = Setting(42)
    schema_only_setting = Setting(None, schema_only=True)
    list_setting = Setting([])
    non_setting = 5

    component = SettingProvider(Component)
    settingsAboutToBePacked = Signal()

    def __init__(self):
        super().__init__()
        self.component = Component()

    migrate_settings = Mock()
    migrate_context = Mock()
Exemplo n.º 10
0
class OWDecreasePoints(OWGenericDiffractionPatternParametersWidget):

    name = "Decrease Number of Points"
    description = "Decrease Number of Points"
    icon = "icons/decrease.png"
    priority = 1000
    
    reduction_factor = Setting([1])
    
    def get_max_height(self):
        return 310

    def get_parameter_name(self):
        return "Reduction Factor"

    def get_current_dimension(self):
        return len(self.reduction_factor)

    def get_parameter_box_instance(self, parameter_tab, index):
        return DecreasePointsBox(widget=self,
                                     parent=parameter_tab,
                                     index=index,
                                     reduction_factor=self.reduction_factor[index])

    def get_empty_parameter_box_instance(self, parameter_tab, index):
        return DecreasePointsBox(widget=self, parent=parameter_tab, index=index)

    def set_data(self, data):
        try:
            if not data is None: self.input_diffraction_patterns = data.measured_dataset.duplicate_diffraction_patterns()

            super().set_data(data)
        except Exception as e:
            QMessageBox.critical(self, "Error",
                                 str(e),
                                 QMessageBox.Ok)

            if self.IS_DEVELOP: raise e

    def set_parameter_data(self):
        for diffraction_pattern_index in range(self.fit_global_parameters.measured_dataset.get_diffraction_patterns_number()):
            reduction_factor = self.get_parameter_box(diffraction_pattern_index).get_reduction_factor()
            if reduction_factor > 1:
                self.fit_global_parameters.measured_dataset.diffraction_patterns[diffraction_pattern_index].diffraction_pattern = \
                    self.input_diffraction_patterns[diffraction_pattern_index].diffraction_pattern[::reduction_factor]

    def get_parameter_array(self):
        return self.fit_global_parameters.measured_dataset.diffraction_patterns

    def get_parameter_item(self, diffraction_pattern_index):
        return self.fit_global_parameters.measured_dataset.diffraction_patterns[diffraction_pattern_index]

    def dumpSettings(self):
        self.dump_reduction_factor()

    def dump_reduction_factor(self): self.dump_variable("reduction_factor")
class BaseWidget:
    settingsHandler = None

    show_graph = Setting(True)

    graph = SettingProvider(Graph)

    def __init__(self):
        initialize_settings(self)
        self.graph = Graph()
class Widget(BaseWidget):
    show_zoom_toolbar = Setting(True)

    zoom_toolbar = SettingProvider(ZoomToolbar)

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

        self.zoom_toolbar = ZoomToolbar()
Exemplo n.º 13
0
class OWPlotSimple(widget.OWWidget):
    name = "Plot Simple"
    id = "OWPlotSimple"
    description = ""
    icon = "icons/plot_simple.png"
    author = ""
    maintainer_email = ""
    priority = 1
    category = ""
    keywords = ["list", "of", "keywords"]
    inputs = [{"name": "oasysaddontemplate-data",
                "type": np.ndarray,
                "doc": "",
                "handler": "do_plot" },
                ]


    input_field = Setting(10.0)

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

        box = oasysgui.widgetBox(self.controlArea, "Input Form", orientation="vertical")

        oasysgui.lineEdit(box, self, "input_field", "Example Input field", valueType=float)
        gui.button(box, self, "Do Plot", callback=self.button_action)


        self.figure_canvas = None

    def do_plot(self, custom_data):
        x = custom_data[0,:]
        y = custom_data[-1,:]
        x.shape = -1
        y.shape = -1
        fig = plt.figure()
        plt.plot(x,y,linewidth=1.0, figure=fig)
        plt.grid(True)

        if self.figure_canvas is not None:
            self.mainArea.layout().removeWidget(self.figure_canvas)

        self.figure_canvas = FigureCanvas(fig)

        self.mainArea.layout().addWidget(self.figure_canvas)

        gui.rubber(self.mainArea)

    def button_action(self):
        a = np.array([
            [  8.47091837e+04,  8.57285714e+04,   8.67479592e+04, 8.77673469e+04,] ,
            [  self.input_field,  self.input_field,   self.input_field, self.input_field]
            ])

        self.do_plot(a)
Exemplo n.º 14
0
class MyWidget(OWBaseWidget):
    name = "Dummy"

    field = Setting(42)
    component = SettingProvider(DummyComponent)

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

        self.component = DummyComponent(self)
        self.widget = None
class OWPlaneMirror(OWOpticalElement, WidgetDecorator):
    name = "PlaneMirror"
    id = "PlaneMirror"
    description = "Plane Mirror"
    icon = "icons/plane_mirror.png"
    priority = 1

    OWOpticalElement.WhatWhereReferTo = Setting(
        PositioningDirectivesPhrases.Type.DistanceFromSource)

    oe_name = Setting("Plane mirror")

    def after_change_workspace_units(self):
        super(OWPlaneMirror, self).after_change_workspace_units()

    def build_mirror_specific_gui(self, container_box):
        pass

    def get_native_optical_element(self):
        return Optics.MirrorPlane(L=self.length,
                                  AngleGrazing=numpy.deg2rad(self.alpha))

    def get_optical_element(self, native_optical_element):
        return WiserOpticalElement(
            name=self.oe_name,
            boundary_shape=None,
            native_CoreOptics=native_optical_element,
            native_PositioningDirectives=self.get_PositionDirectives())

    def receive_specific_syned_data(self, optical_element):
        pass

    def check_syned_shape(self, optical_element):
        if not isinstance(optical_element._surface_shape, Plane):
            raise Exception(
                "Syned Data not correct: Mirror Surface Shape is not Elliptical"
            )
Exemplo n.º 16
0
class SRWWidget(widget.OWWidget):

    want_main_area = 1

    is_automatic_run = Setting(True)

    error_id = 0
    warning_id = 0
    info_id = 0

    MAX_WIDTH = 1320
    MAX_HEIGHT = 700

    CONTROL_AREA_WIDTH = 405
    TABS_AREA_HEIGHT = 560

    srw_live_propagation_mode = "Unknown"

    def __init__(self, show_general_option_box=True, show_automatic_box=True):
        super().__init__()

        geom = QApplication.desktop().availableGeometry()
        self.setGeometry(
            QRect(round(geom.width() * 0.05), round(geom.height() * 0.05),
                  round(min(geom.width() * 0.98, self.MAX_WIDTH)),
                  round(min(geom.height() * 0.95, self.MAX_HEIGHT))))

        self.setMaximumHeight(self.geometry().height())
        self.setMaximumWidth(self.geometry().width())

        self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)

        self.general_options_box = gui.widgetBox(self.controlArea,
                                                 "General Options",
                                                 addSpace=True,
                                                 orientation="horizontal")
        self.general_options_box.setVisible(show_general_option_box)

        if show_automatic_box:
            gui.checkBox(self.general_options_box, self, 'is_automatic_run',
                         'Automatic Execution')

    def callResetSettings(self):
        if ConfirmDialog.confirmed(parent=self,
                                   message="Confirm Reset of the Fields?"):
            try:
                self.resetSettings()
            except:
                pass
Exemplo n.º 17
0
class OWSlits(OWOpticalElement, WidgetDecorator):
    name = "Slits"
    id = "Slits"
    description = "Slits"
    icon = "icons/slit.png"
    priority = 1

    length = Setting(0.01)
    alpha = Setting(90.0)

    oe_name = Setting("Slit")

    def after_change_workspace_units(self):
        super(OWSlits, self).after_change_workspace_units()

    def build_mirror_specific_gui(self, container_box):
        pass

    def get_native_optical_element(self):
        return Optics.Slits(L=self.length)

    def get_optical_element(self, native_optical_element):
        return WiserOpticalElement(
            name=self.oe_name,
            boundary_shape=None,
            native_CoreOptics=native_optical_element,
            native_PositioningDirectives=self.get_PositionDirectives())

    def receive_specific_syned_data(self, optical_element):
        pass

    def check_syned_shape(self, optical_element):
        if not isinstance(optical_element._surface_shape, Plane):
            raise Exception(
                "Syned Data not correct: Mirror Surface Shape is not Elliptical"
            )
Exemplo n.º 18
0
class OWMultiplier(widget.OWBaseWidget):
    name = "Multiplier"
    description = ""
    icon = "icons/Unknown.svg"
    priority = 10
    category = ""
    keywords = ["list", "of", "keywords"]
    outputs = [("Product", int)]
    inputs = [("A number", int, "get_a_number")]

    want_main_area = False

    factor = Setting(True)

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

        self.n = None
        self.product = 0

        gui.radioButtonsInBox(self.controlArea, self, "factor",
            ("None", "Double", "Triple", "Quadruple"),
            box="Multiply", callback=self.do_multiply)

        self.result = gui.label(self.controlArea, self,
                                "The product is %(product)i",
                                box="Result")
        self.result.hide()

        gui.rubber(self.controlArea)

    def get_a_number(self, n):
        self.n = n
        self.do_multiply()

    def do_multiply(self):
        if self.n is None:
            self.result.hide()
            self.send("Product", None)
        else:
            self.result.show()
            self.product = self.n * (self.factor + 1)
            self.send("Product", self.product)
Exemplo n.º 19
0
class OWWidgetName(widget.OWBaseWidget):
    name = "Widget Name"
    id = "orangewidget.widget_category.widget_name"
    description = ""
    icon = "icons/Unknown.svg"
    priority = 10
    category = ""
    keywords = ["list", "of", "keywords"]
    want_main_area = False
    outputs = [("Name", type)]
    inputs = [("Name", type, "handler")]

    foo = Setting(True)

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

        # controls
        gui.rubber(self.controlArea)
Exemplo n.º 20
0
class Histogram(ow_automatic_element.AutomaticElement):

    name = "Scanning Variable Histogram"
    description = "Display Data Tools: Histogram"
    icon = "icons/histogram.png"
    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    priority = 7
    category = "Display Data Tools"
    keywords = ["data", "file", "load", "read"]

    inputs = [("Input Beam", ShadowBeam, "setBeam")]

    IMAGE_WIDTH = 878
    IMAGE_HEIGHT = 635

    want_main_area = 1
    plot_canvas = None
    plot_scan_canvas = None

    input_beam = None

    image_plane = Setting(0)
    image_plane_new_position = Setting(10.0)
    image_plane_rel_abs_position = Setting(0)

    x_column_index = Setting(10)

    x_range = Setting(0)
    x_range_min = Setting(0.0)
    x_range_max = Setting(0.0)

    weight_column_index = Setting(23)
    rays = Setting(1)

    number_of_bins = Setting(100)

    title = Setting("Energy")

    iterative_mode = Setting(0)

    last_ticket = None

    is_conversion_active = Setting(1)

    current_histo_data = None
    current_stats = None
    last_histo_data = None
    histo_index = -1

    plot_type = Setting(1)
    add_labels = Setting(0)
    has_colormap = Setting(1)
    plot_type_3D = Setting(0)
    sigma_fwhm_size = Setting(0)
    peak_integral_intensity = Setting(0)
    absolute_relative_intensity = Setting(0)

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

        self.refresh_button = gui.button(self.controlArea,
                                         self,
                                         "Refresh",
                                         callback=self.plot_results,
                                         height=45)
        gui.separator(self.controlArea, 10)

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

        # graph tab
        tab_set = oasysgui.createTabPage(self.tabs_setting, "Plot Settings")
        tab_gen = oasysgui.createTabPage(self.tabs_setting,
                                         "Histogram Settings")

        screen_box = oasysgui.widgetBox(tab_set,
                                        "Screen Position Settings",
                                        addSpace=True,
                                        orientation="vertical",
                                        height=120)

        self.image_plane_combo = gui.comboBox(
            screen_box,
            self,
            "image_plane",
            label="Position of the Image",
            items=["On Image Plane", "Retraced"],
            labelWidth=260,
            callback=self.set_ImagePlane,
            sendSelectedValue=False,
            orientation="horizontal")

        self.image_plane_box = oasysgui.widgetBox(screen_box,
                                                  "",
                                                  addSpace=False,
                                                  orientation="vertical",
                                                  height=50)
        self.image_plane_box_empty = oasysgui.widgetBox(screen_box,
                                                        "",
                                                        addSpace=False,
                                                        orientation="vertical",
                                                        height=50)

        oasysgui.lineEdit(self.image_plane_box,
                          self,
                          "image_plane_new_position",
                          "Image Plane new Position",
                          labelWidth=220,
                          valueType=float,
                          orientation="horizontal")

        gui.comboBox(self.image_plane_box,
                     self,
                     "image_plane_rel_abs_position",
                     label="Position Type",
                     labelWidth=250,
                     items=["Absolute", "Relative"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.set_ImagePlane()

        general_box = oasysgui.widgetBox(tab_set,
                                         "General Settings",
                                         addSpace=True,
                                         orientation="vertical",
                                         height=250)

        self.x_column = gui.comboBox(
            general_box,
            self,
            "x_column_index",
            label="Column",
            labelWidth=70,
            items=[
                "1: X",
                "2: Y",
                "3: Z",
                "4: X'",
                "5: Y'",
                "6: Z'",
                "7: E\u03c3 X",
                "8: E\u03c3 Y",
                "9: E\u03c3 Z",
                "10: Ray Flag",
                "11: Energy",
                "12: Ray Index",
                "13: Optical Path",
                "14: Phase \u03c3",
                "15: Phase \u03c0",
                "16: E\u03c0 X",
                "17: E\u03c0 Y",
                "18: E\u03c0 Z",
                "19: Wavelength",
                "20: R = sqrt(X\u00b2 + Y\u00b2 + Z\u00b2)",
                "21: Theta (angle from Y axis)",
                "22: Magnitude = |E\u03c3| + |E\u03c0|",
                "23: Total Intensity = |E\u03c3|\u00b2 + |E\u03c0|\u00b2",
                "24: \u03a3 Intensity = |E\u03c3|\u00b2",
                "25: \u03a0 Intensity = |E\u03c0|\u00b2",
                "26: |K|",
                "27: K X",
                "28: K Y",
                "29: K Z",
                "30: S0-stokes = |E\u03c0|\u00b2 + |E\u03c3|\u00b2",
                "31: S1-stokes = |E\u03c0|\u00b2 - |E\u03c3|\u00b2",
                "32: S2-stokes = 2|E\u03c3||E\u03c0|cos(Phase \u03c3-Phase \u03c0)",
                "33: S3-stokes = 2|E\u03c3||E\u03c0|sin(Phase \u03c3-Phase \u03c0)",
                "34: Power = Intensity * Energy",
            ],
            sendSelectedValue=False,
            orientation="horizontal")

        gui.comboBox(general_box,
                     self,
                     "x_range",
                     label="X Range",
                     labelWidth=250,
                     items=["<Default>", "Set.."],
                     callback=self.set_XRange,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.xrange_box = oasysgui.widgetBox(general_box,
                                             "",
                                             addSpace=True,
                                             orientation="vertical",
                                             height=100)
        self.xrange_box_empty = oasysgui.widgetBox(general_box,
                                                   "",
                                                   addSpace=True,
                                                   orientation="vertical",
                                                   height=100)

        oasysgui.lineEdit(self.xrange_box,
                          self,
                          "x_range_min",
                          "X min",
                          labelWidth=220,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.xrange_box,
                          self,
                          "x_range_max",
                          "X max",
                          labelWidth=220,
                          valueType=float,
                          orientation="horizontal")

        self.set_XRange()

        self.weight_column = gui.comboBox(
            general_box,
            self,
            "weight_column_index",
            label="Weight",
            labelWidth=70,
            items=[
                "0: No Weight",
                "1: X",
                "2: Y",
                "3: Z",
                "4: X'",
                "5: Y'",
                "6: Z'",
                "7: E\u03c3 X",
                "8: E\u03c3 Y",
                "9: E\u03c3 Z",
                "10: Ray Flag",
                "11: Energy",
                "12: Ray Index",
                "13: Optical Path",
                "14: Phase \u03c3",
                "15: Phase \u03c0",
                "16: E\u03c0 X",
                "17: E\u03c0 Y",
                "18: E\u03c0 Z",
                "19: Wavelength",
                "20: R = sqrt(X\u00b2 + Y\u00b2 + Z\u00b2)",
                "21: Theta (angle from Y axis)",
                "22: Magnitude = |E\u03c3| + |E\u03c0|",
                "23: Total Intensity = |E\u03c3|\u00b2 + |E\u03c0|\u00b2",
                "24: \u03a3 Intensity = |E\u03c3|\u00b2",
                "25: \u03a0 Intensity = |E\u03c0|\u00b2",
                "26: |K|",
                "27: K X",
                "28: K Y",
                "29: K Z",
                "30: S0-stokes = |E\u03c0|\u00b2 + |E\u03c3|\u00b2",
                "31: S1-stokes = |E\u03c0|\u00b2 - |E\u03c3|\u00b2",
                "32: S2-stokes = 2|E\u03c3||E\u03c0|cos(Phase \u03c3-Phase \u03c0)",
                "33: S3-stokes = 2|E\u03c3||E\u03c0|sin(Phase \u03c3-Phase \u03c0)",
                "34: Power = Intensity * Energy",
            ],
            sendSelectedValue=False,
            orientation="horizontal")

        gui.comboBox(general_box,
                     self,
                     "rays",
                     label="Rays",
                     labelWidth=250,
                     items=["All rays", "Good Only", "Lost Only"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        incremental_box = oasysgui.widgetBox(tab_gen,
                                             "Incremental Result",
                                             addSpace=True,
                                             orientation="vertical",
                                             height=320)

        gui.button(incremental_box,
                   self,
                   "Clear Stored Data",
                   callback=self.clearResults,
                   height=30)
        gui.separator(incremental_box)

        gui.comboBox(incremental_box,
                     self,
                     "iterative_mode",
                     label="Iterative Mode",
                     labelWidth=250,
                     items=["None", "Accumulating", "Scanning"],
                     sendSelectedValue=False,
                     orientation="horizontal",
                     callback=self.set_IterativeMode)

        self.box_scan_empty = oasysgui.widgetBox(incremental_box,
                                                 "",
                                                 addSpace=False,
                                                 orientation="vertical")
        self.box_scan = oasysgui.widgetBox(incremental_box,
                                           "",
                                           addSpace=False,
                                           orientation="vertical")

        gui.comboBox(self.box_scan,
                     self,
                     "plot_type",
                     label="Plot Type",
                     labelWidth=310,
                     items=["2D", "3D"],
                     sendSelectedValue=False,
                     orientation="horizontal",
                     callback=self.set_PlotType)

        self.box_pt_1 = oasysgui.widgetBox(self.box_scan,
                                           "",
                                           addSpace=False,
                                           orientation="vertical",
                                           height=25)

        gui.comboBox(self.box_pt_1,
                     self,
                     "add_labels",
                     label="Add Labels (Variable Name/Value)",
                     labelWidth=310,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.box_pt_2 = oasysgui.widgetBox(self.box_scan,
                                           "",
                                           addSpace=False,
                                           orientation="vertical",
                                           height=25)

        gui.comboBox(self.box_pt_2,
                     self,
                     "plot_type_3D",
                     label="3D Plot Aspect",
                     labelWidth=310,
                     items=["Lines", "Surface"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.comboBox(self.box_scan,
                     self,
                     "has_colormap",
                     label="Colormap",
                     labelWidth=310,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.separator(self.box_scan)

        gui.comboBox(self.box_scan,
                     self,
                     "sigma_fwhm_size",
                     label="Stats: Spot Dimension",
                     labelWidth=310,
                     items=["Sigma", "FWHM"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.comboBox(self.box_scan,
                     self,
                     "peak_integral_intensity",
                     label="Stats: Intensity (1)",
                     labelWidth=310,
                     items=["Peak", "Integral"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.comboBox(self.box_scan,
                     self,
                     "absolute_relative_intensity",
                     label="Stats: Intensity (2)",
                     labelWidth=310,
                     items=["Relative", "Absolute"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.button(self.box_scan,
                   self,
                   "Export Scanning Results/Stats",
                   callback=self.export_scanning_stats_analysis,
                   height=30)

        self.set_IterativeMode()

        histograms_box = oasysgui.widgetBox(tab_gen,
                                            "Histograms settings",
                                            addSpace=True,
                                            orientation="vertical",
                                            height=90)

        oasysgui.lineEdit(histograms_box,
                          self,
                          "number_of_bins",
                          "Number of Bins",
                          labelWidth=250,
                          valueType=int,
                          orientation="horizontal")

        gui.comboBox(histograms_box,
                     self,
                     "is_conversion_active",
                     label="Is U.M. conversion active",
                     labelWidth=250,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.main_tabs = oasysgui.tabWidget(self.mainArea)
        plot_tab = oasysgui.createTabPage(self.main_tabs, "Plots")
        plot_tab_stats = oasysgui.createTabPage(self.main_tabs, "Stats")
        out_tab = oasysgui.createTabPage(self.main_tabs, "Output")

        self.image_box = gui.widgetBox(plot_tab,
                                       "Plot Result",
                                       addSpace=True,
                                       orientation="vertical")
        self.image_box.setFixedHeight(self.IMAGE_HEIGHT)
        self.image_box.setFixedWidth(self.IMAGE_WIDTH)

        self.image_box_stats = gui.widgetBox(plot_tab_stats,
                                             "Stats Result",
                                             addSpace=True,
                                             orientation="vertical")
        self.image_box_stats.setFixedHeight(self.IMAGE_HEIGHT)
        self.image_box_stats.setFixedWidth(self.IMAGE_WIDTH)

        self.shadow_output = oasysgui.textArea(height=580, width=800)

        out_box = gui.widgetBox(out_tab,
                                "System Output",
                                addSpace=True,
                                orientation="horizontal")
        out_box.layout().addWidget(self.shadow_output)

    def clearResults(self, interactive=True):
        if not interactive: proceed = True
        else: proceed = ConfirmDialog.confirmed(parent=self)

        if proceed:
            self.clear_data()

    def clear_data(self):
        self.input_beam = None
        self.last_ticket = None
        self.current_stats = None
        self.current_histo_data = None
        self.last_histo_data = None

        self.histo_index = -1

        if not self.plot_canvas is None:
            self.main_tabs.removeTab(1)
            self.main_tabs.removeTab(0)

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

            self.image_box = gui.widgetBox(plot_tab,
                                           "Plot Result",
                                           addSpace=True,
                                           orientation="vertical")
            self.image_box.setFixedHeight(self.IMAGE_HEIGHT)
            self.image_box.setFixedWidth(self.IMAGE_WIDTH)

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

            self.image_box_stats = gui.widgetBox(plot_tab_stats,
                                                 "Stats Result",
                                                 addSpace=True,
                                                 orientation="vertical")
            self.image_box_stats.setFixedHeight(self.IMAGE_HEIGHT)
            self.image_box_stats.setFixedWidth(self.IMAGE_WIDTH)

            self.main_tabs.insertTab(0, plot_tab_stats, "TEMP")
            self.main_tabs.setTabText(0, "Stats")
            self.main_tabs.insertTab(0, plot_tab, "TEMP")
            self.main_tabs.setTabText(0, "Plots")
            self.main_tabs.setCurrentIndex(0)

            self.plot_canvas = None
            self.plot_canvas_stats = None

    def set_IterativeMode(self):
        self.box_scan_empty.setVisible(self.iterative_mode < 2)
        if self.iterative_mode == 2:
            self.box_scan.setVisible(True)
            self.refresh_button.setEnabled(False)
            self.set_PlotType()
        else:
            self.box_scan.setVisible(False)
            self.refresh_button.setEnabled(True)

        self.clear_data()

    def set_PlotType(self):
        self.plot_canvas = None
        self.plot_canvas_stats = None

        self.box_pt_1.setVisible(self.plot_type == 0)
        self.box_pt_2.setVisible(self.plot_type == 1)

    def set_XRange(self):
        self.xrange_box.setVisible(self.x_range == 1)
        self.xrange_box_empty.setVisible(self.x_range == 0)

    def set_ImagePlane(self):
        self.image_plane_box.setVisible(self.image_plane == 1)
        self.image_plane_box_empty.setVisible(self.image_plane == 0)

    def replace_fig(self, beam, var, xrange, title, xtitle, ytitle, xum):
        if self.plot_canvas is None:
            if self.iterative_mode < 2:
                self.plot_canvas = ShadowPlot.DetailedHistoWidget(
                    y_scale_factor=1.14)
            else:
                if self.plot_type == 0:
                    self.plot_canvas = ScanHistoWidget(
                        self.workspace_units_to_cm)
                elif self.plot_type == 1:
                    self.plot_canvas = Scan3DHistoWidget(
                        self.workspace_units_to_cm,
                        type=Scan3DHistoWidget.PlotType.LINES
                        if self.plot_type_3D == 0 else
                        Scan3DHistoWidget.PlotType.SURFACE)

                self.plot_canvas_stats = DoublePlotWidget(parent=None)
                self.image_box_stats.layout().addWidget(self.plot_canvas_stats)

            self.image_box.layout().addWidget(self.plot_canvas)

        if self.iterative_mode == 0:
            self.last_ticket = None
            self.current_histo_data = None
            self.current_stats = None
            self.last_histo_data = None
            self.histo_index = -1
            self.plot_canvas.plot_histo(beam._beam,
                                        var,
                                        self.rays,
                                        xrange,
                                        self.weight_column_index,
                                        title,
                                        xtitle,
                                        ytitle,
                                        nbins=self.number_of_bins,
                                        xum=xum,
                                        conv=self.workspace_units_to_cm)

        elif self.iterative_mode == 1:
            self.current_histo_data = None
            self.current_stats = None
            self.last_histo_data = None
            self.histo_index = -1
            self.last_ticket = self.plot_canvas.plot_histo(
                beam._beam,
                var,
                self.rays,
                xrange,
                self.weight_column_index,
                title,
                xtitle,
                ytitle,
                nbins=self.number_of_bins,
                xum=xum,
                conv=self.workspace_units_to_cm,
                ticket_to_add=self.last_ticket)
        else:
            if not beam.scanned_variable_data is None:
                self.last_ticket = None
                self.histo_index += 1

                um = beam.scanned_variable_data.get_scanned_variable_um()
                um = " " + um if um.strip() == "" else " [" + um + "]"

                histo_data = self.plot_canvas.plot_histo(
                    beam=beam,
                    col=var,
                    nbins=self.number_of_bins,
                    title=title,
                    xtitle=xtitle,
                    ytitle=ytitle,
                    histo_index=self.histo_index,
                    scan_variable_name=beam.scanned_variable_data.
                    get_scanned_variable_display_name() + um,
                    scan_variable_value=beam.scanned_variable_data.
                    get_scanned_variable_value(),
                    offset=0.0 if self.last_histo_data is None else
                    self.last_histo_data.offset,
                    xrange=xrange,
                    show_reference=False,
                    add_labels=self.add_labels == 1,
                    has_colormap=self.has_colormap == 1)
                scanned_variable_value = beam.scanned_variable_data.get_scanned_variable_value(
                )

                if isinstance(scanned_variable_value, str):
                    histo_data.scan_value = self.histo_index + 1
                else:
                    histo_data.scan_value = beam.scanned_variable_data.get_scanned_variable_value(
                    )

                if not histo_data.bins is None:
                    if self.current_histo_data is None:
                        self.current_histo_data = HistogramDataCollection(
                            histo_data)
                    else:
                        self.current_histo_data.add_histogram_data(histo_data)

                if self.current_stats is None:
                    self.current_stats = StatisticalDataCollection(histo_data)
                else:
                    self.current_stats.add_statistical_data(histo_data)

                self.last_histo_data = histo_data

                if self.sigma_fwhm_size == 0:
                    sizes = self.current_stats.get_sigmas()
                    label_size = "Sigma " + xum
                else:
                    sizes = self.current_stats.get_fwhms()
                    label_size = "FWHM " + xum

                if self.absolute_relative_intensity == 0:  #relative
                    if self.peak_integral_intensity == 0:  # peak
                        intensities = self.current_stats.get_relative_peak_intensities(
                        )
                        label_intensity = "Relative Peak Intensity"
                    else:
                        intensities = self.current_stats.get_relative_integral_intensities(
                        )
                        label_intensity = "Relative Integral Intensity"
                else:
                    if self.peak_integral_intensity == 0:  # peak
                        intensities = self.current_stats.get_absolute_peak_intensities(
                        )
                        label_intensity = "Absolute Peak Intensity"
                    else:
                        intensities = self.current_stats.get_absolute_integral_intensities(
                        )
                        label_intensity = "Absolute Integral Intensity"

                self.plot_canvas_stats.plotCurves(
                    self.current_stats.get_scan_values(), sizes, intensities,
                    "Statistics",
                    beam.scanned_variable_data.
                    get_scanned_variable_display_name() + um, label_size,
                    label_intensity)

    def plot_histo(self, var_x, title, xtitle, ytitle, xum):
        beam_to_plot = self.input_beam

        if self.image_plane == 1:
            new_shadow_beam = self.input_beam.duplicate(history=False)
            dist = 0.0

            if self.image_plane_rel_abs_position == 1:  # relative
                dist = self.image_plane_new_position
            else:  # absolute
                if self.input_beam.historySize() == 0:
                    historyItem = None
                else:
                    historyItem = self.input_beam.getOEHistory(
                        oe_number=self.input_beam._oe_number)

                if historyItem is None: image_plane = 0.0
                elif self.input_beam._oe_number == 0: image_plane = 0.0
                else: image_plane = historyItem._shadow_oe_end._oe.T_IMAGE

                dist = self.image_plane_new_position - image_plane

            self.retrace_beam(new_shadow_beam, dist)

            beam_to_plot = new_shadow_beam

        xrange = self.get_range(beam_to_plot._beam, var_x)

        self.replace_fig(beam_to_plot, var_x, xrange, title, xtitle, ytitle,
                         xum)

    def get_range(self, beam_to_plot, var_x):
        if self.x_range == 0:
            x_max = 0
            x_min = 0

            x, good_only = beam_to_plot.getshcol((var_x, 10))

            x_to_plot = copy.deepcopy(x)

            go = numpy.where(good_only == 1)
            lo = numpy.where(good_only != 1)

            if self.rays == 0:
                x_max = numpy.array(x_to_plot[0:], float).max()
                x_min = numpy.array(x_to_plot[0:], float).min()
            elif self.rays == 1:
                x_max = numpy.array(x_to_plot[go], float).max()
                x_min = numpy.array(x_to_plot[go], float).min()
            elif self.rays == 2:
                x_max = numpy.array(x_to_plot[lo], float).max()
                x_min = numpy.array(x_to_plot[lo], float).min()

            xrange = [x_min, x_max]
        else:
            congruence.checkLessThan(self.x_range_min, self.x_range_max,
                                     "X range min", "X range max")

            factor1 = ShadowPlot.get_factor(var_x, self.workspace_units_to_cm)

            xrange = [self.x_range_min / factor1, self.x_range_max / factor1]

        return xrange

    def plot_results(self):
        try:
            plotted = False

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            if self.trace_shadow:
                grabber = TTYGrabber()
                grabber.start()

            if ShadowCongruence.checkEmptyBeam(self.input_beam):
                ShadowPlot.set_conversion_active(self.getConversionActive())

                self.number_of_bins = congruence.checkPositiveNumber(
                    self.number_of_bins, "Number of Bins")

                x, auto_title, xum = self.get_titles()

                self.plot_histo(x,
                                title=self.title,
                                xtitle=auto_title,
                                ytitle="Number of Rays",
                                xum=xum)

                plotted = True
            if self.trace_shadow:
                grabber.stop()

                for row in grabber.ttyData:
                    self.writeStdOut(row)

            time.sleep(
                0.5
            )  # prevents a misterious dead lock in the Orange cycle when refreshing the histogram

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

            if self.IS_DEVELOP: raise exception

            return False

    def get_titles(self):
        auto_title = self.x_column.currentText().split(":", 2)[1]

        xum = auto_title + " "
        self.title = auto_title
        x = self.x_column_index + 1

        if x == 1 or x == 2 or x == 3:
            if self.getConversionActive():
                xum = xum + "[" + u"\u03BC" + "m]"
                auto_title = auto_title + " [$\mu$m]"
            else:
                xum = xum + " [" + self.workspace_units_label + "]"
                auto_title = auto_title + " [" + self.workspace_units_label + "]"
        elif x == 4 or x == 5 or x == 6:
            if self.getConversionActive():
                xum = xum + "[" + u"\u03BC" + "rad]"
                auto_title = auto_title + " [$\mu$rad]"
            else:
                xum = xum + " [rad]"
                auto_title = auto_title + " [rad]"
        elif x == 11:
            xum = xum + "[eV]"
            auto_title = auto_title + " [eV]"
        elif x == 13:
            xum = xum + " [" + self.workspace_units_label + "]"
            auto_title = auto_title + " [" + self.workspace_units_label + "]"
        elif x == 14:
            xum = xum + "[rad]"
            auto_title = auto_title + " [rad]"
        elif x == 15:
            xum = xum + "[rad]"
            auto_title = auto_title + " [rad]"
        elif x == 19:
            xum = xum + "[Å]"
            auto_title = auto_title + " [Å]"
        elif x == 20:
            xum = xum + " [" + self.workspace_units_label + "]"
            auto_title = auto_title + " [" + self.workspace_units_label + "]"
        elif x == 21:
            xum = xum + "[rad]"
            auto_title = auto_title + " [rad]"
        elif x >= 25 and x <= 28:
            xum = xum + "[Å-1]"
            auto_title = auto_title + " [Å-1]"

        return x, auto_title, xum

    def setBeam(self, beam):
        if ShadowCongruence.checkEmptyBeam(beam):
            if ShadowCongruence.checkGoodBeam(beam):
                self.input_beam = beam

                if self.is_automatic_run:
                    self.plot_results()
            else:
                QMessageBox.critical(
                    self, "Error",
                    "Data not displayable: No good rays or bad content",
                    QMessageBox.Ok)

    def writeStdOut(self, text):
        cursor = self.shadow_output.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.shadow_output.setTextCursor(cursor)
        self.shadow_output.ensureCursorVisible()

    def retrace_beam(self, new_shadow_beam, dist):
        new_shadow_beam._beam.retrace(dist)

    def getConversionActive(self):
        return self.is_conversion_active == 1

    def export_scanning_stats_analysis(self):
        output_folder = QFileDialog.getExistingDirectory(
            self, "Select Output Directory", directory=os.curdir)

        if output_folder:
            if not self.current_histo_data is None:
                items = ("Hdf5 only", "Text only", "Hdf5 and Text")

                item, ok = QInputDialog.getItem(self, "Select Output Format",
                                                "Formats: ", items, 2, False)

                if ok and item:
                    if item == "Hdf5 only" or item == "Hdf5 and Text":
                        write_histo_and_stats_file_hdf5(
                            histo_data=self.current_histo_data,
                            stats=self.current_stats,
                            suffix="",
                            output_folder=output_folder)
                    if item == "Text only" or item == "Hdf5 and Text":
                        write_histo_and_stats_file(
                            histo_data=self.current_histo_data,
                            stats=self.current_stats,
                            suffix="",
                            output_folder=output_folder)

                    QMessageBox.information(
                        self, "Export Scanning Results & Stats",
                        "Data saved into directory: " + output_folder,
                        QMessageBox.Ok)
Exemplo n.º 21
0
class OWxfh(XoppyWidget):
    name = "Fh"
    id = "orange.widgets.dataxfh"
    description = "Crystal Structure Factors"
    icon = "icons/xoppy_xfh.png"
    priority = 17
    category = ""
    keywords = ["xoppy", "xfh"]

    ILATTICE = Setting(32)
    HMILLER = Setting(1)
    KMILLER = Setting(1)
    LMILLER = Setting(1)
    plot_variable = Setting(0)
    I_PLOT = Setting(2)
    TEMPER = Setting(1.0)
    ENERGY = Setting(8000.0)
    ENERGY_END = Setting(18000.0)
    NPOINTS = Setting(20)
    DUMP_TO_FILE = Setting(0)  # No
    FILE_NAME = Setting("Fh.dat")

    def build_gui(self):

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

        idx = -1

        #widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "ILATTICE",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=Crystal_GetCrystalsList(),
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

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

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

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

        #widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "plot_variable",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=self.plotOptionList()[2:],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=150)
        self.show_at(self.unitFlags()[idx], box1)

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

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

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

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

        # widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "DUMP_TO_FILE",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     items=["No", "Yes"],
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "FILE_NAME",
                     label=self.unitLabels()[idx],
                     addSpace=True)
        self.show_at(self.unitFlags()[idx], box1)

        gui.rubber(self.controlArea)

    def unitLabels(self):
        return [
            'Crystal:', 'h miller index', 'k miller index', 'l miller index',
            'Plot:', 'Temperature factor [see help]:', 'From Energy [eV]',
            'To energy [eV]', 'Number of points', 'Dump to file', 'File name'
        ]

    def unitFlags(self):
        return [
            'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True',
            'True', "True", "self.DUMP_TO_FILE == 1"
        ]

    def plotOptionList(self):
        return [
            "Photon energy [eV]", "Wavelength [A]", "Bragg angle [deg]",
            "Re(f_0)", "Im(f_0)  ", "Re(FH)", "Im(FH)", "Re(FH_BAR)",
            "Im(FH_BAR)", "Re(psi_0)", "Im(psi_0)  ", "Re(psi_H)", "Im(psi_H)",
            "Re(psi_BAR)", "Im(psi_BAR)", "Re(F(h,k,l))", "Im(F(h,k,l))",
            "delta (1-Re(refrac))", "Re(refrac index)", "Im(refrac index)",
            "absorption coeff", "s-pol Darwin width [microrad]",
            "p-pol Darwin width [microrad]", "Sin(Bragg angle)/Lambda",
            "psi_over_f"
        ]

    def get_help_name(self):
        return 'fh'

    def check_fields(self):
        self.HMILLER = congruence.checkNumber(self.HMILLER, "h miller index")
        self.KMILLER = congruence.checkNumber(self.KMILLER, "k miller index")
        self.LMILLER = congruence.checkNumber(self.LMILLER, "l miller index")

        self.TEMPER = congruence.checkNumber(self.TEMPER, "Temperature factor")

        self.ENERGY = congruence.checkPositiveNumber(self.ENERGY,
                                                     "Energy from")
        self.ENERGY_END = congruence.checkStrictlyPositiveNumber(
            self.ENERGY_END, "Energy to")
        congruence.checkLessThan(self.ENERGY, self.ENERGY_END, "Energy from",
                                 "Energy to")
        self.NPOINTS = congruence.checkStrictlyPositiveNumber(
            self.NPOINTS, "Number of Points")

    def do_xoppy_calculation(self):
        self.I_PLOT = self.plot_variable + 2

        return self.xoppy_calc_xfh()

    def extract_data_from_xoppy_output(self, calculation_output):
        return calculation_output

    def get_data_exchange_widget_name(self):
        return "XFH"

    def getTitles(self):
        return ["Calculation Result"]

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

    def getYTitles(self):
        return [self.plotOptionList()[self.I_PLOT]]

    def getVariablesToPlot(self):
        return [(0, self.I_PLOT)]

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

    def xoppy_calc_xfh(self):
        #TODO: remove I_ABSORP
        ILATTICE = self.ILATTICE
        HMILLER = self.HMILLER
        KMILLER = self.KMILLER
        LMILLER = self.LMILLER
        I_PLOT = self.I_PLOT
        TEMPER = self.TEMPER
        ENERGY = self.ENERGY
        ENERGY_END = self.ENERGY_END
        NPOINTS = self.NPOINTS

        descriptor = Crystal_GetCrystalsList()[ILATTICE]
        print("Using crystal descriptor: ", descriptor)
        bragg_dictionary = bragg_calc(descriptor=descriptor,
                                      hh=HMILLER,
                                      kk=KMILLER,
                                      ll=LMILLER,
                                      temper=TEMPER,
                                      emin=ENERGY,
                                      emax=ENERGY_END,
                                      estep=50.0,
                                      fileout=None)

        energy = numpy.linspace(ENERGY, ENERGY_END, NPOINTS)

        out = numpy.zeros((25, NPOINTS))

        info = ""
        for i, ienergy in enumerate(energy):
            dic2 = crystal_fh(bragg_dictionary, ienergy)
            print("Energy=%g eV FH=(%g,%g)" %
                  (ienergy, dic2["STRUCT"].real, dic2["STRUCT"].imag))

            out[0, i] = ienergy
            out[1, i] = dic2["WAVELENGTH"] * 1e10
            out[2, i] = dic2["THETA"] * 180 / numpy.pi
            out[3, i] = dic2["F_0"].real
            out[4, i] = dic2["F_0"].imag
            out[5, i] = dic2["FH"].real
            out[6, i] = dic2["FH"].imag
            out[7, i] = dic2["FH_BAR"].real
            out[8, i] = dic2["FH_BAR"].imag
            out[9, i] = dic2["psi_0"].real
            out[10, i] = dic2["psi_0"].imag
            out[11, i] = dic2["psi_h"].real
            out[12, i] = dic2["psi_h"].imag
            out[13, i] = dic2["psi_hbar"].real
            out[14, i] = dic2["psi_hbar"].imag
            out[15, i] = dic2["STRUCT"].real
            out[16, i] = dic2["STRUCT"].imag
            out[17, i] = dic2["DELTA_REF"]
            out[18, i] = dic2["REFRAC"].real
            out[19, i] = dic2["REFRAC"].imag
            out[20, i] = dic2["ABSORP"]
            out[21, i] = 1e6 * dic2["ssr"]  # in microrads
            out[22, i] = 1e6 * dic2["spr"]  # in microrads
            out[23, i] = dic2["RATIO"]
            out[24, i] = dic2["psi_over_f"]
            info += "#\n#\n#\n"
            info += dic2["info"]

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

        try:
            calculated_data.add_content("xoppy_data", out.T)
            calculated_data.add_content("plot_x_col", 0)
            calculated_data.add_content("plot_y_col", I_PLOT)
        except:
            pass
        try:
            calculated_data.add_content("labels", self.plotOptionList())
        except:
            pass
        try:
            calculated_data.add_content("info", info)
        except:
            pass

        if self.DUMP_TO_FILE:
            with open(self.FILE_NAME, "w") as file:
                try:
                    file.write("#F %s\n" % self.FILE_NAME)
                    file.write("\n#S 1 xoppy CrossSec results\n")
                    file.write("#N %d\n" % (out.shape[0]))
                    tmp = "#L"
                    for item in self.plotOptionList():
                        tmp += "  %s" % (item)
                    tmp += "\n"
                    file.write(tmp)
                    for j in range(out.shape[1]):
                        file.write(
                            ("%19.12e  " * out.shape[0] + "\n") %
                            tuple(out[i, j] for i in range(out.shape[0])))
                    file.close()
                    print("File written to disk: %s \n" % self.FILE_NAME)
                except:
                    raise Exception(
                        "CrossSec: The data could not be dumped onto the specified file!\n"
                    )

        return calculated_data
Exemplo n.º 22
0
class FocusingPolycapillary(ow_generic_element.GenericElement):
    name = "Focusing Polycapillary Lens"
    description = "User Defined: Focusing Polycapillary Lens"
    icon = "icons/focusing_polycapillary.png"
    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    priority = 7
    category = "User Defined"
    keywords = ["data", "file", "load", "read"]

    inputs = [("Input Beam", ShadowBeam, "setBeam")]

    outputs = [{"name": "Beam",
                "type": ShadowBeam,
                "doc": "Shadow Beam",
                "id": "beam"},
               {"name": "Trigger",
                "type": TriggerIn,
                "doc": "Feedback signal to start a new beam simulation",
                "id": "Trigger"}]

    input_beam = None

    NONE_SPECIFIED = "NONE SPECIFIED"

    CONTROL_AREA_HEIGHT = 440
    CONTROL_AREA_WIDTH = 470

    input_diameter = Setting(0.5)
    inner_diameter = Setting(1.5)
    output_diameter = Setting(0.5)

    angular_acceptance = Setting(20.0)
    focal_length = Setting(10.0)
    focus_dimension = Setting(100)

    lens_length = Setting(10.0)

    source_plane_distance = Setting(0.0)
    image_plane_distance = Setting(0)

    transmittance = Setting(40.0)

    file_to_write_out = Setting(3)

    want_main_area = 1

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

        self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)

        tabs_setting = gui.tabWidget(self.controlArea)

        tab_bas = oasysgui.createTabPage(tabs_setting, "Basic Setting")
        tab_adv = oasysgui.createTabPage(tabs_setting, "Advanced Setting")

        lens_box = oasysgui.widgetBox(tab_bas, "Input Parameters", addSpace=False, orientation="vertical", height=600, width=450)

        self.le_source_plane_distance = oasysgui.lineEdit(lens_box, self, "source_plane_distance", "Source Plane Distance", labelWidth=350, valueType=float, orientation="horizontal")
        self.le_image_plane_distance = oasysgui.lineEdit(lens_box, self, "image_plane_distance", "Image Plane Distance", labelWidth=350, valueType=float, orientation="horizontal")

        gui.separator(lens_box)

        self.le_input_diameter = oasysgui.lineEdit(lens_box, self, "input_diameter", "Input Diameter", labelWidth=350, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(lens_box, self, "angular_acceptance", "Angular Acceptance [deg]", labelWidth=350, valueType=float, orientation="horizontal")
        self.le_inner_diameter = oasysgui.lineEdit(lens_box, self, "inner_diameter", "Central Diameter", labelWidth=350, valueType=float, orientation="horizontal")
        self.le_output_diameter = oasysgui.lineEdit(lens_box, self, "output_diameter", "Output Diameter", labelWidth=350, valueType=float, orientation="horizontal")
        self.le_focal_length = oasysgui.lineEdit(lens_box, self, "focal_length", "Focal Length", labelWidth=350, valueType=float, orientation="horizontal")
        self.le_focus_dimension = oasysgui.lineEdit(lens_box, self, "focus_dimension", "Approximate focus dimension", labelWidth=350, valueType=float, orientation="horizontal")
        self.le_lens_length = oasysgui.lineEdit(lens_box, self, "lens_length", "Lens Total Length", labelWidth=350, valueType=float, orientation="horizontal")

        gui.separator(lens_box)

        oasysgui.lineEdit(lens_box, self, "transmittance", "Lens Transmittance [%]", labelWidth=350, valueType=float, orientation="horizontal")

        gui.separator(self.controlArea, height=80)

        button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")

        button = gui.button(button_box, self, "Run Shadow/trace", callback=self.traceOpticalElement)
        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(100)

    def callResetSettings(self):
        super().callResetSettings()
        self.setupUI()

    def after_change_workspace_units(self):
        label = self.le_source_plane_distance.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_image_plane_distance.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_input_diameter.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_inner_diameter.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_output_diameter.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

        label = self.le_focal_length.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_focus_dimension.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

        label = self.le_lens_length.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

    ############################################################
    #
    # GRAPHIC USER INTERFACE MANAGEMENT
    #
    ############################################################

    def get_ray_rotation_angle(self, x, z):
        return numpy.tan(numpy.sqrt(x ** 2 + z ** 2) / self.focal_length)

    def get_first_slits_distance(self):
        return (0.5 * (self.inner_diameter - self.input_diameter)) / numpy.tan(numpy.radians(0.5 * self.angular_acceptance))

    def get_second_slits_distance(self):
        return (0.5 * (self.inner_diameter - self.output_diameter)) / numpy.tan(0.5 * self.output_diameter / self.focal_length)

    ############################################################
    #
    # USER INPUT MANAGEMENT
    #
    ############################################################

    def adjust_first_divergence(self, beam_out):
        for index in range(len(beam_out._beam.rays)):
            if beam_out._beam.rays[index, 9] == 1:
                beam_out._beam.rays[index, 3] = 0.0
                beam_out._beam.rays[index, 4] = 1.0
                beam_out._beam.rays[index, 5] = 0.0

        return beam_out

    def adjust_second_divergence_and_intensity(self, beam_out):
        reduction_factor = numpy.sqrt(self.transmittance / 100)

        for index in range(len(beam_out._beam.rays)):
            if beam_out._beam.rays[index, 9] == 1:
                beam_out._beam.rays[index, 6] = beam_out._beam.rays[index, 6] * reduction_factor
                beam_out._beam.rays[index, 7] = beam_out._beam.rays[index, 7] * reduction_factor
                beam_out._beam.rays[index, 8] = beam_out._beam.rays[index, 8] * reduction_factor
                beam_out._beam.rays[index, 15] = beam_out._beam.rays[index, 15] * reduction_factor
                beam_out._beam.rays[index, 16] = beam_out._beam.rays[index, 16] * reduction_factor
                beam_out._beam.rays[index, 17] = beam_out._beam.rays[index, 17] * reduction_factor

                x_ray = beam_out._beam.rays[index, 0]
                z_ray = beam_out._beam.rays[index, 2]

                sigma = self.focus_dimension * 1e-4

                distance = numpy.random.normal(scale=sigma)

                x_spot = numpy.random.random() * distance * self.get_random_sign()
                z_spot = numpy.sqrt(distance ** 2 - x_spot ** 2) * self.get_random_sign()

                v_director = ShadowMath.vector_difference([x_ray, 0.0, z_ray], [x_spot, self.focal_length + self.get_second_slits_distance(), z_spot])
                v_director = v_director / ShadowMath.vector_modulus(v_director)  # versor

                beam_out._beam.rays[index, 3] = v_director[0]
                beam_out._beam.rays[index, 4] = v_director[1]
                beam_out._beam.rays[index, 5] = v_director[2]

        return beam_out

    def get_random_sign(self):
        random = numpy.random.random()

        if random < 0.5:
            return 1.0
        else:
            return -1.0

    def populateFields_1(self, shadow_oe):
        slits_distance = self.get_first_slits_distance()

        shadow_oe._oe.T_SOURCE = self.source_plane_distance
        shadow_oe._oe.T_IMAGE = slits_distance
        shadow_oe._oe.T_INCIDENCE = 0.0
        shadow_oe._oe.T_REFLECTION = 180.0
        shadow_oe._oe.ALPHA = 0.0

        n_screen = 2
        i_screen = numpy.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # after
        i_abs = numpy.zeros(10)  # not absorbing
        i_slit = numpy.array([1, 1, 0, 0, 0, 0, 0, 0, 0, 0])  # slit
        i_stop = numpy.zeros(10)  # aperture
        k_slit = numpy.array([1, 1, 0, 0, 0, 0, 0, 0, 0, 0])  # ellipse
        thick = numpy.zeros(10)
        file_abs = numpy.array(['', '', '', '', '', '', '', '', '', ''])
        rx_slit = numpy.zeros(10)
        rz_slit = numpy.zeros(10)
        sl_dis = numpy.zeros(10)
        file_src_ext = numpy.array(['', '', '', '', '', '', '', '', '', ''])
        cx_slit = numpy.zeros(10)
        cz_slit = numpy.zeros(10)

        sl_dis[0] = 0.0
        rx_slit[0] = self.input_diameter
        rz_slit[0] = self.input_diameter

        sl_dis[1] = slits_distance
        rx_slit[1] = self.inner_diameter
        rz_slit[1] = self.inner_diameter

        shadow_oe._oe.set_screens(n_screen,
                                 i_screen,
                                 i_abs,
                                 sl_dis,
                                 i_slit,
                                 i_stop,
                                 k_slit,
                                 thick,
                                 file_abs,
                                 rx_slit,
                                 rz_slit,
                                 cx_slit,
                                 cz_slit,
                                 file_src_ext)

    def populateFields_2(self, shadow_oe):
        slits_distance = self.lens_length - (self.get_first_slits_distance() - self.get_second_slits_distance())

        shadow_oe._oe.T_SOURCE = 0.0
        shadow_oe._oe.T_IMAGE = slits_distance
        shadow_oe._oe.T_INCIDENCE = 0.0
        shadow_oe._oe.T_REFLECTION = 180.0
        shadow_oe._oe.ALPHA = 0.0

        n_screen = 1
        i_screen = numpy.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # after
        i_abs = numpy.zeros(10)  # not absorbing
        i_slit = numpy.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # slit
        i_stop = numpy.zeros(10)  # aperture
        k_slit = numpy.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # ellipse
        thick = numpy.zeros(10)
        file_abs = numpy.array(['', '', '', '', '', '', '', '', '', ''])
        rx_slit = numpy.zeros(10)
        rz_slit = numpy.zeros(10)
        sl_dis = numpy.zeros(10)
        file_src_ext = numpy.array(['', '', '', '', '', '', '', '', '', ''])
        cx_slit = numpy.zeros(10)
        cz_slit = numpy.zeros(10)

        sl_dis[0] = slits_distance
        rx_slit[0] = self.inner_diameter
        rz_slit[0] = self.inner_diameter

        shadow_oe._oe.set_screens(n_screen,
                                 i_screen,
                                 i_abs,
                                 sl_dis,
                                 i_slit,
                                 i_stop,
                                 k_slit,
                                 thick,
                                 file_abs,
                                 rx_slit,
                                 rz_slit,
                                 cx_slit,
                                 cz_slit,
                                 file_src_ext)

    def populateFields_3(self, shadow_oe):
        slits_distance = self.get_second_slits_distance()

        shadow_oe._oe.T_SOURCE = 0.0
        shadow_oe._oe.T_IMAGE = slits_distance + self.image_plane_distance
        shadow_oe._oe.T_INCIDENCE = 0.0
        shadow_oe._oe.T_REFLECTION = 180.0
        shadow_oe._oe.ALPHA = 0.0

        n_screen = 1
        i_screen = numpy.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # after
        i_abs = numpy.zeros(10)  # not absorbing
        i_slit = numpy.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # slit
        i_stop = numpy.zeros(10)  # aperture
        k_slit = numpy.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])  # ellipse
        thick = numpy.zeros(10)
        file_abs = numpy.array(['', '', '', '', '', '', '', '', '', ''])
        rx_slit = numpy.zeros(10)
        rz_slit = numpy.zeros(10)
        sl_dis = numpy.zeros(10)
        file_src_ext = numpy.array(['', '', '', '', '', '', '', '', '', ''])
        cx_slit = numpy.zeros(10)
        cz_slit = numpy.zeros(10)

        sl_dis[0] = slits_distance
        rx_slit[0] = self.output_diameter
        rz_slit[0] = self.output_diameter

        shadow_oe._oe.set_screens(n_screen,
                                 i_screen,
                                 i_abs,
                                 sl_dis,
                                 i_slit,
                                 i_stop,
                                 k_slit,
                                 thick,
                                 file_abs,
                                 rx_slit,
                                 rz_slit,
                                 cx_slit,
                                 cz_slit,
                                 file_src_ext)

    def checkFields(self):
        congruence.checkPositiveNumber(self.source_plane_distance, "Distance from Source")
        congruence.checkPositiveNumber(self.image_plane_distance, "Image Plane Distance")
        congruence.checkStrictlyPositiveNumber(self.input_diameter, "Input Diameter")
        congruence.checkStrictlyPositiveAngle(self.angular_acceptance, "Angular Acceptance")
        congruence.checkStrictlyPositiveNumber(self.output_diameter, "Output Diameter")
        congruence.checkStrictlyPositiveNumber(self.inner_diameter, "Central Diameter")
        congruence.checkStrictlyPositiveNumber(self.focal_length, "Focal Length")
        congruence.checkStrictlyPositiveNumber(self.focus_dimension, "Focus Dimension")
        congruence.checkStrictlyPositiveNumber(self.lens_length, "Lens Total Length")

        if self.inner_diameter <= self.input_diameter:
            raise Exception("Central Diameter should be greater than Input diameter")

        if self.inner_diameter <= self.output_diameter:
            raise Exception("Central Diameter should be greater than Output diameter")

        if self.focal_length < self.output_diameter:
            raise Exception("Focal Length should be greater than or equal to Output diameter")

        first_slit_distance = self.get_first_slits_distance()
        second_slit_distance = self.get_second_slits_distance()

        slit_distance = first_slit_distance + second_slit_distance

        if self.lens_length < slit_distance:
            raise Exception("Lens total Length should be greater than or equal to " + str(slit_distance))

        congruence.checkStrictlyPositiveNumber(self.transmittance, "Lens Transmittance")

    def traceOpticalElement(self):
        try:
            self.error(self.error_id)
            self.setStatusMessage("")
            self.progressBarInit()

            if ShadowCongruence.checkEmptyBeam(self.input_beam):
                if ShadowCongruence.checkGoodBeam(self.input_beam):
                    sys.stdout = EmittingStream(textWritten=self.writeStdOut)

                    self.progressBarSet(10)

                    self.checkFields()

                    self.setStatusMessage("Running SHADOW")

                    if self.trace_shadow:
                        grabber = TTYGrabber()
                        grabber.start()

                    self.progressBarSet(50)

                    ###########################################
                    # TODO: TO BE ADDED JUST IN CASE OF BROKEN
                    #       ENVIRONMENT: MUST BE FOUND A PROPER WAY
                    #       TO TEST SHADOW
                    self.fixWeirdShadowBug()
                    ###########################################

                    shadow_oe_1 = ShadowOpticalElement.create_screen_slit()
                    self.populateFields_1(shadow_oe_1)

                    beam_out = ShadowBeam.traceFromOE(self.input_beam, shadow_oe_1)

                    self.adjust_first_divergence(beam_out)

                    self.progressBarSet(60)

                    shadow_oe_2 = ShadowOpticalElement.create_screen_slit()
                    self.populateFields_2(shadow_oe_2)

                    beam_out = ShadowBeam.traceFromOE(beam_out, shadow_oe_2)

                    self.adjust_second_divergence_and_intensity(beam_out)

                    self.progressBarSet(70)

                    shadow_oe_3 = ShadowOpticalElement.create_screen_slit()
                    self.populateFields_3(shadow_oe_3)

                    beam_out = ShadowBeam.traceFromOE(beam_out, shadow_oe_3)

                    if self.trace_shadow:
                        grabber.stop()

                        for row in grabber.ttyData:
                            self.writeStdOut(row)

                    self.setStatusMessage("Plotting Results")

                    self.plot_results(beam_out)

                    self.setStatusMessage("")

                    self.send("Beam", beam_out)
                    self.send("Trigger", TriggerIn(new_object=True))
                else:
                    raise Exception("Input Beam with no good rays")
            else:
                raise Exception("Empty Input Beam")

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

            self.error_id = self.error_id + 1
            self.error(self.error_id, "Exception occurred: " + str(exception))

        self.progressBarFinished()

    def setBeam(self, beam):
        self.onReceivingInput()

        if ShadowCongruence.checkEmptyBeam(beam):
            self.input_beam = beam

            if self.is_automatic_run:
                self.traceOpticalElement()

    def setPreProcessorData(self, data):
        if data is not None:
            if data.prerefl_data_file != ShadowPreProcessorData.NONE:
                self.prerefl_file = data.prerefl_data_file

    def setupUI(self):
        self.set_surface_shape()
        self.set_diameter()
        self.set_cylindrical()
        self.set_ri_calculation_mode()
Exemplo n.º 23
0
class BeamFileWriter(OWWidget):
    name = "Shadow File Writer"
    description = "Utility: Shadow File Writer"
    icon = "icons/beam_file_writer.png"
    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    priority = 3
    category = "Utility"
    keywords = ["data", "file", "load", "read"]

    want_main_area = 0

    beam_file_name = Setting("")
    is_automatic_run= Setting(1)

    inputs = [("Input Beam" , ShadowBeam, "setBeam" ),]

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

    input_beam = None

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

        self.runaction = widget.OWAction("Write Shadow File", self)
        self.runaction.triggered.connect(self.write_file)
        self.addAction(self.runaction)

        self.setFixedWidth(590)
        self.setFixedHeight(190)

        left_box_1 = oasysgui.widgetBox(self.controlArea, "Shadow File Selection", addSpace=True, orientation="vertical",
                                         width=570, height=110)

        gui.checkBox(left_box_1, self, 'is_automatic_run', 'Automatic Execution')

        gui.separator(left_box_1, height=10)

        figure_box = oasysgui.widgetBox(left_box_1, "", addSpace=True, orientation="horizontal", width=550, height=35)

        self.le_beam_file_name = oasysgui.lineEdit(figure_box, self, "beam_file_name", "Shadow File Name",
                                                    labelWidth=120, valueType=str, orientation="horizontal")
        self.le_beam_file_name.setFixedWidth(330)

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

        button = gui.button(self.controlArea, self, "Write Shadow File", callback=self.write_file)
        button.setFixedHeight(45)

        gui.rubber(self.controlArea)

    def selectFile(self):
        self.le_beam_file_name.setText(oasysgui.selectFileFromDialog(self, self.beam_file_name, "Open Shadow File"))

    def setBeam(self, beam):
        if ShadowCongruence.checkEmptyBeam(beam):
            if ShadowCongruence.checkGoodBeam(beam):
                self.input_beam = beam

                if self.is_automatic_run:
                    self.write_file()
            else:
                QtWidgets.QMessageBox.critical(self, "Error",
                                           "No good rays or bad content",
                                           QtWidgets.QMessageBox.Ok)

    def write_file(self):
        self.setStatusMessage("")

        try:
            if ShadowCongruence.checkEmptyBeam(self.input_beam):
                if ShadowCongruence.checkGoodBeam(self.input_beam):
                    if congruence.checkFileName(self.beam_file_name):
                        self.input_beam.writeToFile(self.beam_file_name)

                        path, file_name = os.path.split(self.beam_file_name)

                        self.setStatusMessage("File Out: " + file_name)

                        self.send("Beam", self.input_beam)
                else:
                    QtWidgets.QMessageBox.critical(self, "Error",
                                               "No good rays or bad content",
                                               QtWidgets.QMessageBox.Ok)
        except Exception as exception:
            QtWidgets.QMessageBox.critical(self, "Error",
                                       str(exception), QtWidgets.QMessageBox.Ok)
Exemplo n.º 24
0
class OWxcrystal(XoppyWidget):
    name = "CRYSTAL"
    id = "orange.widgets.dataxcrystal"
    description = "Crystal Reflectivity (perfect, bent, mosaic)"
    icon = "icons/xoppy_xcrystal.png"
    priority = 5
    category = ""
    keywords = ["xoppy", "xcrystal"]
 
    CRYSTAL_MATERIAL = Setting(32)
    MILLER_INDEX_H = Setting(1)
    MILLER_INDEX_K = Setting(1)
    MILLER_INDEX_L = Setting(1)
    TEMPER = Setting("1.0")
    MOSAIC = Setting(0)
    GEOMETRY = Setting(0)
    SCAN = Setting(2)
    UNIT = Setting(1)
    SCANFROM = Setting(-100.0)
    SCANTO = Setting(100.0)
    SCANPOINTS = Setting(200)
    ENERGY = Setting(8000.0)
    ASYMMETRY_ANGLE = Setting(0.0)
    THICKNESS = Setting(0.7)
    MOSAIC_FWHM = Setting(0.1)
    RSAG = Setting(125.0)
    RMER = Setting(1290.0)
    ANISOTROPY = Setting(0)
    POISSON = Setting(0.22)
    CUT = Setting("2 -1 -1 ; 1 1 1 ; 0 0 0")
    FILECOMPLIANCE = Setting("mycompliance.dat")

    def build_gui(self):

        box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5)
        
        idx = -1 
        
        #widget index 3 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "CRYSTAL_MATERIAL",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=Crystal_GetCrystalsList(),
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 4 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "MILLER_INDEX_H",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 5 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "MILLER_INDEX_K",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 6 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "MILLER_INDEX_L",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 

        
        #widget index 8 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "TEMPER",
                     label=self.unitLabels()[idx], addSpace=False, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 9 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "MOSAIC",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['Perfect crystal', 'Mosaic', 'Bent Crystal ML', 'Bent Crystal PP'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 10 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "GEOMETRY",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['BRAGG: diffr beam', 'LAUE: diffr beam', 'BRAGG: transm beam', 'LAUE: transm beam'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 11 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "SCAN",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['Theta (absolute)', 'Th - Th Bragg (corrected)', 'Th - Th Bragg', 'Energy [eV]', 'y (Zachariasen)'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 12 
        idx += 1 
        box1 = gui.widgetBox(box) 
        self.unit_combo = gui.comboBox(box1, self, "UNIT",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['Radians', 'micro rads', 'Degrees', 'ArcSec'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 13 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "SCANFROM",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 14 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "SCANTO",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 15 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "SCANPOINTS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 16 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "ENERGY",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 17 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "ASYMMETRY_ANGLE",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 18 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "THICKNESS",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 19 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "MOSAIC_FWHM",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 20 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "RSAG",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 21 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "RMER",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 22 
        idx += 1 
        box1 = gui.widgetBox(box) 
        gui.comboBox(box1, self, "ANISOTROPY",
                     label=self.unitLabels()[idx], addSpace=False,
                    items=['None (isotropic)', 'Default cut', 'Cut directions', 'From file'],
                    valueType=int, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 23 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "POISSON",
                     label=self.unitLabels()[idx], addSpace=False,
                    valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 24 
        idx += 1 
        box1 = gui.widgetBox(box) 
        oasysgui.lineEdit(box1, self, "CUT",
                     label=self.unitLabels()[idx], addSpace=False, orientation="horizontal", labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1) 
        
        #widget index 25 
        idx += 1 
        box1 = gui.widgetBox(box)

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

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

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

    def unitLabels(self):
         return ['Crystal:','h Miller index','k Miller index','l Miller index','Temperature factor [see help]:', # 0-5
                 'Crystal Model:','Geometry:','Scan:','Scan Units:','Min Scan value:','Max Scan value:','Scan Points:', # 6-12
                 'Fix value (E[eV] or Theta[deg])','Asymmetry angle [deg] (to surf.)','Crystal Thickness [cm]:', # 13-15
                 'Mosaicity [deg, fwhm]: ', #16
                 'R sagittal [cm]: ','R meridional [cm]: ','Anisotropy: ','Poisson ratio','Valong ; Vnorm ; Vperp','File (compliance tensor)']


    def unitFlags(self):
         return ['True','True','True','True','True',
                 'True','True','True','self.SCAN  <=  2','True','True','True',
                 'True','(self.MOSAIC  ==  0) or (self.MOSAIC  >  1)','True',
                 'self.MOSAIC  ==  1',
                 'self.MOSAIC  >  1','self.MOSAIC  >  1','self.MOSAIC  >  1','self.MOSAIC  >  1  and  self.ANISOTROPY  ==  0','self.MOSAIC  >  1  and  self.ANISOTROPY  ==  2','self.MOSAIC  >  1  and  self.ANISOTROPY  ==  3']

    def get_help_name(self):
        return 'crystal'

    def selectFile(self):
        self.le_file_compliance.setText(oasysgui.selectFileFromDialog(self, self.FILECOMPLIANCE, "Open File (compliance tensor)", file_extension_filter="*.dat *.txt"))


    def check_fields(self):
        self.MILLER_INDEX_H = congruence.checkNumber(self.MILLER_INDEX_H, "Miller index H")
        self.MILLER_INDEX_K = congruence.checkNumber(self.MILLER_INDEX_K, "Miller index K")
        self.MILLER_INDEX_L = congruence.checkNumber(self.MILLER_INDEX_L, "Miller index L")
        self.TEMPER = congruence.checkNumber(self.TEMPER, "Temperature factor")

        if self.SCAN == 0 or self.SCAN == 3:
            self.SCANFROM = congruence.checkPositiveNumber(self.SCANFROM, "Min Scan value")
            self.SCANTO = congruence.checkStrictlyPositiveNumber(self.SCANTO, "Max Scan value")
        else:
            self.SCANFROM = congruence.checkNumber(self.SCANFROM, "Min Scan value")
            self.SCANTO = congruence.checkNumber(self.SCANTO, "Max Scan value")

        congruence.checkLessThan(self.SCANFROM, self.SCANTO, "Min Scan value", "Max Scan value")
        self.SCANPOINTS = congruence.checkStrictlyPositiveNumber(self.SCANPOINTS, "Scan points")

        if self.SCAN < 4:
            self.ENERGY = congruence.checkStrictlyPositiveNumber(self.ENERGY , "Fix value")
        else:
            self.ENERGY = congruence.checkNumber(self.ENERGY , "Fix value")

        if self.MOSAIC == 0: #perfect
            self.ASYMMETRY_ANGLE = congruence.checkNumber(self.ASYMMETRY_ANGLE, "Asymmetry angle")
            self.THICKNESS = congruence.checkStrictlyPositiveNumber(self.THICKNESS, "Crystal thickness")
        elif self.MOSAIC == 1: #mosaic
            self.THICKNESS = congruence.checkStrictlyPositiveNumber(self.THICKNESS, "Crystal thickness")
            self.MOSAIC_FWHM = congruence.checkNumber(self.MOSAIC_FWHM, "Mosaicity")
        elif self.MOSAIC == 2 or self.MOSAIC == 3: #bent ML/PP
            self.ASYMMETRY_ANGLE = congruence.checkNumber(self.ASYMMETRY_ANGLE, "Asymmetry angle")
            self.THICKNESS = congruence.checkStrictlyPositiveNumber(self.THICKNESS, "Crystal thickness")
            self.RSAG = congruence.checkStrictlyPositiveNumber(self.RSAG, "R Sagittal")
            self.RMER = congruence.checkStrictlyPositiveNumber(self.RMER, "R meridional")

            if self.ANISOTROPY == 0:
                self.POISSON = congruence.checkStrictlyPositiveNumber(self.POISSON, "Poisson Ratio")
            elif self.ANISOTROPY == 2:
                congruence.checkEmptyString(self.CUT, "Valong; Vnorm; Vperp")
            elif self.ANISOTROPY == 3:
                congruence.checkFile(self.FILECOMPLIANCE)


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

    def extract_data_from_xoppy_output(self, calculation_output):
        return calculation_output

    def get_data_exchange_widget_name(self):
        return "XCRYSTAL"

    def getTitles(self):
        return ["Phase_p","Phase_s","Circ. Polariz.","p-polarized reflectivity","s-polarized reflectivity"]

    def getXTitles(self):
        if self.SCAN < 4:
            return ["Th-ThB{in} [" + self.unit_combo.itemText(self.UNIT) + "]",
                    "Th-ThB{in} [" + self.unit_combo.itemText(self.UNIT) + "]",
                    "Th-ThB{in} [" + self.unit_combo.itemText(self.UNIT) + "]",
                    "Th-ThB{in} [" + self.unit_combo.itemText(self.UNIT) + "]",
                    "Th-ThB{in} [" + self.unit_combo.itemText(self.UNIT) + "]"]
        elif self.SCAN ==4:
            return ["Energy [eV]",
                    "Energy [eV]",
                    "Energy [eV]",
                    "Energy [eV]",
                    "Energy [eV]"]
        else:
            return ["y (Zachariasen)",
                    "y (Zachariasen)",
                    "y (Zachariasen)",
                    "y (Zachariasen)",
                    "y (Zachariasen)"]


    def getYTitles(self):
        return ["phase_p [rad]","phase_s [rad]","Circ. Polariz.","p-polarized reflectivity","s-polarized reflectivity"]

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

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

    def plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", log_x=False, log_y=False):
        super().plot_histo(x, y,progressBarValue, tabs_canvas_index, plot_canvas_index, title, xtitle, ytitle, log_x, log_y)

        # ALLOW FIT BUTTON HERE
        self.plot_canvas[plot_canvas_index].fitAction.setVisible(True)

        # overwrite FWHM and peak values
        if title == "s-polarized reflectivity" or title == "p-polarized reflectivity":
            t = numpy.where(y>=max(y)*0.5)
            x_left,x_right =  x[t[0][0]], x[t[0][-1]]


            self.plot_canvas[plot_canvas_index].addMarker(x_left, 0.5, legend="G1", text="FWHM=%5.2f"%(x_right-x_left),
                                                          color="pink",selectable=False, draggable=False,
                                                          symbol="+", constraint=None)
            self.plot_canvas[plot_canvas_index].addMarker(x_right, 0.5, legend="G2", text=None, color="pink",
                                                          selectable=False, draggable=False, symbol="+", constraint=None)

            index_ymax = numpy.argmax(y)
            self.plot_canvas[plot_canvas_index].addMarker(x[index_ymax], y[index_ymax], legend="G3",
                                                          text=None, color="pink",
                                                          selectable=False, draggable=False, symbol="+", constraint=None)
            self.plot_canvas[plot_canvas_index].addMarker(x[index_ymax], y[index_ymax]-0.05, legend="G4",
                                                          text="Peak=%5.2f"%(y[index_ymax]), color="pink",
                                                          selectable=False, draggable=False, symbol=None, constraint=None)

    def xoppy_calc_xcrystal(self):
        CRYSTAL_MATERIAL = self.CRYSTAL_MATERIAL
        MILLER_INDEX_H = self.MILLER_INDEX_H
        MILLER_INDEX_K = self.MILLER_INDEX_K
        MILLER_INDEX_L = self.MILLER_INDEX_L
        TEMPER = self.TEMPER
        MOSAIC = self.MOSAIC
        GEOMETRY = self.GEOMETRY
        SCAN = self.SCAN
        UNIT = self.UNIT
        SCANFROM = self.SCANFROM
        SCANTO = self.SCANTO
        SCANPOINTS = self.SCANPOINTS
        ENERGY = self.ENERGY
        ASYMMETRY_ANGLE = self.ASYMMETRY_ANGLE
        THICKNESS = self.THICKNESS
        MOSAIC_FWHM = self.MOSAIC_FWHM
        RSAG = self.RSAG
        RMER = self.RMER
        ANISOTROPY = self.ANISOTROPY
        POISSON = self.POISSON
        CUT = self.CUT
        FILECOMPLIANCE = self.FILECOMPLIANCE


        for file in ["diff_pat.dat","diff_pat.gle","diff_pat.par","diff_pat.xop","xcrystal.bra"]:
            try:
                os.remove(os.path.join(locations.home_bin_run(),file))
            except:
                pass


        if (GEOMETRY == 1) or (GEOMETRY == 3):
            if ASYMMETRY_ANGLE == 0.0:
                print("xoppy_calc_xcrystal: WARNING: In xcrystal the asymmetry angle is the angle between Bragg planes and crystal surface,"+
                      "in BOTH Bragg and Laue geometries.")


        descriptor = Crystal_GetCrystalsList()[CRYSTAL_MATERIAL]
        if SCAN == 3: # energy scan
            emin = SCANFROM - 1
            emax = SCANTO + 1
        else:
            emin = ENERGY - 100.0
            emax = ENERGY + 100.0

        print("Using crystal descriptor: ",descriptor)

        bragg_dictionary = bragg_calc(descriptor=descriptor,
                                                hh=MILLER_INDEX_H,kk=MILLER_INDEX_K,ll=MILLER_INDEX_L,
                                                temper=float(TEMPER),
                                                emin=emin,emax=emax,estep=5.0,fileout="xcrystal.bra")

        with open("xoppy.inp", "wt") as f:
            f.write("xcrystal.bra\n")
            f.write("%d\n"%MOSAIC)
            f.write("%d\n"%GEOMETRY)

            if MOSAIC == 1:
                f.write("%g\n"%MOSAIC_FWHM)
                f.write("%g\n"%THICKNESS)
            else:
                f.write("%g\n"%THICKNESS)
                f.write("%g\n"%ASYMMETRY_ANGLE)

            scan_flag = 1 + SCAN

            f.write("%d\n"%scan_flag)

            f.write("%19.9f\n"%ENERGY)

            if scan_flag <= 3:
                f.write("%d\n"%UNIT)

            f.write("%g\n"%SCANFROM)
            f.write("%g\n"%SCANTO)
            f.write("%d\n"%SCANPOINTS)

            if MOSAIC > 1: # bent
                f.write("%g\n"%RSAG)
                f.write("%g\n"%RMER)
                f.write("0\n")

                if ( (descriptor == "Si") or (descriptor == "Si2") or (descriptor == "Si_NIST") or (descriptor == "Ge") or descriptor == "Diamond"):
                    pass
                else:  # not Si,Ge,Diamond
                    if ((ANISOTROPY == 1) or (ANISOTROPY == 2)):
                        raise Exception("Anisotropy data not available for this crystal. Either use isotropic or use external compliance file. Please change and run again'")

                f.write("%d\n"%ANISOTROPY)

                if ANISOTROPY == 0:
                    f.write("%g\n"%POISSON)
                elif ANISOTROPY == 1:
                    f.write("%d\n"%CRYSTAL_MATERIAL)
                    f.write("%g\n"%ASYMMETRY_ANGLE)
                    f.write("%d\n"%MILLER_INDEX_H)
                    f.write("%d\n"%MILLER_INDEX_K)
                    f.write("%d\n"%MILLER_INDEX_L)
                elif ANISOTROPY == 2:
                    f.write("%d\n"%CRYSTAL_MATERIAL)
                    f.write("%g\n"%ASYMMETRY_ANGLE)
                    # TODO: check syntax for CUT: Cut syntax is: valong_X valong_Y valong_Z ; vnorm_X vnorm_Y vnorm_Z ; vperp_x vperp_Y vperp_Z
                    f.write("%s\n"%CUT.split(";")[0])
                    f.write("%s\n"%CUT.split(";")[1])
                    f.write("%s\n"%CUT.split(";")[2])
                elif ANISOTROPY == 3:
                    f.write("%s\n"%FILECOMPLIANCE)



        command = "'" + os.path.join(locations.home_bin(), 'diff_pat') + "' < xoppy.inp"
        print("Running command '%s' in directory: %s "%(command, locations.home_bin_run()))
        print("\n--------------------------------------------------------\n")
        os.system(command)
        print("\n--------------------------------------------------------\n")
        
        #show calculated parameters in standard output
        txt_info = open("diff_pat.par").read()
        for line in txt_info:
            print(line,end="")


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

        try:
            calculated_data.add_content("xoppy_data", numpy.loadtxt("diff_pat.dat", skiprows=5))
            calculated_data.add_content("plot_x_col",0)
            calculated_data.add_content("plot_y_col",-1)
            calculated_data.add_content("units_to_degrees", self.get_units_to_degrees())
        except Exception as e:
            raise Exception("Error loading diff_pat.dat :" + str(e))

        try:
            calculated_data.add_content("labels",
                                        ["Th-ThB{in} [" + self.unit_combo.itemText(self.UNIT) + "]",
                                         "Th-ThB{out} [" + self.unit_combo.itemText(self.UNIT) + "]",
                                         "phase_p[rad]",
                                         "phase_s[rad]","Circ Polariz",
                                         "p-polarized reflectivity",
                                         "s-polarized reflectivity"])

        except:
            pass

        try:
            with open("diff_pat.par") as f:
                info = f.readlines()
            calculated_data.add_content("info",info)
        except:
            pass

        return calculated_data


    def get_units_to_degrees(self):
        if self.UNIT == 0: # RADIANS
            return 57.2957795
        elif self.UNIT == 1: #MICRORADIANS
            return 57.2957795e-6
        elif self.UNIT == 2: # DEGREES
            return 1.0
        elif self.UNIT == 3: # ARCSEC
            return 0.000277777805
Exemplo n.º 25
0
class Histogram(ow_automatic_element.AutomaticElement):

    name = "Histogram"
    description = "Display Data Tools: Histogram"
    icon = "icons/histogram.png"
    maintainer = "Luca Rebuffi"
    maintainer_email = "lrebuffi(@at@)anl.gov"
    priority = 2
    category = "Display Data Tools"
    keywords = ["data", "file", "load", "read"]

    inputs = [("Input Beam", ShadowBeam, "setBeam")]

    IMAGE_WIDTH = 878
    IMAGE_HEIGHT = 635

    want_main_area = 1
    plot_canvas = None
    input_beam = None

    image_plane = Setting(0)
    image_plane_new_position = Setting(10.0)
    image_plane_rel_abs_position = Setting(0)

    x_column_index = Setting(10)

    x_range = Setting(0)
    x_range_min = Setting(0.0)
    x_range_max = Setting(0.0)

    weight_column_index = Setting(23)
    rays = Setting(1)

    number_of_bins = Setting(100)

    title = Setting("Energy")

    autosave = Setting(0)
    autosave_file_name = Setting("autosave_histogram_plot.hdf5")

    keep_result = Setting(0)
    autosave_partial_results = Setting(0)

    is_conversion_active = Setting(1)

    cumulated_ticket = None
    plotted_ticket = None
    autosave_file = None
    autosave_prog_id = 0

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

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        gui.button(button_box,
                   self,
                   "Refresh",
                   callback=self.plot_results,
                   height=45)
        gui.button(button_box,
                   self,
                   "Save Current Plot",
                   callback=self.save_results,
                   height=45)

        gui.separator(self.controlArea, 10)

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

        # graph tab
        tab_set = oasysgui.createTabPage(self.tabs_setting, "Plot Settings")
        tab_gen = oasysgui.createTabPage(self.tabs_setting,
                                         "Histogram Settings")

        screen_box = oasysgui.widgetBox(tab_set,
                                        "Screen Position Settings",
                                        addSpace=True,
                                        orientation="vertical",
                                        height=120)

        self.image_plane_combo = gui.comboBox(
            screen_box,
            self,
            "image_plane",
            label="Position of the Image",
            items=["On Image Plane", "Retraced"],
            labelWidth=260,
            callback=self.set_ImagePlane,
            sendSelectedValue=False,
            orientation="horizontal")

        self.image_plane_box = oasysgui.widgetBox(screen_box,
                                                  "",
                                                  addSpace=False,
                                                  orientation="vertical",
                                                  height=50)
        self.image_plane_box_empty = oasysgui.widgetBox(screen_box,
                                                        "",
                                                        addSpace=False,
                                                        orientation="vertical",
                                                        height=50)

        oasysgui.lineEdit(self.image_plane_box,
                          self,
                          "image_plane_new_position",
                          "Image Plane new Position",
                          labelWidth=220,
                          valueType=float,
                          orientation="horizontal")

        gui.comboBox(self.image_plane_box,
                     self,
                     "image_plane_rel_abs_position",
                     label="Position Type",
                     labelWidth=250,
                     items=["Absolute", "Relative"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.set_ImagePlane()

        general_box = oasysgui.widgetBox(tab_set,
                                         "General Settings",
                                         addSpace=True,
                                         orientation="vertical",
                                         height=250)

        self.x_column = gui.comboBox(
            general_box,
            self,
            "x_column_index",
            label="Column",
            labelWidth=70,
            items=[
                "1: X",
                "2: Y",
                "3: Z",
                "4: X'",
                "5: Y'",
                "6: Z'",
                "7: E\u03c3 X",
                "8: E\u03c3 Y",
                "9: E\u03c3 Z",
                "10: Ray Flag",
                "11: Energy",
                "12: Ray Index",
                "13: Optical Path",
                "14: Phase \u03c3",
                "15: Phase \u03c0",
                "16: E\u03c0 X",
                "17: E\u03c0 Y",
                "18: E\u03c0 Z",
                "19: Wavelength",
                "20: R = sqrt(X\u00b2 + Y\u00b2 + Z\u00b2)",
                "21: Theta (angle from Y axis)",
                "22: Magnitude = |E\u03c3| + |E\u03c0|",
                "23: Total Intensity = |E\u03c3|\u00b2 + |E\u03c0|\u00b2",
                "24: \u03a3 Intensity = |E\u03c3|\u00b2",
                "25: \u03a0 Intensity = |E\u03c0|\u00b2",
                "26: |K|",
                "27: K X",
                "28: K Y",
                "29: K Z",
                "30: S0-stokes = |E\u03c0|\u00b2 + |E\u03c3|\u00b2",
                "31: S1-stokes = |E\u03c0|\u00b2 - |E\u03c3|\u00b2",
                "32: S2-stokes = 2|E\u03c3||E\u03c0|cos(Phase \u03c3-Phase \u03c0)",
                "33: S3-stokes = 2|E\u03c3||E\u03c0|sin(Phase \u03c3-Phase \u03c0)",
                "34: Power = Intensity * Energy",
            ],
            sendSelectedValue=False,
            orientation="horizontal")

        gui.comboBox(general_box,
                     self,
                     "x_range",
                     label="X Range",
                     labelWidth=250,
                     items=["<Default>", "Set.."],
                     callback=self.set_XRange,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.xrange_box = oasysgui.widgetBox(general_box,
                                             "",
                                             addSpace=True,
                                             orientation="vertical",
                                             height=100)
        self.xrange_box_empty = oasysgui.widgetBox(general_box,
                                                   "",
                                                   addSpace=True,
                                                   orientation="vertical",
                                                   height=100)

        oasysgui.lineEdit(self.xrange_box,
                          self,
                          "x_range_min",
                          "X min",
                          labelWidth=220,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(self.xrange_box,
                          self,
                          "x_range_max",
                          "X max",
                          labelWidth=220,
                          valueType=float,
                          orientation="horizontal")

        self.set_XRange()

        self.weight_column = gui.comboBox(
            general_box,
            self,
            "weight_column_index",
            label="Weight",
            labelWidth=70,
            items=[
                "0: No Weight",
                "1: X",
                "2: Y",
                "3: Z",
                "4: X'",
                "5: Y'",
                "6: Z'",
                "7: E\u03c3 X",
                "8: E\u03c3 Y",
                "9: E\u03c3 Z",
                "10: Ray Flag",
                "11: Energy",
                "12: Ray Index",
                "13: Optical Path",
                "14: Phase \u03c3",
                "15: Phase \u03c0",
                "16: E\u03c0 X",
                "17: E\u03c0 Y",
                "18: E\u03c0 Z",
                "19: Wavelength",
                "20: R = sqrt(X\u00b2 + Y\u00b2 + Z\u00b2)",
                "21: Theta (angle from Y axis)",
                "22: Magnitude = |E\u03c3| + |E\u03c0|",
                "23: Total Intensity = |E\u03c3|\u00b2 + |E\u03c0|\u00b2",
                "24: \u03a3 Intensity = |E\u03c3|\u00b2",
                "25: \u03a0 Intensity = |E\u03c0|\u00b2",
                "26: |K|",
                "27: K X",
                "28: K Y",
                "29: K Z",
                "30: S0-stokes = |E\u03c0|\u00b2 + |E\u03c3|\u00b2",
                "31: S1-stokes = |E\u03c0|\u00b2 - |E\u03c3|\u00b2",
                "32: S2-stokes = 2|E\u03c3||E\u03c0|cos(Phase \u03c3-Phase \u03c0)",
                "33: S3-stokes = 2|E\u03c3||E\u03c0|sin(Phase \u03c3-Phase \u03c0)",
                "34: Power = Intensity * Energy",
            ],
            sendSelectedValue=False,
            orientation="horizontal")

        gui.comboBox(general_box,
                     self,
                     "rays",
                     label="Rays",
                     labelWidth=250,
                     items=["All rays", "Good Only", "Lost Only"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        autosave_box = oasysgui.widgetBox(tab_gen,
                                          "Autosave",
                                          addSpace=True,
                                          orientation="vertical",
                                          height=85)

        gui.comboBox(autosave_box,
                     self,
                     "autosave",
                     label="Save automatically plot into file",
                     labelWidth=250,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal",
                     callback=self.set_autosave)

        self.autosave_box_1 = oasysgui.widgetBox(autosave_box,
                                                 "",
                                                 addSpace=False,
                                                 orientation="horizontal",
                                                 height=25)
        self.autosave_box_2 = oasysgui.widgetBox(autosave_box,
                                                 "",
                                                 addSpace=False,
                                                 orientation="horizontal",
                                                 height=25)

        self.le_autosave_file_name = oasysgui.lineEdit(
            self.autosave_box_1,
            self,
            "autosave_file_name",
            "File Name",
            labelWidth=100,
            valueType=str,
            orientation="horizontal")

        gui.button(self.autosave_box_1,
                   self,
                   "...",
                   callback=self.selectAutosaveFile)

        incremental_box = oasysgui.widgetBox(tab_gen,
                                             "Incremental Result",
                                             addSpace=True,
                                             orientation="vertical",
                                             height=120)

        gui.comboBox(incremental_box,
                     self,
                     "keep_result",
                     label="Keep Result",
                     labelWidth=250,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal",
                     callback=self.set_autosave)

        self.cb_autosave_partial_results = gui.comboBox(
            incremental_box,
            self,
            "autosave_partial_results",
            label="Save partial plots into file",
            labelWidth=250,
            items=["No", "Yes"],
            sendSelectedValue=False,
            orientation="horizontal")

        gui.button(incremental_box, self, "Clear", callback=self.clearResults)

        histograms_box = oasysgui.widgetBox(tab_gen,
                                            "Histograms settings",
                                            addSpace=True,
                                            orientation="vertical",
                                            height=90)

        oasysgui.lineEdit(histograms_box,
                          self,
                          "number_of_bins",
                          "Number of Bins",
                          labelWidth=250,
                          valueType=int,
                          orientation="horizontal")

        gui.comboBox(histograms_box,
                     self,
                     "is_conversion_active",
                     label="Is U.M. conversion active",
                     labelWidth=250,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.set_autosave()

        self.main_tabs = oasysgui.tabWidget(self.mainArea)
        plot_tab = oasysgui.createTabPage(self.main_tabs, "Plots")
        out_tab = oasysgui.createTabPage(self.main_tabs, "Output")

        self.image_box = gui.widgetBox(plot_tab,
                                       "Plot Result",
                                       addSpace=True,
                                       orientation="vertical")
        self.image_box.setFixedHeight(self.IMAGE_HEIGHT)
        self.image_box.setFixedWidth(self.IMAGE_WIDTH)

        self.shadow_output = oasysgui.textArea(height=580, width=800)

        out_box = gui.widgetBox(out_tab,
                                "System Output",
                                addSpace=True,
                                orientation="horizontal")
        out_box.layout().addWidget(self.shadow_output)

    def clearResults(self, interactive=True):
        if not interactive: proceed = True
        else: proceed = ConfirmDialog.confirmed(parent=self)

        if proceed:
            self.input_beam = ShadowBeam()
            self.cumulated_ticket = None
            self.plotted_ticket = None
            self.autosave_prog_id = 0
            if not self.autosave_file is None:
                self.autosave_file.close()
                self.autosave_file = None

            self.plot_canvas.clear()

    def set_XRange(self):
        self.xrange_box.setVisible(self.x_range == 1)
        self.xrange_box_empty.setVisible(self.x_range == 0)

    def set_ImagePlane(self):
        self.image_plane_box.setVisible(self.image_plane == 1)
        self.image_plane_box_empty.setVisible(self.image_plane == 0)

    def set_autosave(self):
        self.autosave_box_1.setVisible(self.autosave == 1)
        self.autosave_box_2.setVisible(self.autosave == 0)

        self.cb_autosave_partial_results.setEnabled(self.autosave == 1
                                                    and self.keep_result == 1)

    def selectAutosaveFile(self):
        self.le_autosave_file_name.setText(
            oasysgui.selectFileFromDialog(
                self,
                self.autosave_file_name,
                "Select File",
                file_extension_filter="HDF5 Files (*.hdf5 *.h5 *.hdf)"))

    def replace_fig(self, beam, var, xrange, title, xtitle, ytitle, xum):
        if self.plot_canvas is None:
            self.plot_canvas = ShadowPlot.DetailedHistoWidget(
                y_scale_factor=1.14)
            self.image_box.layout().addWidget(self.plot_canvas)

        try:
            if self.autosave == 1:
                if self.autosave_file is None:
                    self.autosave_file = ShadowPlot.HistogramHdf5File(
                        congruence.checkDir(self.autosave_file_name))
                elif self.autosave_file.filename != congruence.checkFileName(
                        self.autosave_file_name):
                    self.autosave_file.close()
                    self.autosave_file = ShadowPlot.HistogramHdf5File(
                        congruence.checkDir(self.autosave_file_name))

            if self.keep_result == 1:
                self.cumulated_ticket, last_ticket = self.plot_canvas.plot_histo(
                    beam,
                    var,
                    self.rays,
                    xrange,
                    self.weight_column_index,
                    title,
                    xtitle,
                    ytitle,
                    nbins=self.number_of_bins,
                    xum=xum,
                    conv=self.workspace_units_to_cm,
                    ticket_to_add=self.cumulated_ticket)

                self.plotted_ticket = self.cumulated_ticket

                if self.autosave == 1:
                    self.autosave_prog_id += 1
                    self.autosave_file.write_coordinates(self.cumulated_ticket)
                    dataset_name = self.weight_column.itemText(
                        self.weight_column_index)

                    self.autosave_file.add_histogram(self.cumulated_ticket,
                                                     dataset_name=dataset_name)

                    if self.autosave_partial_results == 1:
                        if last_ticket is None:
                            self.autosave_file.add_histogram(
                                self.cumulated_ticket,
                                plot_name="Histogram #" +
                                str(self.autosave_prog_id),
                                dataset_name=dataset_name)
                        else:
                            self.autosave_file.add_histogram(
                                last_ticket,
                                plot_name="Histogram #" +
                                str(self.autosave_prog_id),
                                dataset_name=dataset_name)

                    self.autosave_file.flush()
            else:
                ticket, _ = self.plot_canvas.plot_histo(
                    beam,
                    var,
                    self.rays,
                    xrange,
                    self.weight_column_index,
                    title,
                    xtitle,
                    ytitle,
                    nbins=self.number_of_bins,
                    xum=xum,
                    conv=self.workspace_units_to_cm)

                self.cumulated_ticket = None
                self.plotted_ticket = ticket

                if self.autosave == 1:
                    self.autosave_prog_id += 1
                    self.autosave_file.write_coordinates(ticket)
                    self.autosave_file.add_histogram(
                        ticket,
                        dataset_name=self.weight_column.itemText(
                            self.weight_column_index))
                    self.autosave_file.flush()

        except Exception as e:
            if not self.IS_DEVELOP:
                raise Exception(
                    "Data not plottable: No good rays or bad content")
            else:
                raise e

    def plot_histo(self, var_x, title, xtitle, ytitle, xum):
        beam_to_plot = self.input_beam._beam

        if self.image_plane == 1:
            new_shadow_beam = self.input_beam.duplicate(history=False)
            dist = 0.0

            if self.image_plane_rel_abs_position == 1:  # relative
                dist = self.image_plane_new_position
            else:  # absolute
                if self.input_beam.historySize() == 0:
                    historyItem = None
                else:
                    historyItem = self.input_beam.getOEHistory(
                        oe_number=self.input_beam._oe_number)

                if historyItem is None: image_plane = 0.0
                elif self.input_beam._oe_number == 0: image_plane = 0.0
                else: image_plane = historyItem._shadow_oe_end._oe.T_IMAGE

                dist = self.image_plane_new_position - image_plane

            self.retrace_beam(new_shadow_beam, dist)

            beam_to_plot = new_shadow_beam._beam

        xrange = self.get_range(beam_to_plot, var_x)

        self.replace_fig(beam_to_plot, var_x, xrange, title, xtitle, ytitle,
                         xum)

    def get_range(self, beam_to_plot, var_x):
        if self.x_range == 0:
            x_max = 0
            x_min = 0

            x, good_only = beam_to_plot.getshcol((var_x, 10))

            x_to_plot = copy.deepcopy(x)

            go = numpy.where(good_only == 1)
            lo = numpy.where(good_only != 1)

            if self.rays == 0:
                x_max = numpy.array(x_to_plot[0:], float).max()
                x_min = numpy.array(x_to_plot[0:], float).min()
            elif self.rays == 1:
                x_max = numpy.array(x_to_plot[go], float).max()
                x_min = numpy.array(x_to_plot[go], float).min()
            elif self.rays == 2:
                x_max = numpy.array(x_to_plot[lo], float).max()
                x_min = numpy.array(x_to_plot[lo], float).min()

            xrange = [x_min, x_max]
        else:
            congruence.checkLessThan(self.x_range_min, self.x_range_max,
                                     "X range min", "X range max")

            factor1 = ShadowPlot.get_factor(var_x, self.workspace_units_to_cm)

            xrange = [self.x_range_min / factor1, self.x_range_max / factor1]

        return xrange

    def save_results(self):
        if not self.plotted_ticket is None:
            try:
                file_name, _ = QtWidgets.QFileDialog.getSaveFileName(
                    self,
                    "Save Current Plot",
                    filter="HDF5 Files (*.hdf5 *.h5 *.hdf)")

                if not file_name is None and not file_name.strip() == "":
                    if not (file_name.endswith("hd5")
                            or file_name.endswith("hdf5")
                            or file_name.endswith("hdf")):
                        file_name += ".hdf5"

                    save_file = ShadowPlot.HistogramHdf5File(
                        congruence.checkDir(file_name))

                    save_file.write_coordinates(self.plotted_ticket)
                    dataset_name = self.weight_column.itemText(
                        self.weight_column_index)

                    save_file.add_histogram(self.plotted_ticket,
                                            dataset_name=dataset_name)

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

                if self.IS_DEVELOP: raise exception

    def plot_results(self):
        try:
            plotted = False

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            if self.trace_shadow:
                grabber = TTYGrabber()
                grabber.start()

            if ShadowCongruence.checkEmptyBeam(self.input_beam):
                ShadowPlot.set_conversion_active(self.getConversionActive())

                self.number_of_bins = congruence.checkPositiveNumber(
                    self.number_of_bins, "Number of Bins")

                x, auto_title, xum = self.get_titles()

                self.plot_histo(x,
                                title=self.title,
                                xtitle=auto_title,
                                ytitle="Number of Rays",
                                xum=xum)

                plotted = True
            if self.trace_shadow:
                grabber.stop()

                for row in grabber.ttyData:
                    self.writeStdOut(row)

            time.sleep(
                0.5
            )  # prevents a misterious dead lock in the Orange cycle when refreshing the histogram

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

            if self.IS_DEVELOP: raise exception

    def get_titles(self):
        auto_title = self.x_column.currentText().split(":", 2)[1]

        xum = auto_title + " "
        self.title = auto_title
        x = self.x_column_index + 1

        if x == 1 or x == 2 or x == 3:
            if self.getConversionActive():
                xum = xum + "[" + u"\u03BC" + "m]"
                auto_title = auto_title + " [$\mu$m]"
            else:
                xum = xum + " [" + self.workspace_units_label + "]"
                auto_title = auto_title + " [" + self.workspace_units_label + "]"
        elif x == 4 or x == 5 or x == 6:
            if self.getConversionActive():
                xum = xum + "[" + u"\u03BC" + "rad]"
                auto_title = auto_title + " [$\mu$rad]"
            else:
                xum = xum + " [rad]"
                auto_title = auto_title + " [rad]"
        elif x == 11:
            xum = xum + "[eV]"
            auto_title = auto_title + " [eV]"
        elif x == 13:
            xum = xum + " [" + self.workspace_units_label + "]"
            auto_title = auto_title + " [" + self.workspace_units_label + "]"
        elif x == 14:
            xum = xum + "[rad]"
            auto_title = auto_title + " [rad]"
        elif x == 15:
            xum = xum + "[rad]"
            auto_title = auto_title + " [rad]"
        elif x == 19:
            xum = xum + "[Å]"
            auto_title = auto_title + " [Å]"
        elif x == 20:
            xum = xum + " [" + self.workspace_units_label + "]"
            auto_title = auto_title + " [" + self.workspace_units_label + "]"
        elif x == 21:
            xum = xum + "[rad]"
            auto_title = auto_title + " [rad]"
        elif x >= 25 and x <= 28:
            xum = xum + "[Å-1]"
            auto_title = auto_title + " [Å-1]"

        return x, auto_title, xum

    def setBeam(self, beam):
        if ShadowCongruence.checkEmptyBeam(beam):
            if ShadowCongruence.checkGoodBeam(beam):
                self.input_beam = beam

                if self.is_automatic_run:
                    self.plot_results()
            else:
                QtWidgets.QMessageBox.critical(
                    self, "Error",
                    "Data not displayable: No good rays or bad content",
                    QtWidgets.QMessageBox.Ok)

    def writeStdOut(self, text):
        cursor = self.shadow_output.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.shadow_output.setTextCursor(cursor)
        self.shadow_output.ensureCursorVisible()

    def retrace_beam(self, new_shadow_beam, dist):
        new_shadow_beam._beam.retrace(dist)

    def getConversionActive(self):
        return self.is_conversion_active == 1
class OWdabam_height_profile(OWWidget):
    name = "DABAM Height Profile"
    id = "dabam_height_profile"
    description = "Calculation of mirror surface error profile"
    icon = "icons/dabam.png"
    author = "Luca Rebuffi"
    maintainer_email = "[email protected]; [email protected]"
    priority = 2
    category = ""
    keywords = ["dabam_height_profile"]

    outputs = [{
        "name": "PreInput",
        "type": WiserPreInputData,
        "doc": "PreInput",
        "id": "PreInput"
    }]

    want_main_area = 1
    want_control_area = 1

    MAX_WIDTH = 1320
    MAX_HEIGHT = 700

    IMAGE_WIDTH = 860
    IMAGE_HEIGHT = 645

    CONTROL_AREA_WIDTH = 405
    TABS_AREA_HEIGHT = 618

    xx = None
    yy = None

    entry_number = Setting(1)

    shape = Setting(0)
    slope_error_from = Setting(0.0)
    slope_error_to = Setting(1.5)
    dimension_y_from = Setting(0.0)
    dimension_y_to = Setting(200.0)

    use_undetrended = Setting(0)

    center_y = Setting(1)
    modify_y = Setting(0)
    new_length = Setting(200.0)
    filler_value = Setting(0.0)

    renormalize_y = Setting(1)
    error_type_y = Setting(0)
    rms_y = Setting(0.9)

    dabam_profile_index = Setting(1)

    heigth_profile_file_name = Setting('mirror.dat')

    tab = []

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

        self.runaction = widget.OWAction("Calculate Height Profile", self)
        self.runaction.triggered.connect(self.calculate_heigth_profile_ni)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Generate Height Profile File", self)
        self.runaction.triggered.connect(self.generate_heigth_profile_file_ni)
        self.addAction(self.runaction)

        geom = QApplication.desktop().availableGeometry()
        self.setGeometry(
            QRect(round(geom.width() * 0.05), round(geom.height() * 0.05),
                  round(min(geom.width() * 0.98, self.MAX_WIDTH)),
                  round(min(geom.height() * 0.95, self.MAX_HEIGHT))))

        self.setMaximumHeight(self.geometry().height())
        self.setMaximumWidth(self.geometry().width())

        # DABAM INITIALIZATION
        self.server = dabam.dabam()
        self.server.set_input_silent(True)

        gui.separator(self.controlArea)

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        button = gui.button(button_box,
                            self,
                            "Calculate Height\nProfile",
                            callback=self.calculate_heigth_profile)
        button.setFixedHeight(45)

        button = gui.button(button_box,
                            self,
                            "Generate Height\nProfile File",
                            callback=self.generate_heigth_profile_file)
        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.setFixedWidth(150)

        button = gui.button(button_box,
                            self,
                            "Reset Fields",
                            callback=self.call_reset_settings)
        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)

        gui.separator(self.controlArea)

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

        tab_input = oasysgui.createTabPage(tabs_setting,
                                           "DABAM Search Setting")
        tab_gener = oasysgui.createTabPage(tabs_setting,
                                           "DABAM Generation Setting")
        tab_out = oasysgui.createTabPage(tabs_setting, "Output")

        manual_box = oasysgui.widgetBox(tab_input,
                                        "Manual Entry",
                                        addSpace=True,
                                        orientation="vertical")

        oasysgui.lineEdit(manual_box,
                          self,
                          "entry_number",
                          "Entry Number",
                          labelWidth=300,
                          valueType=int,
                          orientation="horizontal")

        gui.separator(manual_box)

        button = gui.button(manual_box,
                            self,
                            "Retrieve Profile",
                            callback=self.retrieve_profile)
        button.setFixedHeight(35)
        button.setFixedWidth(self.CONTROL_AREA_WIDTH - 35)

        input_box = oasysgui.widgetBox(tab_input,
                                       "Search Parameters",
                                       addSpace=True,
                                       orientation="vertical")

        gui.comboBox(input_box,
                     self,
                     "shape",
                     label="Mirror Shape",
                     labelWidth=300,
                     items=[
                         "All", "Plane", "Cylindrical", "Elliptical",
                         "Toroidal", "Spherical"
                     ],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.separator(input_box)

        input_box_1 = oasysgui.widgetBox(input_box,
                                         "",
                                         addSpace=True,
                                         orientation="horizontal")

        oasysgui.lineEdit(input_box_1,
                          self,
                          "slope_error_from",
                          "Slope Error From (" + u"\u03BC" + "rad)",
                          labelWidth=150,
                          valueType=float,
                          orientation="horizontal")
        oasysgui.lineEdit(input_box_1,
                          self,
                          "slope_error_to",
                          "To (" + u"\u03BC" + "rad)",
                          labelWidth=60,
                          valueType=float,
                          orientation="horizontal")

        input_box_2 = oasysgui.widgetBox(input_box,
                                         "",
                                         addSpace=True,
                                         orientation="horizontal")

        self.le_dimension_y_from = oasysgui.lineEdit(input_box_2,
                                                     self,
                                                     "dimension_y_from",
                                                     "Mirror Length From",
                                                     labelWidth=150,
                                                     valueType=float,
                                                     orientation="horizontal")
        self.le_dimension_y_to = oasysgui.lineEdit(input_box_2,
                                                   self,
                                                   "dimension_y_to",
                                                   "To",
                                                   labelWidth=60,
                                                   valueType=float,
                                                   orientation="horizontal")

        table_box = oasysgui.widgetBox(tab_input,
                                       "Search Results",
                                       addSpace=True,
                                       orientation="vertical",
                                       height=250)

        self.overlay_search = Overlay(table_box, self.search_profiles)
        self.overlay_search.hide()

        button = gui.button(input_box,
                            self,
                            "Search",
                            callback=self.overlay_search.show)
        button.setFixedHeight(35)
        button.setFixedWidth(self.CONTROL_AREA_WIDTH - 35)

        gui.comboBox(table_box,
                     self,
                     "use_undetrended",
                     label="Use Undetrended Profile",
                     labelWidth=300,
                     items=["No", "Yes"],
                     callback=self.table_item_clicked,
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.separator(table_box)

        self.scrollarea = QScrollArea()
        self.scrollarea.setMinimumWidth(self.CONTROL_AREA_WIDTH - 35)

        table_box.layout().addWidget(self.scrollarea,
                                     alignment=Qt.AlignHCenter)

        self.table = QTableWidget(1, 5)
        self.table.setStyleSheet("background-color: #FBFBFB;")
        self.table.setAlternatingRowColors(True)
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
        self.table.verticalHeader().setVisible(False)

        self.table.setColumnWidth(0, 40)
        self.table.setColumnWidth(1, 70)
        self.table.setColumnWidth(2, 70)
        self.table.setColumnWidth(3, 85)
        self.table.setColumnWidth(4, 80)

        self.table.resizeRowsToContents()
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.itemClicked.connect(self.table_item_clicked)

        self.scrollarea.setWidget(self.table)
        self.scrollarea.setWidgetResizable(1)

        output_profile_box = oasysgui.widgetBox(
            tab_gener,
            "Surface Generation Parameters",
            addSpace=True,
            orientation="vertical",
            height=370)

        gui.comboBox(output_profile_box,
                     self,
                     "center_y",
                     label="Center Profile in the middle of O.E.",
                     labelWidth=300,
                     items=["No", "Yes"],
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.separator(output_profile_box)

        gui.comboBox(output_profile_box,
                     self,
                     "modify_y",
                     label="Modify Length?",
                     labelWidth=150,
                     items=[
                         "No", "Rescale to new length",
                         "Fit to new length (fill or cut)"
                     ],
                     callback=self.set_ModifyY,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.modify_box_1 = oasysgui.widgetBox(output_profile_box,
                                               "",
                                               addSpace=False,
                                               orientation="vertical",
                                               height=60)

        self.modify_box_2 = oasysgui.widgetBox(output_profile_box,
                                               "",
                                               addSpace=False,
                                               orientation="vertical",
                                               height=60)
        self.le_new_length_1 = oasysgui.lineEdit(self.modify_box_2,
                                                 self,
                                                 "new_length",
                                                 "New Length",
                                                 labelWidth=300,
                                                 valueType=float,
                                                 orientation="horizontal")

        self.modify_box_3 = oasysgui.widgetBox(output_profile_box,
                                               "",
                                               addSpace=False,
                                               orientation="vertical",
                                               height=60)
        self.le_new_length_2 = oasysgui.lineEdit(self.modify_box_3,
                                                 self,
                                                 "new_length",
                                                 "New Length",
                                                 labelWidth=300,
                                                 valueType=float,
                                                 orientation="horizontal")
        oasysgui.lineEdit(self.modify_box_3,
                          self,
                          "filler_value",
                          "Filler Value (if new length > profile length) [nm]",
                          labelWidth=300,
                          valueType=float,
                          orientation="horizontal")

        self.set_ModifyY()

        gui.comboBox(output_profile_box,
                     self,
                     "renormalize_y",
                     label="Renormalize Length Profile to different RMS",
                     labelWidth=300,
                     items=["No", "Yes"],
                     callback=self.set_RenormalizeY,
                     sendSelectedValue=False,
                     orientation="horizontal")

        self.output_profile_box_1 = oasysgui.widgetBox(output_profile_box,
                                                       "",
                                                       addSpace=False,
                                                       orientation="vertical",
                                                       height=60)
        self.output_profile_box_2 = oasysgui.widgetBox(output_profile_box,
                                                       "",
                                                       addSpace=False,
                                                       orientation="vertical",
                                                       height=60)

        gui.comboBox(
            self.output_profile_box_1,
            self,
            "error_type_y",
            label="Normalization to",
            labelWidth=270,
            items=["Figure Error (nm)", "Slope Error (" + u"\u03BC" + "rad)"],
            sendSelectedValue=False,
            orientation="horizontal")

        oasysgui.lineEdit(self.output_profile_box_1,
                          self,
                          "rms_y",
                          "Rms Value",
                          labelWidth=300,
                          valueType=float,
                          orientation="horizontal")

        self.set_RenormalizeY()

        output_box = oasysgui.widgetBox(tab_gener,
                                        "Outputs",
                                        addSpace=True,
                                        orientation="vertical")

        select_file_box = oasysgui.widgetBox(output_box,
                                             "",
                                             addSpace=True,
                                             orientation="horizontal")

        self.le_heigth_profile_file_name = oasysgui.lineEdit(
            select_file_box,
            self,
            "heigth_profile_file_name",
            "Output File Name",
            labelWidth=120,
            valueType=str,
            orientation="horizontal")

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

        self.shadow_output = oasysgui.textArea(height=400)

        out_box = oasysgui.widgetBox(tab_out,
                                     "System Output",
                                     addSpace=True,
                                     orientation="horizontal",
                                     height=500)
        out_box.layout().addWidget(self.shadow_output)

        gui.rubber(self.controlArea)

        self.initializeTabs()

        gui.rubber(self.mainArea)

        self.overlay_search.raise_()

    def resizeEvent(self, event):
        self.overlay_search.resize(self.CONTROL_AREA_WIDTH - 15, 290)
        event.accept()

    def after_change_workspace_units(self):
        self.si_to_user_units = 1e2 / self.workspace_units_to_cm

        self.horHeaders = [
            "Entry", "Shape", "Length\n[" + self.workspace_units_label + "]",
            "Heights St.Dev.\n[nm]", "Slopes St.Dev.\n[" + u"\u03BC" + "rad]"
        ]
        self.table.setHorizontalHeaderLabels(self.horHeaders)
        self.plot_canvas[0].setGraphXLabel("Y [" + self.workspace_units_label +
                                           "]")
        self.plot_canvas[1].setGraphXLabel("Y [" + self.workspace_units_label +
                                           "]")
        self.plot_canvas[5].setGraphXLabel("Y [" + self.workspace_units_label +
                                           "]")

        label = self.le_dimension_y_from.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_dimension_y_to.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_new_length_1.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_new_length_2.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

    def initializeTabs(self):
        self.tabs = oasysgui.tabWidget(self.mainArea)

        self.tab = [
            oasysgui.createTabPage(self.tabs, "Info"),
            oasysgui.createTabPage(self.tabs, "Heights Profile"),
            oasysgui.createTabPage(self.tabs, "Slopes Profile"),
            oasysgui.createTabPage(self.tabs, "PSD Heights"),
            oasysgui.createTabPage(self.tabs, "CSD Heights"),
            oasysgui.createTabPage(self.tabs, "ACF"),
            oasysgui.createTabPage(self.tabs, "Generated 1D Profile"),
        ]

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

        self.plot_canvas = [None, None, None, None, None, None]

        self.plot_canvas[0] = oasysgui.plotWindow(roi=False,
                                                  control=False,
                                                  position=True)
        self.plot_canvas[0].setDefaultPlotLines(True)
        self.plot_canvas[0].setActiveCurveColor(color='blue')
        self.plot_canvas[0].setGraphYLabel("Z [nm]")
        self.plot_canvas[0].setGraphTitle("Heights Profile")
        self.plot_canvas[0].setInteractiveMode(mode='zoom')

        self.plot_canvas[1] = oasysgui.plotWindow(roi=False,
                                                  control=False,
                                                  position=True)
        self.plot_canvas[1].setDefaultPlotLines(True)
        self.plot_canvas[1].setActiveCurveColor(color='blue')
        self.plot_canvas[1].setGraphYLabel("Zp [$\mu$rad]")
        self.plot_canvas[1].setGraphTitle("Slopes Profile")
        self.plot_canvas[1].setInteractiveMode(mode='zoom')

        self.plot_canvas[2] = oasysgui.plotWindow(roi=False,
                                                  control=False,
                                                  position=True)
        self.plot_canvas[2].setDefaultPlotLines(True)
        self.plot_canvas[2].setActiveCurveColor(color='blue')
        self.plot_canvas[2].setGraphXLabel("f [m^-1]")
        self.plot_canvas[2].setGraphYLabel("PSD [m^3]")
        self.plot_canvas[2].setGraphTitle(
            "Power Spectral Density of Heights Profile")
        self.plot_canvas[2].setInteractiveMode(mode='zoom')
        self.plot_canvas[2].setXAxisLogarithmic(True)
        self.plot_canvas[2].setYAxisLogarithmic(True)

        self.plot_canvas[3] = oasysgui.plotWindow(roi=False,
                                                  control=False,
                                                  position=True)
        self.plot_canvas[3].setDefaultPlotLines(True)
        self.plot_canvas[3].setActiveCurveColor(color='blue')
        self.plot_canvas[3].setGraphXLabel("f [m^-1]")
        self.plot_canvas[3].setGraphYLabel("CSD [m^3]")
        self.plot_canvas[3].setGraphTitle(
            "Cumulative Spectral Density of Heights Profile")
        self.plot_canvas[3].setInteractiveMode(mode='zoom')
        self.plot_canvas[3].setXAxisLogarithmic(True)

        self.plot_canvas[4] = oasysgui.plotWindow(roi=False,
                                                  control=False,
                                                  position=True)
        self.plot_canvas[4].setDefaultPlotLines(True)
        self.plot_canvas[4].setActiveCurveColor(color='blue')
        self.plot_canvas[4].setGraphXLabel("Length [m]")
        self.plot_canvas[4].setGraphYLabel("ACF")
        self.plot_canvas[4].setGraphTitle(
            "Autocovariance Function of Heights Profile")
        self.plot_canvas[4].setInteractiveMode(mode='zoom')

        self.plot_canvas[5] = oasysgui.plotWindow(roi=False,
                                                  control=False,
                                                  position=True)
        self.plot_canvas[5].setDefaultPlotLines(True)
        self.plot_canvas[5].setActiveCurveColor(color='blue')
        self.plot_canvas[5].setGraphYLabel("Z [nm]")
        self.plot_canvas[5].setGraphTitle("Heights Profile")
        self.plot_canvas[5].setInteractiveMode(mode='zoom')

        self.profileInfo = oasysgui.textArea(height=self.IMAGE_HEIGHT - 5,
                                             width=400)

        profile_box = oasysgui.widgetBox(self.tab[0],
                                         "",
                                         addSpace=True,
                                         orientation="horizontal",
                                         height=self.IMAGE_HEIGHT,
                                         width=410)
        profile_box.layout().addWidget(self.profileInfo)

        for index in range(0, 6):
            self.tab[index + 1].layout().addWidget(self.plot_canvas[index])

        self.tabs.setCurrentIndex(1)

    def plot_dabam_graph(self,
                         plot_canvas_index,
                         curve_name,
                         x_values,
                         y_values,
                         xtitle,
                         ytitle,
                         title="",
                         color='blue',
                         replace=True):
        self.plot_canvas[plot_canvas_index].addCurve(
            x_values,
            y_values,
            curve_name,
            symbol='',
            color=color,
            replace=replace)  #'+', '^', ','
        self.plot_canvas[plot_canvas_index].setGraphTitle(title)
        self.plot_canvas[plot_canvas_index].setGraphXLabel(xtitle)
        self.plot_canvas[plot_canvas_index].setGraphYLabel(ytitle)
        self.plot_canvas[plot_canvas_index].replot()

    def set_ModifyY(self):
        self.modify_box_1.setVisible(self.modify_y == 0)
        self.modify_box_2.setVisible(self.modify_y == 1)
        self.modify_box_3.setVisible(self.modify_y == 2)

    def set_RenormalizeY(self):
        self.output_profile_box_1.setVisible(self.renormalize_y == 1)

    def table_item_clicked(self):
        if self.table.selectionModel().hasSelection():
            if not self.table.rowCount() == 0:
                if not self.table.item(0, 0) is None:
                    row = self.table.selectionModel().selectedRows()[0].row()
                    self.entry_number = int(self.table.item(row, 0).text())

                    self.retrieve_profile()

    def retrieve_profile(self):
        try:
            if self.entry_number is None or self.entry_number <= 0:
                raise Exception(
                    "Entry number should be a strictly positive integer number"
                )

            self.server.load(self.entry_number)
            self.profileInfo.setText(self.server.info_profiles())
            title0 = "Heights Profile. St.Dev.=%.3f nm" % (
                self.server.stdev_profile_heights() * 1e9)
            title1 = "Slopes Profile. St.Dev.=%.3f $\mu$rad" % (
                self.server.stdev_profile_slopes() * 1e6)
            if self.use_undetrended == 0:
                self.plot_dabam_graph(0,
                                      "heights_profile",
                                      self.si_to_user_units * self.server.y,
                                      1e9 * self.server.zHeights,
                                      "Y [" + self.workspace_units_label + "]",
                                      "Z [nm]",
                                      title=title0)
                self.plot_dabam_graph(1,
                                      "slopes_profile",
                                      self.si_to_user_units * self.server.y,
                                      1e6 * self.server.zSlopes,
                                      "Y [" + self.workspace_units_label + "]",
                                      "Zp [$\mu$rad]",
                                      title=title1)
            else:
                self.plot_dabam_graph(0,
                                      "heights_profile",
                                      self.si_to_user_units * self.server.y,
                                      1e9 * self.server.zHeightsUndetrended,
                                      "Y [" + self.workspace_units_label + "]",
                                      "Z [nm]",
                                      title=title0)
                self.plot_dabam_graph(1,
                                      "slopes_profile",
                                      self.si_to_user_units * self.server.y,
                                      1e6 * self.server.zSlopesUndetrended,
                                      "Y [" + self.workspace_units_label + "]",
                                      "Zp [$\mu$rad]",
                                      title=title1)
            y = self.server.f**(self.server.powerlaw["hgt_pendent"]
                                ) * 10**self.server.powerlaw["hgt_shift"]
            i0 = self.server.powerlaw["index_from"]
            i1 = self.server.powerlaw["index_to"]
            beta = -self.server.powerlaw["hgt_pendent"]
            self.plot_dabam_graph(
                2,
                "psd_heights_2",
                self.server.f,
                self.server.psdHeights,
                "f [m^-1]",
                "PSD [m^3]",
                title=
                "Power Spectral Density of Heights Profile (beta=%.2f,Df=%.2f)"
                % (beta, (5 - beta) / 2))
            self.plot_dabam_graph(2,
                                  "psd_heights_1",
                                  self.server.f,
                                  y,
                                  "f [m^-1]",
                                  "PSD [m^3]",
                                  color='green',
                                  replace=False)
            self.plot_dabam_graph(2,
                                  "psd_heights_3",
                                  self.server.f[i0:i1],
                                  y[i0:i1],
                                  "f [m^-1]",
                                  "PSD [m^3]",
                                  color='red',
                                  replace=False)
            self.plot_dabam_graph(3, "csd", self.server.f,
                                  self.server.csd_heights(), "f [m^-1]",
                                  "CSD [m^3]")
            c1, c2, c3 = dabam.autocorrelationfunction(self.server.y,
                                                       self.server.zHeights)
            self.plot_dabam_graph(
                4,
                "acf",
                c1[0:-1],
                c2,
                "Length [m]",
                "Heights Autocovariance",
                title=
                "Autocovariance Function of Heights Profile.\nAutocorrelation Length (ACF=0.5)=%.3f m"
                % (c3))
            # surface error removal
            if not self.yy is None and not self.xx is None:
                self.xx = None
                self.yy = None
                self.plot_dabam_graph(5, "heights_profile_generated",
                                      numpy.zeros(1), numpy.zeros(1),
                                      "Y [" + self.workspace_units_label + "]",
                                      "Z [nm]")

            if (self.tabs.currentIndex() == 6): self.tabs.setCurrentIndex(1)

        except Exception as exception:
            QMessageBox.critical(self, "Error", exception.args[0],
                                 QMessageBox.Ok)

            #raise exception

    def search_profiles(self):
        try:
            self.table.itemClicked.disconnect(self.table_item_clicked)
            self.table.clear()

            row_count = self.table.rowCount()
            for n in range(0, row_count):
                self.table.removeRow(0)

            self.table.setHorizontalHeaderLabels(self.horHeaders)

            profiles = dabam.dabam_summary_dictionary(
                surface=self.get_dabam_shape(),
                slp_err_from=self.slope_error_from * 1e-6,
                slp_err_to=self.slope_error_to * 1e-6,
                length_from=self.dimension_y_from / self.si_to_user_units,
                length_to=self.dimension_y_to / self.si_to_user_units)

            for index in range(0, len(profiles)):
                self.table.insertRow(0)

            for index in range(0, len(profiles)):
                table_item = QTableWidgetItem(str(profiles[index]["entry"]))
                table_item.setTextAlignment(Qt.AlignCenter)
                self.table.setItem(index, 0, table_item)
                table_item = QTableWidgetItem(str(profiles[index]["surface"]))
                table_item.setTextAlignment(Qt.AlignLeft)
                self.table.setItem(index, 1, table_item)
                table_item = QTableWidgetItem(
                    str(
                        numpy.round(
                            profiles[index]["length"] * self.si_to_user_units,
                            3)))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(index, 2, table_item)
                table_item = QTableWidgetItem(
                    str(numpy.round(profiles[index]["hgt_err"] * 1e9, 3)))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(index, 3, table_item)
                table_item = QTableWidgetItem(
                    str(numpy.round(profiles[index]["slp_err"] * 1e6, 3)))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(index, 4, table_item)

            self.table.setHorizontalHeaderLabels(self.horHeaders)
            self.table.resizeRowsToContents()
            self.table.setSelectionBehavior(QAbstractItemView.SelectRows)

            self.table.itemClicked.connect(self.table_item_clicked)

            self.overlay_search.hide()

        except Exception as exception:
            self.overlay_search.hide()

            QMessageBox.critical(self, "Error", exception.args[0],
                                 QMessageBox.Ok)

    def get_dabam_shape(self):
        if self.shape == 0: return None
        elif self.shape == 1: return "plane"
        elif self.shape == 2: return "cylindrical"
        elif self.shape == 3: return "elliptical"
        elif self.shape == 4: return "toroidal"
        elif self.shape == 5: return "spherical"

    def calculate_heigth_profile_ni(self):
        self.calculate_heigth_profile(not_interactive_mode=True)

    def calculate_heigth_profile(self, not_interactive_mode=False):
        import matplotlib
        print(matplotlib.__version__)

        try:
            if self.server.y is None: raise Exception("No Profile Selected")

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            # PREVENTS CRASH WITH PYQT5
            if not not_interactive_mode: self.tabs.setCurrentIndex(6)

            if self.modify_y == 2:
                profile_1D_y_x_temp = self.si_to_user_units * self.server.y
                if self.use_undetrended == 0:
                    profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeights
                else:
                    profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeightsUndetrended

                first_coord = profile_1D_y_x_temp[0]
                second_coord = profile_1D_y_x_temp[1]
                last_coord = profile_1D_y_x_temp[-1]
                step = numpy.abs(second_coord - first_coord)
                length = numpy.abs(last_coord - first_coord)
                n_points_old = len(profile_1D_y_x_temp)

                if self.new_length > length:
                    difference = self.new_length - length

                    n_added_points = int(difference / step)
                    if difference % step == 0:
                        n_added_points += 1
                    if n_added_points % 2 != 0:
                        n_added_points += 1

                    profile_1D_y_x = numpy.arange(n_added_points +
                                                  n_points_old) * step
                    profile_1D_y_y = numpy.ones(
                        n_added_points + n_points_old
                    ) * self.filler_value * 1e-9 * self.si_to_user_units
                    profile_1D_y_y[int(n_added_points / 2):n_points_old +
                                   int(n_added_points /
                                       2)] = profile_1D_y_y_temp
                elif self.new_length < length:
                    difference = length - self.new_length

                    n_removed_points = int(difference / step)
                    if difference % step == 0:
                        n_removed_points -= 1
                    if n_removed_points % 2 != 0:
                        n_removed_points -= 1

                    if n_removed_points >= 2:
                        profile_1D_y_x = profile_1D_y_x_temp[0:(
                            n_points_old - n_removed_points)]
                        profile_1D_y_y = profile_1D_y_y_temp[(
                            int(n_removed_points / 2) -
                            1):(n_points_old - int(n_removed_points / 2) - 1)]

                    else:
                        profile_1D_y_x = profile_1D_y_x_temp
                        profile_1D_y_y = profile_1D_y_y_temp
                else:
                    profile_1D_y_x = profile_1D_y_x_temp
                    profile_1D_y_y = profile_1D_y_y_temp

            else:
                if self.modify_y == 0:
                    profile_1D_y_x = self.si_to_user_units * self.server.y
                elif self.modify_y == 1:
                    scale_factor_y = self.new_length / (
                        self.si_to_user_units *
                        (max(self.server.y) - min(self.server.y)))
                    profile_1D_y_x = self.si_to_user_units * self.server.y * scale_factor_y

                if self.use_undetrended == 0:
                    profile_1D_y_y = self.si_to_user_units * self.server.zHeights
                else:
                    profile_1D_y_y = self.si_to_user_units * self.server.zHeightsUndetrended

            if self.center_y:
                first_coord = profile_1D_y_x[0]
                last_coord = profile_1D_y_x[-1]
                length = numpy.abs(last_coord - first_coord)

                profile_1D_y_x_temp = numpy.linspace(-length / 2, length / 2,
                                                     len(profile_1D_y_x))

                profile_1D_y_x = profile_1D_y_x_temp

            if self.renormalize_y == 0:
                rms_y = None
            else:
                if self.error_type_y == profiles_simulation.FIGURE_ERROR:
                    rms_y = self.si_to_user_units * self.rms_y * 1e-9  # from nm to user units

                    profile_1D_y_y = profile_1D_y_y / profile_1D_y_y.std(
                    ) * rms_y
                else:
                    rms_y = self.rms_y * 1e-6  # from urad to rad

                    yslopes = numpy.gradient(
                        profile_1D_y_y, profile_1D_y_x[1] - profile_1D_y_x[0])
                    profile_1D_y_y = profile_1D_y_y / yslopes.std() * rms_y

            self.xx = profile_1D_y_x
            self.yy = profile_1D_y_y

            x_to_plot = self.xx
            y_to_plot = self.yy * 1e9 / self.si_to_user_units

            ny = len(self.yy)
            slope = numpy.zeros(ny)
            for i in range(ny - 1):
                step = self.xx[i + 1] - self.xx[i]
                slope[i] = numpy.arctan((self.yy[i + 1] - self.yy[i]) / step)
            slope[ny - 1] = slope[ny - 2]

            title = ' Slope error rms  : %f $\mu$rad' % (slope.std() * 1e6) + '\n' + \
                    ' Figure error rms : %f nm' % (round(self.yy.std()* 1e9 / self.si_to_user_units, 6))

            self.plot_dabam_graph(5,
                                  "heights_profile_generated",
                                  x_to_plot,
                                  y_to_plot,
                                  "Y [" + self.workspace_units_label + "]",
                                  "Z [nm]",
                                  title=title)

            if not not_interactive_mode:
                QMessageBox.information(
                    self, "QMessageBox.information()",
                    "Height Profile calculated: if the result is satisfactory,\nclick \'Generate Height Profile File\' to complete the operation ",
                    QMessageBox.Ok)
        except Exception as exception:
            QMessageBox.critical(self, "Error", exception.args[0],
                                 QMessageBox.Ok)

            #raise exception

    def generate_heigth_profile_file_ni(self):
        self.generate_heigth_profile_file(not_interactive_mode=True)

    def generate_heigth_profile_file(self, not_interactive_mode=False):
        if not self.yy is None and not self.xx is None:
            try:
                congruence.checkDir(self.heigth_profile_file_name)

                sys.stdout = EmittingStream(textWritten=self.writeStdOut)
                numpy.savetxt(self.heigth_profile_file_name, self.yy)

                QMessageBox.information(
                    self, "QMessageBox.information()", "Height Profile file " +
                    self.heigth_profile_file_name + " written on disk",
                    QMessageBox.Ok)

                self.send(
                    "PreInput",
                    WiserPreInputData(
                        figure_error_file=self.heigth_profile_file_name,
                        figure_error_step=numpy.abs(self.xx[1] - self.xx[0]),
                        figure_user_units_to_m=self.workspace_units_to_m))
            except Exception as exception:
                QMessageBox.critical(self, "Error", exception.args[0],
                                     QMessageBox.Ok)

    def call_reset_settings(self):
        if ConfirmDialog.confirmed(parent=self,
                                   message="Confirm Reset of the Fields?"):
            try:
                self.resetSettings()
            except:
                pass

    def check_fields(self):
        if self.modify_y == 1 or self.modify_y == 2:
            self.new_length = congruence.checkStrictlyPositiveNumber(
                self.new_length, "New Length")

        if self.renormalize_y == 1:
            self.rms_y = congruence.checkPositiveNumber(self.rms_y, "Rms Y")

        congruence.checkDir(self.heigth_profile_file_name)

    def writeStdOut(self, text):
        cursor = self.shadow_output.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.shadow_output.setTextCursor(cursor)
        self.shadow_output.ensureCursorVisible()

    def selectFile(self):
        self.le_heigth_profile_file_name.setText(
            oasysgui.selectFileFromDialog(
                self,
                self.heigth_profile_file_name,
                "Select Output File",
                file_extension_filter="Data Files (*.dat)"))
Exemplo n.º 27
0
class OWxcrosssec(XoppyWidget):
    name = "CrossSec"
    id = "orange.widgets.dataxcrosssec"
    description = "X-ray Matter Cross Sections"
    icon = "icons/xoppy_xcrosssec.png"
    priority = 19
    category = ""
    keywords = ["xoppy", "xcrosssec"]

    MAT_FLAG = Setting(0)
    MAT_LIST = Setting(0)
    DESCRIPTOR = Setting("Si")
    DENSITY = Setting(1.0)
    CALCULATE = Setting(1)
    GRID = Setting(0)
    GRIDSTART = Setting(100.0)
    GRIDEND = Setting(10000.0)
    GRIDN = Setting(200)
    UNIT = Setting(0)
    DUMP_TO_FILE = Setting(0)  # No
    FILE_NAME = Setting("CrossSec.dat")

    xtitle = None
    ytitle = None

    def build_gui(self):

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

        idx = -1

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(
            box1,
            self,
            "MAT_FLAG",
            label=self.unitLabels()[idx],
            addSpace=False,
            items=['Element(formula)', 'Mixture(formula)', 'Mixture(table)'],
            valueType=int,
            orientation="horizontal",
            labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

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

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

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

        #widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "CALCULATE",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'Total', 'PhotoElectric', 'Rayleigh', 'Compton',
                         'Total-Rayleigh'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "GRID",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Standard', 'User defined', 'Single Value'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

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

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

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

        #widget index 10
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "UNIT",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=[
                         'barn/atom [Cross Section] *see help*',
                         'cm^2 [Cross Section] *see help*',
                         'cm^2/g [Mass abs coef]', 'cm^-1 [Linear abs coef]'
                     ],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=130)
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 11
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "DUMP_TO_FILE",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     items=["No", "Yes"],
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 12
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "FILE_NAME",
                     label=self.unitLabels()[idx],
                     addSpace=True)
        self.show_at(self.unitFlags()[idx], box1)

        gui.rubber(self.controlArea)

    def unitLabels(self):
        return [
            'material', 'table', 'formula', 'density', 'Cross section',
            'Energy [eV] grid:', 'Starting Energy [eV]: ', 'To: ',
            'Number of points', 'Units', 'Dump to file', 'File name'
        ]

    def unitFlags(self):
        return [
            'True', 'self.MAT_FLAG  ==  2', 'self.MAT_FLAG  <=  1 ',
            'self.MAT_FLAG  ==  1  &  self.UNIT  ==  3', 'True', 'True',
            'self.GRID  !=  0', 'self.GRID  ==  1', 'self.GRID  ==  1', 'True',
            'True', 'self.DUMP_TO_FILE == 1'
        ]

    def get_help_name(self):
        return 'crosssec'

    def check_fields(self):
        self.DESCRIPTOR = congruence.checkEmptyString(self.DESCRIPTOR,
                                                      "formula")
        if self.MAT_FLAG == 1:
            self.DENSITY = congruence.checkStrictlyPositiveNumber(
                self.DENSITY, "density")

        if self.GRID > 0:
            self.GRIDSTART = congruence.checkPositiveNumber(
                self.GRIDSTART, "Starting Energy")

            if self.GRID == 1:
                self.GRIDEND = congruence.checkStrictlyPositiveNumber(
                    self.GRIDEND, "Energy to")
                congruence.checkLessThan(self.GRIDSTART, self.GRIDEND,
                                         "Starting Energy", "Energy to")
                self.GRIDN = congruence.checkStrictlyPositiveNumber(
                    self.GRIDN, "Number of points")

    def do_xoppy_calculation(self):
        out_dict = self.xoppy_calc_xcrosssec()

        if "info" in out_dict.keys():
            print(out_dict["info"])

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

        try:
            calculated_data.add_content("xoppy_data", out_dict["data"].T)
            calculated_data.add_content("plot_x_col", 0)
            calculated_data.add_content("plot_y_col", -1)
        except:
            pass
        try:
            calculated_data.add_content("labels", out_dict["labels"])
        except:
            pass
        try:
            calculated_data.add_content("info", out_dict["info"])
        except:
            pass

        return calculated_data

    def extract_data_from_xoppy_output(self, calculation_output):
        try:
            calculation_output.get_content("xoppy_data")

            labels = calculation_output.get_content("labels")

            self.xtitle = labels[0]
            self.ytitle = labels[1]
        except:
            QMessageBox.information(
                self, "Calculation Result", "Calculation Result:\n" +
                calculation_output.get_content("info"), QMessageBox.Ok)

            self.xtitle = None
            self.ytitle = None

        return calculation_output

    def plot_results(self, calculated_data, progressBarValue=80):
        self.initializeTabs()

        try:
            calculated_data.get_content("xoppy_data")

            super().plot_results(calculated_data, progressBarValue)
        except:
            self.plot_info(
                calculated_data.get_content("info") + "\n", progressBarValue,
                0, 0)

    def get_data_exchange_widget_name(self):
        return "XCROSSSEC"

    def getTitles(self):
        return ["Calculation Result"]

    def getXTitles(self):
        if self.xtitle is None:
            return [""]
        else:
            return [self.xtitle]

    def getYTitles(self):
        if self.ytitle is None:
            return [""]
        else:
            return [self.ytitle]

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

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

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

    def xoppy_calc_xcrosssec(self):

        MAT_FLAG = self.MAT_FLAG
        MAT_LIST = self.MAT_LIST
        DESCRIPTOR = self.DESCRIPTOR
        density = self.DENSITY
        CALCULATE = self.CALCULATE
        GRID = self.GRID
        GRIDSTART = self.GRIDSTART
        GRIDEND = self.GRIDEND
        GRIDN = self.GRIDN
        UNIT = self.UNIT

        if MAT_FLAG == 0:  # element
            descriptor = DESCRIPTOR
            density = xraylib.ElementDensity(
                xraylib.SymbolToAtomicNumber(DESCRIPTOR))
        elif MAT_FLAG == 1:  # formula
            descriptor = DESCRIPTOR
        elif MAT_FLAG == 2:
            tmp = xraylib.GetCompoundDataNISTByIndex(MAT_LIST)
            descriptor = tmp["name"]
            density = tmp["density"]

        print("xoppy_calc_xcrosssec: using density = %g g/cm3" % density)
        if GRID == 0:
            energy = numpy.arange(0, 500)
            elefactor = numpy.log10(10000.0 / 30.0) / 300.0
            energy = 10.0 * 10**(energy * elefactor)
        elif GRID == 1:
            if GRIDN == 1:
                energy = numpy.array([GRIDSTART])
            else:
                energy = numpy.linspace(GRIDSTART, GRIDEND, GRIDN)
        elif GRID == 2:
            energy = numpy.array([GRIDSTART])

        if MAT_FLAG == 0:  # element
            out = cross_calc(descriptor,
                             energy,
                             calculate=CALCULATE,
                             density=density)
        elif MAT_FLAG == 1:  # compound parse
            out = cross_calc_mix(descriptor,
                                 energy,
                                 calculate=CALCULATE,
                                 density=density,
                                 parse_or_nist=0)
        elif MAT_FLAG == 2:  # NIST compound
            out = cross_calc_mix(descriptor,
                                 energy,
                                 calculate=CALCULATE,
                                 density=density,
                                 parse_or_nist=1)

        calculate_items = [
            'Total', 'PhotoElectric', 'Rayleigh', 'Compton',
            'Total minus Rayleigh'
        ]
        unit_items = ['barn/atom', 'cm^2', 'cm^2/g', 'cm^-1']
        if energy.size > 1:
            tmp_x = out[0, :].copy()
            tmp_y = out[UNIT + 1, :].copy()
            tmp = numpy.vstack((tmp_x, tmp_y))
            labels = [
                "Photon energy [eV]",
                "%s cross section [%s]" %
                (calculate_items[CALCULATE], unit_items[UNIT])
            ]
            to_return = {
                "application": "xoppy",
                "name": "xcrosssec",
                "data": tmp,
                "labels": labels
            }
        else:
            tmp = None
            txt = "xoppy_calc_xcrosssec: Calculated %s cross section: %g %s" % (
                calculate_items[CALCULATE], out[UNIT + 1, 0], unit_items[UNIT])
            print(txt)
            to_return = {
                "application": "xoppy",
                "name": "xcrosssec",
                "info": txt
            }

        if self.DUMP_TO_FILE:
            with open(self.FILE_NAME, "w") as file:
                try:
                    file.write("#F %s\n" % self.FILE_NAME)
                    file.write("\n#S 1 xoppy CrossSec results\n")
                    file.write("#N 5\n")
                    tmp = "#L  Photon energy [eV]"
                    for unit_item in unit_items:
                        tmp += "  %s [%s]" % (calculate_items[CALCULATE],
                                              unit_item)
                    tmp += "\n"
                    file.write(tmp)
                    for j in range(out.shape[1]):
                        # file.write("%19.12e  "%energy[j])
                        file.write(
                            ("%19.12e  " * out.shape[0] + "\n") %
                            tuple(out[i, j] for i in range(out.shape[0])))
                    file.close()
                    print("File written to disk: %s \n" % self.FILE_NAME)
                except:
                    raise Exception(
                        "CrossSec: The data could not be dumped onto the specified file!\n"
                    )

        return to_return
Exemplo n.º 28
0
class OpticalElementLensWidget(widget.OWWidget):
    name = "Optical lens"
    description = "Optical lens"
    icon = "icons/lens.svg"
    
    inputs  = [("Optical beam", OpticalBeam, "onOpticalBeam", widget.Multiple)]
    outputs = [("Optical beam", OpticalBeam)]    

    value_le_focal_x = Setting(1.0)
    value_le_focal_y = Setting(1.0)

    value_le_driver_settings = Setting("")

    want_main_area = False

    def __init__(self, parent=None, signalManager=None):
        widget.OWWidget.__init__(self, parent, signalManager)

        self.__optical_lens = OpticalElement("lens")
       
        self.le_focal_x = gui.lineEdit(self.controlArea,
                                       self,
                                       "value_le_focal_x",
                                       label="Focal length x [m]",
                                       validator=QDoubleValidator(bottom=0.0))
        
        self.le_focal_y = gui.lineEdit(self.controlArea,
                                       self,
                                       "value_le_focal_y",
                                       label="Focal length y [m]",
                                       validator=QDoubleValidator(bottom=0.0))

        self.__driver_settings_widget = DriverSettingsWidget(self.__optical_lens, 
                                                             self,
                                                             "value_le_driver_settings")
        self.__optical_lens.setOnSynchronize(self.synchronizeToOpticalElement)      
        self.__optical_lens.setOnCalculationStart(self.calculationStart)      
        self.__optical_lens.setOnCalculationFinished(self.calculationFinished)      

    def calculationStart(self):
        self.progressBarInit()
        self.progressBarSet(0)
        QApplication.processEvents()

    def calculationFinished(self):
        self.progressBarSet(100)
        QApplication.processEvents()
        
    def synchronizeToOpticalElement(self):
        focal_x = float(self.value_le_focal_x)
        focal_y = float(self.value_le_focal_y)

        beamline_component = LensIdeal(focal_x=focal_x,
                                       focal_y=focal_y)
        self.__optical_lens.setBeamlineComponent(beamline_component=beamline_component)

    def onOpticalBeam(self, optical_beam, sender):
        optical_beam.sender().addOutput(self.__optical_lens)
                
        sender = OpticalBeam(self.__optical_lens)
        self.send("Optical beam", sender)
Exemplo n.º 29
0
class OWheight_profile_simulator(OWWidget):
    name = "Height Profile Simulator"
    id = "height_profile_simulator"
    description = "Calculation of mirror surface height profile"
    icon = "icons/simulator.png"
    author = "Luca Rebuffi"
    maintainer_email = "*****@*****.**"
    priority = 1
    category = ""
    keywords = ["height_profile_simulator"]

    outputs = [{
        "name": "PreInput",
        "type": WiserPreInputData,
        "doc": "PreInput",
        "id": "PreInput"
    }]

    want_main_area = 1
    want_control_area = 1

    MAX_WIDTH = 1320
    MAX_HEIGHT = 700

    IMAGE_WIDTH = 860
    IMAGE_HEIGHT = 645

    CONTROL_AREA_WIDTH = 405
    TABS_AREA_HEIGHT = 618

    xx = None
    yy = None

    kind_of_profile_y = Setting(0)
    step_y = Setting(1.0)
    dimension_y = Setting(200.1)
    power_law_exponent_beta_y = Setting(1.5)
    correlation_length_y = Setting(30.0)
    rms_y = Setting(1)
    montecarlo_seed_y = Setting(8788)
    error_type_y = Setting(profiles_simulation.FIGURE_ERROR)

    heigth_profile_file_name = Setting('figure_error.dat')

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

        self.runaction = widget.OWAction("Calculate Height Profile", self)
        self.runaction.triggered.connect(self.calculate_heigth_profile)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Generate Height Profile File", self)
        self.runaction.triggered.connect(self.generate_heigth_profile_file)
        self.addAction(self.runaction)

        geom = QApplication.desktop().availableGeometry()
        self.setGeometry(
            QRect(round(geom.width() * 0.05), round(geom.height() * 0.05),
                  round(min(geom.width() * 0.98, self.MAX_WIDTH)),
                  round(min(geom.height() * 0.95, self.MAX_HEIGHT))))

        self.setMaximumHeight(self.geometry().height())
        self.setMaximumWidth(self.geometry().width())

        gui.separator(self.controlArea)

        button_box = oasysgui.widgetBox(self.controlArea,
                                        "",
                                        addSpace=False,
                                        orientation="horizontal")

        button = gui.button(button_box,
                            self,
                            "Calculate Height\nProfile",
                            callback=self.calculate_heigth_profile)
        button.setFixedHeight(45)

        button = gui.button(button_box,
                            self,
                            "Generate Height\nProfile File",
                            callback=self.generate_heigth_profile_file)
        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.setFixedWidth(150)

        button = gui.button(button_box,
                            self,
                            "Reset Fields",
                            callback=self.call_reset_settings)
        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)

        gui.separator(self.controlArea)

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

        tab_input = oasysgui.createTabPage(tabs_setting, "Input Parameters")
        tab_out = oasysgui.createTabPage(tabs_setting, "Output")

        #/ ---------------------------------------

        input_box_l = oasysgui.widgetBox(tab_input,
                                         "Calculation Parameters",
                                         addSpace=True,
                                         orientation="vertical")

        gui.comboBox(input_box_l,
                     self,
                     "kind_of_profile_y",
                     label="Kind of Profile",
                     labelWidth=260,
                     items=["Fractal", "Gaussian"],
                     callback=self.set_KindOfProfileY,
                     sendSelectedValue=False,
                     orientation="horizontal")

        gui.separator(input_box_l)

        self.kind_of_profile_y_box_1 = oasysgui.widgetBox(
            input_box_l,
            "",
            addSpace=False,
            orientation="vertical",
            height=230)

        self.le_dimension_y = oasysgui.lineEdit(self.kind_of_profile_y_box_1,
                                                self,
                                                "dimension_y",
                                                "Dimensions",
                                                labelWidth=260,
                                                valueType=float,
                                                orientation="horizontal")
        self.le_step_y = oasysgui.lineEdit(self.kind_of_profile_y_box_1,
                                           self,
                                           "step_y",
                                           "Step",
                                           labelWidth=260,
                                           valueType=float,
                                           orientation="horizontal")
        oasysgui.lineEdit(self.kind_of_profile_y_box_1,
                          self,
                          "montecarlo_seed_y",
                          "Monte Carlo initial seed",
                          labelWidth=260,
                          valueType=int,
                          orientation="horizontal")

        self.kind_of_profile_y_box_1_1 = oasysgui.widgetBox(
            self.kind_of_profile_y_box_1,
            "",
            addSpace=False,
            orientation="vertical")

        oasysgui.lineEdit(self.kind_of_profile_y_box_1_1,
                          self,
                          "power_law_exponent_beta_y",
                          "Beta Value",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        self.kind_of_profile_y_box_1_2 = oasysgui.widgetBox(
            self.kind_of_profile_y_box_1,
            "",
            addSpace=False,
            orientation="vertical")

        self.le_correlation_length_y = oasysgui.lineEdit(
            self.kind_of_profile_y_box_1_2,
            self,
            "correlation_length_y",
            "Correlation Length",
            labelWidth=260,
            valueType=float,
            orientation="horizontal")

        gui.separator(self.kind_of_profile_y_box_1)

        gui.comboBox(
            self.kind_of_profile_y_box_1,
            self,
            "error_type_y",
            label="Normalization to",
            labelWidth=270,
            items=["Figure Error (nm)", "Slope Error (" + "\u03BC" + "rad)"],
            sendSelectedValue=False,
            orientation="horizontal")

        oasysgui.lineEdit(self.kind_of_profile_y_box_1,
                          self,
                          "rms_y",
                          "Rms Value",
                          labelWidth=260,
                          valueType=float,
                          orientation="horizontal")

        self.set_KindOfProfileY()

        self.output_box = oasysgui.widgetBox(tab_input,
                                             "Outputs",
                                             addSpace=True,
                                             orientation="vertical")

        self.select_file_box = oasysgui.widgetBox(self.output_box,
                                                  "",
                                                  addSpace=False,
                                                  orientation="horizontal")

        self.le_heigth_profile_file_name = oasysgui.lineEdit(
            self.select_file_box,
            self,
            "heigth_profile_file_name",
            "Output File Name",
            labelWidth=120,
            valueType=str,
            orientation="horizontal")

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

        self.wise_output = QTextEdit()
        self.wise_output.setReadOnly(True)
        self.wise_output.setStyleSheet("background-color: white;")

        out_box = oasysgui.widgetBox(tab_out,
                                     "System Output",
                                     addSpace=True,
                                     orientation="horizontal",
                                     height=580)
        out_box.layout().addWidget(self.wise_output)

        gui.rubber(self.controlArea)

        main_tabs = oasysgui.tabWidget(self.mainArea)
        self.plot_tab = oasysgui.createTabPage(main_tabs, "Results")
        self.plot_tab.setFixedHeight(self.IMAGE_HEIGHT)
        self.plot_tab.setFixedWidth(self.IMAGE_WIDTH)

        self.plot_canvas = None

        gui.rubber(self.mainArea)

    def after_change_workspace_units(self):
        label = self.le_dimension_y.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_step_y.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_correlation_length_y.parent().layout().itemAt(
            0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

    def set_KindOfProfileY(self):
        self.kind_of_profile_y_box_1_1.setVisible(self.kind_of_profile_y == 0)
        self.kind_of_profile_y_box_1_2.setVisible(self.kind_of_profile_y == 1)

    def calculate_heigth_profile(self, not_interactive_mode=False):
        try:
            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            if self.error_type_y == profiles_simulation.FIGURE_ERROR:
                rms_y = self.rms_y * 1e-9  # from nm to m
            else:
                rms_y = self.rms_y * 1e-6  # from urad to rad

            xx, yy = profiles_simulation.simulate_profile_1D(
                step=self.step_y * self.workspace_units_to_m,
                mirror_length=self.dimension_y * self.workspace_units_to_m,
                random_seed=self.montecarlo_seed_y,
                error_type=self.error_type_y,
                profile_type=1 - self.kind_of_profile_y,
                rms=rms_y,
                correlation_length=self.correlation_length_y *
                self.workspace_units_to_m,
                power_law_exponent_beta=self.power_law_exponent_beta_y)

            xx_to_plot = xx / self.workspace_units_to_m  # to user units
            yy_to_plot = yy * 1e9  # nm
            self.yy = yy / self.workspace_units_to_m  # to user units

            ny = yy.size

            slope = numpy.zeros(ny)
            for i in range(ny - 1):
                step = xx[i + 1] - xx[i]
                slope[i] = numpy.arctan((yy[i + 1] - yy[i]) / step)
            slope[ny - 1] = slope[ny - 2]
            sloperms = slope.std()

            title = ' Slope error rms in Z direction: %f $\mu$rad' % (
                sloperms * 1e6)

            if self.plot_canvas is None:
                self.plot_canvas = oasysgui.plotWindow(roi=False,
                                                       control=False,
                                                       position=False)
                self.plot_canvas.setDefaultPlotLines(True)
                self.plot_canvas.setActiveCurveColor(color='blue')

                self.plot_tab.layout().addWidget(self.plot_canvas)

            WiserPlot.plot_histo(self.plot_canvas, xx_to_plot, yy_to_plot,
                                 title,
                                 "X [" + self.workspace_units_label + "]",
                                 "Z [nm]")

            QMessageBox.information(
                self, "QMessageBox.information()",
                "Height Profile calculated: if the result is satisfactory,\nclick \'Generate Height Profile File\' to complete the operation ",
                QMessageBox.Ok)
        except Exception as exception:
            QMessageBox.critical(self, "Error", exception.args[0],
                                 QMessageBox.Ok)
            raise exception

    def generate_heigth_profile_file(self, not_interactive_mode=False):
        if not self.yy is None:
            try:
                congruence.checkDir(self.heigth_profile_file_name)

                sys.stdout = EmittingStream(textWritten=self.writeStdOut)

                numpy.savetxt(self.heigth_profile_file_name, self.yy)

                QMessageBox.information(
                    self, "QMessageBox.information()", "Height Profile file " +
                    self.heigth_profile_file_name + " written on disk",
                    QMessageBox.Ok)

                self.send(
                    "PreInput",
                    WiserPreInputData(
                        figure_error_file=self.heigth_profile_file_name,
                        figure_error_step=self.step_y,
                        figure_user_units_to_m=self.workspace_units_to_m))
            except Exception as exception:
                QMessageBox.critical(self, "Error", exception.args[0],
                                     QMessageBox.Ok)

    def call_reset_settings(self):
        if ConfirmDialog.confirmed(parent=self,
                                   message="Confirm Reset of the Fields?"):
            try:
                self.resetSettings()
            except:
                pass

    def check_fields(self):
        self.dimension_y = congruence.checkStrictlyPositiveNumber(
            self.dimension_y, "Dimension")
        self.step_y = congruence.checkStrictlyPositiveNumber(
            self.step_y, "Step")
        if self.kind_of_profile_y == 0:
            self.power_law_exponent_beta_y = congruence.checkPositiveNumber(
                self.power_law_exponent_beta_y, "Beta Value")
        if self.kind_of_profile_y == 1:
            self.correlation_length_y = congruence.checkStrictlyPositiveNumber(
                self.correlation_length_y, "Correlation Length")
        self.rms_y = congruence.checkPositiveNumber(self.rms_y, "Rms")
        self.montecarlo_seed_y = congruence.checkPositiveNumber(
            self.montecarlo_seed_y, "Monte Carlo initial seed")

        congruence.checkDir(self.heigth_profile_file_name)

    def writeStdOut(self, text):
        cursor = self.wise_output.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.wise_output.setTextCursor(cursor)
        self.wise_output.ensureCursorVisible()

    def selectFile(self):
        self.le_heigth_profile_file_name.setText(
            oasysgui.selectFileFromDialog(
                self,
                self.heigth_profile_file_name,
                "Select Output File",
                file_extension_filter="Data Files (*.dat *.txt)"))
Exemplo n.º 30
0
class OWmlayer(XoppyWidget):
    name = "MLayer"
    id = "orange.widgets.datamlayer"
    description = "Multilayer Reflectivity"
    icon = "icons/xoppy_mlayer.png"
    priority = 11
    category = ""
    keywords = ["xoppy", "mlayer"]

    MODE = Setting(0)
    SCAN = Setting(0)
    F12_FLAG = Setting(0)
    SUBSTRATE = Setting("Si")
    ODD_MATERIAL = Setting("Si")
    EVEN_MATERIAL = Setting("W")
    ENERGY = Setting(8050.0)
    THETA = Setting(0.0)
    SCAN_STEP = Setting(0.01)
    NPOINTS = Setting(600)
    ODD_THICKNESS = Setting(25.0)
    EVEN_THICKNESS = Setting(25.0)
    NLAYERS = Setting(50)
    FILE = Setting("layers.dat")

    def build_gui(self):

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

        idx = -1

        #widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "MODE",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Periodic Layers', 'Individual Layers'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "SCAN",
                     label=self.unitLabels()[idx],
                     addSpace=False,
                     items=['Grazing Angle', 'Photon Energy'],
                     valueType=int,
                     orientation="horizontal",
                     labelWidth=250)
        self.show_at(self.unitFlags()[idx], box1)

        #widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(
            box1,
            self,
            "F12_FLAG",
            label=self.unitLabels()[idx],
            addSpace=False,
            items=['Create on the fly', 'Use existing file: mlayers.f12'],
            valueType=int,
            orientation="horizontal",
            labelWidth=150)
        self.show_at(self.unitFlags()[idx], box1)

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

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

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

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

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

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

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

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

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

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

        #widget index 13
        idx += 1
        box1 = gui.widgetBox(box)
        file_box = oasysgui.widgetBox(box1,
                                      "",
                                      addSpace=False,
                                      orientation="horizontal",
                                      height=25)

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

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

        gui.rubber(self.controlArea)

    def unitLabels(self):
        return [
            'Layer periodicity: ', 'Scanning variable: ',
            'Material parameters:', 'Substrate: ',
            'Odd layer material (closer to vacuum): ',
            'Even layer material (closer to substrate): ',
            'Photon energy [eV]:', 'Grazing angle [degrees]:',
            'Scanning variable step: ', 'Number of scanning points',
            'Thickness [A] for odd material:',
            'Thickness [A] for even material:', 'Number of layer pairs:',
            'File with layer thicknesses:'
        ]

    def unitFlags(self):
        return [
            'True', 'True', 'True', 'self.F12_FLAG  ==  0',
            'self.F12_FLAG  ==  0', 'self.F12_FLAG  ==  0', 'True', 'True',
            'True', 'True', 'self.MODE  ==  0  &  self.F12_FLAG  ==  0',
            'self.MODE  ==  0  &  self.F12_FLAG  ==  0',
            'self.MODE  ==  0  &  self.F12_FLAG  ==  0', 'self.MODE  ==  1'
        ]

    def get_help_name(self):
        return 'mlayer'

    def selectFile(self):
        self.le_file.setText(
            oasysgui.selectFileFromDialog(self,
                                          self.FILE,
                                          "Open File with layer thicknesses",
                                          file_extension_filter="*.dat *.txt"))

    def check_fields(self):
        if self.F12_FLAG == 1:
            congruence.checkEmptyString(self.SUBSTRATE, "Substrate")
            congruence.checkEmptyString(self.ODD_MATERIAL,
                                        "Odd layer material")
            congruence.checkEmptyString(self.EVEN_MATERIAL,
                                        "Even layer material")

        if self.SCAN == 0:  # ga
            self.ENERGY = congruence.checkStrictlyPositiveNumber(
                self.ENERGY, "Photon energy")
        else:
            self.THETA = congruence.checkStrictlyPositiveNumber(
                self.THETA, "Grazing angle")

        self.SCAN_STEP = congruence.checkStrictlyPositiveNumber(
            self.SCAN_STEP, "Scanning variable step")
        self.NPOINTS = congruence.checkStrictlyPositiveNumber(
            self.NPOINTS, "Number of scanning points")

        if self.MODE == 0:  # periodic layers
            self.ODD_THICKNESS = congruence.checkStrictlyPositiveNumber(
                self.ODD_THICKNESS, "Thickness for odd material")
            self.EVEN_THICKNESS = congruence.checkStrictlyPositiveNumber(
                self.EVEN_THICKNESS, "Thickness for even material")
            self.NLAYERS = congruence.checkStrictlyPositiveNumber(
                self.NLAYERS, "Number of layer pairs")
        else:
            congruence.checkFile(self.FILE)

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

    def extract_data_from_xoppy_output(self, calculation_output):
        return calculation_output

    def get_data_exchange_widget_name(self):
        return "MLAYER"

    def getTitles(self):
        return [
            "s-reflectivity", "p-reflectivity", "averaged reflectivity",
            "s-phase shift", "p-phase shift", "(s-electric field)^2",
            "(p-electric field)^2"
        ]

    def getXTitles(self):
        if self.SCAN == 0:
            return [
                "Grazing angle Theta [deg]", "Grazing angle Theta [deg]",
                "Grazing angle Theta [deg]", "Grazing angle Theta [deg]",
                "Grazing angle Theta [deg]", "Grazing angle Theta [deg]",
                "Grazing angle Theta [deg]"
            ]
        else:
            return [
                "Photon energy [eV]", "Photon energy [eV]",
                "Photon energy [eV]", "Photon energy [eV]",
                "Photon energy [eV]", "Photon energy [eV]",
                "Photon energy [eV]"
            ]

    def getYTitles(self):
        return self.getTitles()

    def getVariablesToPlot(self):
        if self.SCAN == 0:
            return [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7)]
        else:
            return [(0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8)]

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

    def xoppy_calc_mlayer(self):

        # copy the variable locally, so no more use of self.
        MODE = self.MODE
        SCAN = self.SCAN
        F12_FLAG = self.F12_FLAG
        SUBSTRATE = self.SUBSTRATE
        ODD_MATERIAL = self.ODD_MATERIAL
        EVEN_MATERIAL = self.EVEN_MATERIAL
        ENERGY = self.ENERGY
        THETA = self.THETA
        SCAN_STEP = self.SCAN_STEP
        NPOINTS = self.NPOINTS
        ODD_THICKNESS = self.ODD_THICKNESS
        EVEN_THICKNESS = self.EVEN_THICKNESS
        NLAYERS = self.NLAYERS
        FILE = self.FILE

        for file in ["mlayer.inp", "mlayer.par", "mlayer.f12"]:
            try:
                os.remove(os.path.join(locations.home_bin_run(), file))
            except:
                pass

        #
        # write input file for Fortran mlayer: mlayer.inp
        #
        f = open('mlayer.inp', 'w')

        if SCAN == 0 and MODE == 0: a0 = 1
        if SCAN == 1 and MODE == 0: a0 = 2
        if SCAN == 0 and MODE == 1: a0 = 3
        if SCAN == 1 and MODE == 1: a0 = 4

        f.write("%d \n" % a0)
        f.write("N\n")

        f.write("%g\n" % (codata.h * codata.c / codata.e * 1e10 / ENERGY))
        f.write("%g\n" % THETA)

        #
        if SCAN == 0:
            f.write("%g\n" % SCAN_STEP)

        a2 = codata.h * codata.c / codata.e * 1e10 / ENERGY
        a3 = codata.h * codata.c / codata.e * 1e10 / (ENERGY + SCAN_STEP)
        a4 = a3 - a2

        if SCAN != 0:
            f.write("%g\n" % a4)

        #
        f.write("%d\n" % NPOINTS)

        if MODE == 0:
            f.write("%d\n" % NLAYERS)

        if MODE == 0:
            if a0 != 5:
                f.write("%g  %g  \n" % (ODD_THICKNESS, EVEN_THICKNESS))
            else:
                for i in range(NLAYERS):
                    f.write("%g  %g  \n" % (ODD_THICKNESS, EVEN_THICKNESS))

        if MODE != 0:
            f1 = open(FILE, 'r')
            a5 = f1.read()
            f1.close()

        if MODE != 0:
            print("Number of layers in %s file is %d " % (FILE, NLAYERS))
            f.write("%d\n" % NLAYERS)
            f.write(a5)

        f.write("mlayer.par\n")
        f.write("mlayer.dat\n")

        f.write("6\n")

        f.close()
        print('File written to disk: mlayer.inp')

        #
        # create f12 file
        #

        if F12_FLAG == 0:
            energy = numpy.arange(0, 500)
            elefactor = numpy.log10(10000.0 / 30.0) / 300.0
            energy = 10.0 * 10**(energy * elefactor)

            f12_s = f1f2_calc(SUBSTRATE, energy)
            f12_e = f1f2_calc(EVEN_MATERIAL, energy)
            f12_o = f1f2_calc(ODD_MATERIAL, energy)

            f = open("mlayer.f12", 'w')
            f.write(
                '; File created by xoppy for materials [substrate=%s,even=%s,odd=%s]: \n'
                % (SUBSTRATE, EVEN_MATERIAL, ODD_MATERIAL))
            f.write('; Atomic masses: \n')
            f.write(
                "%g %g %g \n" %
                (xraylib.AtomicWeight(xraylib.SymbolToAtomicNumber(SUBSTRATE)),
                 xraylib.AtomicWeight(
                     xraylib.SymbolToAtomicNumber(EVEN_MATERIAL)),
                 xraylib.AtomicWeight(
                     xraylib.SymbolToAtomicNumber(ODD_MATERIAL))))
            f.write('; Densities: \n')
            f.write("%g %g %g \n" %
                    (xraylib.ElementDensity(
                        xraylib.SymbolToAtomicNumber(SUBSTRATE)),
                     xraylib.ElementDensity(
                         xraylib.SymbolToAtomicNumber(EVEN_MATERIAL)),
                     xraylib.ElementDensity(
                         xraylib.SymbolToAtomicNumber(ODD_MATERIAL))))
            f.write('; Number of energy points: \n')

            f.write("%d\n" % (energy.size))
            f.write(
                '; For each energy point, energy[eV], f1[substrate], f2[substrate], f1[even], f2[even], f1[odd], f2[odd]: \n'
            )
            for i in range(energy.size):
                f.write("%g %g %g %g %g %g %g \n" %
                        (energy[i], f12_s[0, i], f12_s[1, i], f12_e[0, i],
                         f12_e[1, i], f12_o[0, i], f12_o[1, i]))

            f.close()

            print('File written to disk: mlayer.f12')

        #
        # run external program mlayer
        #

        if platform.system() == "Windows":
            command = os.path.join(locations.home_bin(),
                                   'mlayer.exe < mlayer.inp')
        else:
            command = "'" + os.path.join(locations.home_bin(),
                                         'mlayer') + "' < mlayer.inp"
        print("Running command '%s' in directory: %s " %
              (command, locations.home_bin_run()))
        print("\n--------------------------------------------------------\n")
        os.system(command)
        print("\n--------------------------------------------------------\n")

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

        try:
            if SCAN == 0:
                calculated_data.add_content("xoppy_data",
                                            numpy.loadtxt("mlayer.dat"))
                calculated_data.add_content("plot_x_col", 0)
                calculated_data.add_content("plot_y_col", 3)
            elif SCAN == 1:  # internal scan is in wavelength. Add a column with energy
                aa = numpy.loadtxt("mlayer.dat")
                photon_energy = (codata.h * codata.c / codata.e * 1e10) / aa[:,
                                                                             0]
                bb = numpy.zeros((aa.shape[0], 1 + aa.shape[1]))
                bb[:, 0] = photon_energy
                bb[:, 1:] = aa
                calculated_data.add_content("xoppy_data", bb)
                calculated_data.add_content("plot_x_col", 0)
                calculated_data.add_content("plot_y_col", 4)

            calculated_data.add_content("units_to_degrees", 1.0)
        except:
            pass
        try:
            info = "ML %s(%3.2f A):%s(%3.2f A) %d pairs; E=%5.3f eV" % (
                ODD_MATERIAL, ODD_THICKNESS, EVEN_MATERIAL, EVEN_THICKNESS,
                NLAYERS, ENERGY)
            calculated_data.add_content("info", info)
        except:
            pass

        return calculated_data

    def defaults(self):
        self.resetSettings()
        self.compute()
        return

    def help1(self):
        print("help pressed.")
        xoppy_util.xoppy_doc('mlayer')