Пример #1
0
    def __init__(self, file_atoms):
        QMainWindow.__init__(self)

        self.f = file_atoms  # FileAtoms object

        # # Central widget containing toolbar and plot area

        # ## Toolbar

        l = self.labelDataField = QLabel("&Data field")
        c = self.comboBoxDataField = QComboBox()
        c.addItems(ATOM_ATTR_NAMES)
        l.setBuddy(c)
        l2 = self.labelSpinBox = QLabel("&Bins")
        sb = self.spinBox = QSpinBox()
        sb.setMaximum(MAX_NUM_BINS)
        sb.setValue(50)
        l2.setBuddy(sb)
        b = self.puishButtonPlot = QPushButton("&Plot")
        b.clicked.connect(self.on_plot)

        s = self.spacer0 = QSpacerItem(0, 0, QSizePolicy.Expanding,
                                       QSizePolicy.Minimum)

        bb = [l, c, l2, sb, b]

        l0 = self.layoutToolbar = QHBoxLayout()
        for b in bb:
            l0.addWidget(b)
        l0.addItem(s)
        a = self.widgetPlotToolbar = QWidget()
        a.setLayout(l0)
        a.setFixedHeight(40)

        # ## Plot widget
        # http://stackoverflow.com/questions/12459811
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar2QT(self.canvas, self)
        l1 = self.layoutPlot = QVBoxLayout()
        l1.addWidget(self.toolbar)
        l1.addWidget(self.canvas)
        a99.set_margin(l1, 0)
        # a = self.widgetPlot = QWidget()
        # a.setLayout(l1)

        # ## Mounts central widget
        l2 = self.layoutCentral = QVBoxLayout()
        l2.addWidget(self.widgetPlotToolbar)
        l2.addLayout(l1)
        # l2.addWidget(self.widgetPlot)
        a99.set_margin(l2, 0)
        a = self.centralWidget = QWidget()
        a.setLayout(l2)
        a.setFont(a99.MONO_FONT)
        self.setCentralWidget(self.centralWidget)

        # # Final adjustments
        self.setWindowTitle("Histogram")
        a99.place_center(self)
Пример #2
0
    def __init__(self, *args):
        a99.WEditor.__init__(self, *args)

        # # Main layout & splitter
        lmain = self.layout_editor

        sp = self.splitter_bidon = QSplitter(Qt.Horizontal)

        # ## First widget of splitter: molecules
        w0 = self.keep_ref(QWidget())
        l0 = QVBoxLayout(w0)
        a99.set_margin(l0, 2)
        l0.setSpacing(2)

        a = self.title_mol = QLabel(a99.format_title0("Molecules (Alt+&M)"))
        l0.addWidget(a)

        w = self.keep_ref(QLineEdit())
        l0.addWidget(w)

        w = self.w_mol = WDBMolecule(self.parent_form)
        # **Note** Cannot set buddy to w itself because it has a Qt.NoFocus policy
        a.setBuddy(w.tableWidget)
        w.id_changed.connect(self.mol_id_changed)
        w.changed.connect(self.changed)
        l0.addWidget(w)

        # ## Second widget of splitter: tab widget containing the rest
        w1 = self.tabWidget = QTabWidget(self)

        # ### First tab: systems, PFANT molecules, and Franck-Condon factors
        w = self.w_system = WDBSystemPFANTMolFCF(self.parent_form)
        w.changed.connect(self.changed)
        w1.addTab(self.w_system, "Electronic systems (Alt+&E)")

        # ### Second tab: NIST Chemistry Web Book data
        w = self.w_state = WDBState(self.parent_form)
        w.changed.connect(self.changed)
        w1.addTab(self.w_state, "States from NIST (Alt+&S)")

        sp.addWidget(w0)
        sp.addWidget(w1)
        # sp.setStretchFactor(0, 1)
        # sp.setStretchFactor(1, 2)

        lmain.addWidget(sp)

        # # Final adjustments
        a99.nerdify(self)
Пример #3
0
    def _get_toolbar_bottom(self):
        ltb = QHBoxLayout()
        self.layout_main.addLayout(ltb)
        a99.set_margin(ltb, _LAYMN_TOOLBAR)
        ltb.setSpacing(_LAYSP_TOOLBAR)
        bb = self.button_zeros = QPushButton("Fill empty fields with zeros")
        bb.clicked.connect(self.None_to_zero)
        ltb.addWidget(bb)

        ltb.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))

        bb = self.button_zeros = QPushButton("View Hönl-London factors")
        bb.clicked.connect(self.view_hlf)
        ltb.addWidget(bb)

        bb = self.button_zeros = QPushButton("Generate TRAPRB input")
        bb.setToolTip(
            "Generates text to be used as input file for the TRAPRB Fortran code [Jarmain&McCallum1970]\n"
            "This code calculates Franck-Condon factors")
        bb.clicked.connect(self.view_traprb)
        ltb.addWidget(bb)

        return ltb
Пример #4
0
    def __init__(self, *args):
        a99.WBase.__init__(self, *args)

        # # Main layout & splitter
        lmain = self.keep_ref(QVBoxLayout(self))
        sp = self.keep_ref(QSplitter(Qt.Horizontal))

        # ## First widget of splitter
        w0 = self.keep_ref(QWidget())
        l0 = QVBoxLayout(w0)
        a99.set_margin(l0, 0)
        l0.setSpacing(2)

        a = self.title_mol = QLabel(a99.format_title1("Systems"))
        l0.addWidget(a)

        w = self.w_system = WDBSystem(self.parent_form)
        w.id_changed.connect(self.id_system_changed)
        w.id_changed.connect(self.id_changed)
        w.changed.connect(self.changed)
        l0.addWidget(w)

        # ## Second widget of splitter
        sp1 = self.keep_ref(QSplitter(Qt.Vertical))

        # ### widget 1.1

        w10 = self.keep_ref(QWidget())
        l10 = QVBoxLayout(w10)
        a99.set_margin(l10, 0)
        l10.setSpacing(2)

        a = self.title_state = self.keep_ref(
            QLabel(a99.format_title1("PFANT molecules")))
        l10.addWidget(a)

        w = self.w_pfantmol = WDBPFANTMol(self.parent_form)
        w.changed.connect(self.changed)
        l10.addWidget(w)

        # ### widget 1.1

        w11 = self.keep_ref(QWidget())
        l11 = QVBoxLayout(w11)
        a99.set_margin(l11, 0)
        l11.setSpacing(2)

        a = self.title_state = self.keep_ref(
            QLabel(a99.format_title1("Franck-Condon Factors")))
        l11.addWidget(a)

        w = self.w_fcf = WDBFCF(self.parent_form)
        w.changed.connect(self.changed)
        l11.addWidget(w)

        # ## Adds widgets to splitters

        sp1.addWidget(w10)
        sp1.addWidget(w11)

        sp.addWidget(w0)
        sp.addWidget(sp1)

        lmain.addWidget(sp)

        # # Final adjustments
        a99.nerdify(self)

        self.w_system._move_to_first()
Пример #5
0
    def __init__(self, parent_form):
        a99.WConfigEditor.__init__(self, parent_form)

        self.w_molconsts = parent_form.w_molconsts

        # ## Vertical layout: source and destination stacked
        lsd = self.layout_editor

        # ### Horizontal layout: sources radio buttons, source-specific setup area

        lh = self.keep_ref(QHBoxLayout())
        # a99.set_margin
        lsd.addLayout(lh)

        # #### Vertical layout: source radio group box

        lss = QVBoxLayout()
        lh.addLayout(lss)

        # ##### Source radio buttons
        lss.addWidget(self.keep_ref(QLabel("<b>Source</b>")))
        w = self.w_source = _WSource(self.parent_form)
        w.index_changed.connect(self._source_changed)
        lss.addWidget(w)
        lss.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding))

        # #### Adds configuration panels for various sources
        # Only one panel should be visible at a time
        # **Note** The order here doesn't matter
        panels = {}
        panels["HITRAN"] = self.w_hitran = _WHitranPanel(self)
        panels["VALD3"] = self.w_vald3 = _WVald3Panel(self)
        panels["Plez"] = self.w_plez = _WPlezPanel(self)
        panels["Kurucz"] = self.w_kurucz = _WKuruczPanel(self)
        for name in _NAMES:
            ds = _SOURCES[name]
            ds.widget = p = panels[name]
            lh.addWidget(p)
            p.changed.connect(self._panel_changed)

        # ### Flags panel

        fr = self.frame_flags = a99.get_frame()
        lsd.addWidget(fr)
        lfr = self.layout_flags = QVBoxLayout(fr)
        lfr.setSpacing(_LAYSP_V)
        a99.set_margin(lfr, _LAYMN_V)

        la = self.label_flags = QLabel("<b>Flags</b>")
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        lfr.addWidget(la)

        lg = QGridLayout()
        lg.setSpacing(_LAYSP_GRID)
        a99.set_margin(lg, _LAYMN_GRID)
        lfr.addLayout(lg)

        i_row = 0

        a = self.keep_ref(
            QLabel("Calculate 'gf' based on\n"
                   "Hönl-London factors (HLFs)"))
        w = self.checkbox_hlf = QCheckBox()
        w.setChecked(True)
        w.stateChanged.connect(self.changed)
        w.setToolTip(
            "If selected, will ignore 'loggf' from Kurucz file and\n"
            "calculate 'gf' using Hönl-London factors formulas taken from Kovacz (1969)"
        )
        lg.addWidget(a, i_row, 0)
        lg.addWidget(w, i_row, 1)
        i_row += 1

        a = self.keep_ref(
            QLabel("Apply normalization factor\n"
                   "for HLFs to add up to 1 (for fixed J)"))
        w = self.checkbox_normhlf = QCheckBox()
        w.setChecked(True)
        w.stateChanged.connect(self.changed)
        w.setToolTip("If selected, calculated 'gf's will be multiplied by\n"
                     "2 / ((2 * J2l + 1) * (2 * S + 1)*(2 - DELTAK))")
        lg.addWidget(a, i_row, 0)
        lg.addWidget(w, i_row, 1)
        i_row += 1

        a = self.keep_ref(
            QLabel("Multiply calculated 'gf' by\n"
                   "Franck-Condon factor"))
        w = self.checkbox_fcf = QCheckBox()
        w.setChecked(True)
        w.stateChanged.connect(self.changed)
        w.setToolTip(
            "If selected, incorporates internally calculated Franck-Condon factor"
            "into the calculated 'gf'")
        lg.addWidget(a, i_row, 0)
        lg.addWidget(w, i_row, 1)
        i_row += 1

        a = self.keep_ref(
            QLabel("Use spin' for branch determination\n"
                   "(spin'' is always used)"))
        w = self.checkbox_spinl = QCheckBox()
        w.setChecked(True)
        w.stateChanged.connect(self.changed)
        w.setToolTip(
            "If you tick this box, branches P12, P21, Q12, Q21, R21, R12 (i.e., with two numbers) become possible"
        )
        lg.addWidget(a, i_row, 0)
        lg.addWidget(w, i_row, 1)
        i_row += 1

        a = self.keep_ref(QLabel("Quiet conversion"))
        w = self.checkbox_quiet = QCheckBox()
        w.setChecked(True)
        w.stateChanged.connect(self.changed)
        w.setToolTip("If selected, will show less error messages")
        lg.addWidget(a, i_row, 0)
        lg.addWidget(w, i_row, 1)
        i_row += 1

        a = self.keep_ref(QLabel("Force 0.1 <= FCF < 1 (debugging option)"))
        w = self.checkbox_special_fcf = QCheckBox()
        w.stateChanged.connect(self.changed)
        w.setToolTip(
            "(*temporary*) If selected, makes 'fcf = fcf * 10 ** -(math.floor(math.log10(fcf)) + 1)'"
        )
        lg.addWidget(a, i_row, 0)
        lg.addWidget(w, i_row, 1)
        i_row += 1

        # ### Output file specification

        w0 = self.w_out = _WSelectSaveFile(self.parent_form)
        w0.wants_autofilename.connect(self._wants_autofilename)
        w0.changed.connect(self._fn_output_changed)
        lsd.addWidget(w0)

        # ### "Convert" button

        lmn = QHBoxLayout()
        lsd.addLayout(lmn)
        lmn.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))
        b = self.button_convert = QPushButton("&Run Conversion")
        b.clicked.connect(self._convert_clicked)
        lmn.addWidget(b)
        b = self.button_convert = QPushButton("&Open result in mled.py")
        b.clicked.connect(self._open_mol_clicked)
        lmn.addWidget(b)

        # name, property
        self._map = [
            a99.CEMapItem("sourcename", self.w_source),
            a99.CEMapItem("fn_output", self.w_out, propertyname="value"),
            a99.CEMapItem("kurucz_iso", self.w_kurucz, propertyname="iso"),
            a99.CEMapItem("kurucz_fn_input",
                          self.w_kurucz.w_file,
                          propertyname="value"),
            a99.CEMapItem("plez_fn_input",
                          self.w_plez.w_file,
                          propertyname="value"),
            a99.CEMapItem("plez_species", self.w_plez, propertyname="species"),
            a99.CEMapItem("flag_hlf", self),
            a99.CEMapItem("flag_normhlf", self),
            a99.CEMapItem("flag_fcf", self),
            a99.CEMapItem("flag_special_fcf", self),
            a99.CEMapItem("flag_spinl", self),
            a99.CEMapItem("flag_quiet", self),
        ]
Пример #6
0
    def __init__(self, parent=None, rm=None):
        QMainWindow.__init__(self, parent)
        assert isinstance(rm, pyfant.RunnableManager)
        self.rm = rm
        # Whether to close matplotlib plots when window is closed
        self.flag_close_mpl_plots_on_close = True
        # Whether to show "close window to continue" when finished
        self.flag_close_message = True
        self.__num_finished_shown = 0  # outdated version of self.rm.num_finished
        self.__lock_table = Lock()
        self.__lfcs = 0  # labelFinished color state
        self.__explorer_form = None

        # # Window design

        # ## Toolbar

        b0 = self.pushButtonStatus = QPushButton("Show &status")
        b0.clicked.connect(self.on_status)
        b0.setCheckable(True)
        b0.setChecked(FLAG_SHOW_STATUS)
        b0.setToolTip("Turn status panel on/off")
        b1 = self.pushButtonTable = QPushButton("Show &runnables")
        b1.clicked.connect(self.on_table)
        b1.setCheckable(True)
        b1.setChecked(FLAG_SHOW_RUNNABLES)
        b1.setToolTip("Turn status panel on/off")
        b2 = self.pushButtonPause = QPushButton("&Pause")
        b2.clicked.connect(self.on_pause)
        b2.setCheckable(True)
        b2.setToolTip("Pause/Resume")
        b3 = self.pushButtonCancel = QPushButton("&Kill running")
        b3.setToolTip("Attempts to kill all running jobs")
        b3.clicked.connect(self.on_kill)
        b4 = self.pushButtonCancel = QPushButton("&Exit thread")
        b4.setToolTip("Stops runnables manager thread (irreversible)")
        b4.clicked.connect(self.on_exit)
        b5 = self.pushButtonRetryFailed = QPushButton("Retry &failed")
        b5.clicked.connect(self.on_retry_failed)
        b6 = self.pushButtonCollectErrors = QPushButton("&Collect errors")
        b6.setToolTip(
            "Searches for errors in log files and reports these errors in a new window."
        )
        b6.clicked.connect(self.on_collect_errors)
        # todo + note: assuming that there is no interest in adding new tasks later
        l = self.labelEnd = QLabel()
        l.setVisible(False)

        s = self.spacer0 = QSpacerItem(0, 0, QSizePolicy.Expanding,
                                       QSizePolicy.Minimum)

        bb = [b0, b1, b2, b3, b4, b5, b6, l]
        l0 = self.layoutToolbar = QHBoxLayout()
        for b in bb:
            l0.addWidget(b)
        l0.addItem(s)

        a = self.widgetToolbar = QWidget()
        a.setLayout(l0)
        a.setFixedHeight(40)

        # ## Status widget

        # ### Left column
        w0 = self.labelStatusFinished = QLabel()
        w1 = self.labelStatusFailed = QLabel()
        w2 = self.labelStatusElla = QLabel()
        w3 = self.labelStatusTPR = QLabel()
        w4 = self.labelStatusTotal = QLabel()
        w5 = self.labelStatusRema = QLabel()
        ww = [("Num finished", w0), ("Num failed", w1), ("Time ellapsed", w2),
              ("Time total estimate", w4), ("Time remaining estimate", w5),
              ("Average time per runnable", w3)]
        l = self.layoutStatus0 = QFormLayout()
        for caption, w in ww:
            w.setStyleSheet("QLabel {font-weight: bold}")
            l.addRow(caption, w)

        # ### Right column
        w0 = self.checkBox_paused = QCheckBox()
        w1 = self.checkBox_cancelled = QCheckBox()
        w2 = self.checkBox_finished = QCheckBox()
        w3 = self.checkBox_failed = QCheckBox()
        w4 = self.checkBox_exited = QCheckBox()
        l = self.layoutStatus1 = QFormLayout()
        ww = [("Paused", w0), ("Cancelled", w1), ("Finished", w2),
              ("Failed", w3), ("Exited", w4)]
        for caption, w in ww:
            w.setChecked(False)
            w.setEnabled(False)
            l.addRow(caption, w)

        l = QHBoxLayout()
        l.addLayout(self.layoutStatus0)
        l.addLayout(self.layoutStatus1)
        x = self.widgetStatus = QWidget()
        x.setVisible(b0.isChecked())
        x.setLayout(l)

        # ## Table Widget

        a = self.tableWidget = QTableWidget()
        a.setToolTip("Double-click to open session directory")
        a.setSelectionMode(QAbstractItemView.SingleSelection)
        a.setAlternatingRowColors(True)
        a.setEditTriggers(QTableWidget.NoEditTriggers)
        a.setSelectionBehavior(QTableWidget.SelectRows)
        a.cellDoubleClicked.connect(self.on_tableWidget_cellDoubleClicked)
        # a.setFont(MONO_FONT)
        a.setVisible(self.pushButtonTable.isChecked())
        a.installEventFilter(self)

        # ## Mounts central widget

        l2 = self.layoutCentral = QVBoxLayout()
        ww = [self.widgetToolbar, self.widgetStatus, self.tableWidget]
        for w in ww:
            l2.addWidget(w)
        # l2.addWidget(self.widgetPlot)
        a99.set_margin(l2, 0)
        a = self.centralWidget = QWidget()
        a.setLayout(l2)
        a.setFont(a99.MONO_FONT)
        self.setCentralWidget(self.centralWidget)

        # # # Status bar
        # self.label_n = QLabel()
        # self.label_t = QLabel()
        # sb = self.statusBar()
        # sb.insertWidget(0, self.label_n, 0)
        # sb.insertWidget(1, self.label_t, 0)

        # # Final adjustments
        self.setGeometry(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
        a99.place_center(self)
        self.setWindowTitle("Runnables Manager")

        # # Non-visual stuff

        # ## Wiring of signals to trigger status update
        t = self.timerUpdate = QTimer()
        t.setInterval(1000)  # miliseconds
        signals = [t.timeout, self.rm.runnable_changed, self.rm.finished]
        self.changed_proxy = a99.SignalProxy(signals,
                                             delay=0,
                                             rateLimit=1,
                                             slot=self.__update,
                                             flag_connect=False)
        self.rm.runnable_added.connect(self.__populate, Qt.QueuedConnection)

        # ## Timer to flick the finish indicator
        t = self.timerFinished = QTimer()
        t.setInterval(200)  # miliseconds
        t.timeout.connect(self.on_timerFinished_timeout)
Пример #7
0
    def __init__(self, parent=None):
        a99.WEditor.__init__(self, parent)

        # # Setup & accessible attributes

        # # Internal stuff that must not be accessed from outside

        # options map: list of _Option
        self.omap = []
        # Internal flag to prevent taking action when some field is updated programatically
        self.flag_process_changes = False
        self.error_text = ""
        self.hiding_text = ""

        # # Central layout

        la = self.layout_editor
        a99.set_margin(la, 0)

        # ## Toolbar: checkboxes with executables
        l1 = self.layout_exes = QHBoxLayout()
        la.addLayout(l1)

        w = self.label_filter = QLabel("<b>Fil&ter:</b>")
        l1.addWidget(w)
        w = self.lineEdit_filter = QLineEdit()
        self.label_filter.setBuddy(w)
        w.textEdited.connect(self.on_filter)
        l1.addWidget(w)
        w.setFixedWidth(100)

        w = self.line12312 = QFrame()  # vertical line
        l1.addWidget(w)
        # w.setGeometry(QRect(240, 240, 3, 61))
        w.setFrameShape(QFrame.VLine)
        w.setFrameShadow(QFrame.Sunken)
        w.setFixedWidth(3)

        w0 = self.checkbox_i = QCheckBox("innewmarcs")
        w1 = self.checkbox_h = QCheckBox("hydro2")
        w2 = self.checkbox_p = QCheckBox("pfant")
        w3 = self.checkbox_n = QCheckBox("nulbad")
        ww = self.checkboxes_exes = [w0, w1, w2, w3]
        l1.addWidget(QLabel("<b>Show options for Fortran binaries:</b>"))
        for w in ww:
            l1.addWidget(w)
            w.setTristate(False)
            w.setChecked(True)
            w.stateChanged.connect(self.on_checkbox_exe_clicked)
        l1.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))

        # ## Toolbar: checkbox for main configuration file override
        l1 = self.layout23432 = QHBoxLayout()
        la.addLayout(l1)
        w = self.checkbox_main = QCheckBox(
            "Show options that override main configuration file")
        w.setStyleSheet("QCheckBox {color: %s}" % COLOR_CONFIG)
        w.setChecked(True)
        w.stateChanged.connect(self.on_checkbox_main_clicked)
        w.setToolTip("Show options that, if set, will override values "
                     "that appear in the main configuration file.")
        l1.addWidget(w)
        w = self.checkbox_devel = QCheckBox("Show developer options")
        w.setChecked(False)
        w.stateChanged.connect(self.on_checkbox_devel_clicked)
        w.setToolTip(
            "Show options that were created to aid software development and debugging."
        )
        l1.addWidget(w)
        l1.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))
        b = QPushButton("Preview command line")
        b.clicked.connect(self.on_preview)
        l1.addWidget(b)

        # ## Splitter with scroll area and descripton+error area
        sp = self.splitter = QSplitter(Qt.Vertical)
        la.addWidget(sp)

        # ### Scroll area containing the form

        sa = self.scrollArea = QScrollArea()
        sp.addWidget(sa)
        sa.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        sa.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        # Widget that will be handled by the scrollable area
        w = self.scrollWidget = QWidget()
        sa.setWidget(self.scrollWidget)
        sa.setWidgetResizable(True)
        #        la.addWidget(w)

        # #### The form layout
        # This layout contains the form layout and a spacer item
        lw = QVBoxLayout()
        w.setLayout(lw)
        # Form layout
        lo = self.formLayout = QGridLayout()
        lw.addLayout(lo)
        lo.setVerticalSpacing(4)
        lo.setHorizontalSpacing(5)
        lw.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding))

        # ##### The editing controls

        self.w_logging_level = QLineEdit()
        self.w_logging_console = QCheckBox()
        self.w_allow = QCheckBox()
        self.w_logging_file = QCheckBox()
        self.w_fn_logging = QLineEdit()
        self.w_fn_main = QLineEdit()
        self.w_fn_progress = QLineEdit()
        self.w_explain = QCheckBox()
        self.w_fn_modeles = QLineEdit()
        self.w_teff = QLineEdit()
        self.w_glog = QLineEdit()
        self.w_asalog = QLineEdit()
        self.w_fn_absoru2 = QLineEdit()
        self.w_fn_hmap = QLineEdit()
        self.w_llzero = QLineEdit()
        self.w_llfin = QLineEdit()
        self.w_fn_moddat = QLineEdit()
        self.w_modcode = QLineEdit()
        self.w_tirb = QLineEdit()
        self.w_ptdisk = QLineEdit()
        self.w_kik = QLineEdit()
        self.w_amores = QCheckBox()
        self.w_kq = QLineEdit()
        self.w_vvt = QLineEdit()
        self.w_zph = QLineEdit()
        self.w_interp = QLineEdit()
        self.w_fn_dissoc = QLineEdit()
        self.w_fn_partit = QLineEdit()
        self.w_fn_abonds = QLineEdit()
        self.w_fn_atoms = QLineEdit()
        self.w_fn_moo = QLineEdit()
        self.w_fn_modgrid = QLineEdit()
        self.w_fn_molecules = QLineEdit()
        self.w_fn_opa = QLineEdit()
        self.w_no_molecules = QCheckBox()
        self.w_no_atoms = QCheckBox()
        self.w_no_h = QCheckBox()
        self.w_opa = QCheckBox()
        self.w_abs = QCheckBox()
        self.w_sca = QCheckBox()
        self.w_absoru = QCheckBox()
        self.w_zinf = QLineEdit()
        self.w_pas = QLineEdit()
        self.w_aint = QLineEdit()
        self.w_flprefix = QLineEdit()
        self.w_fn_flux = QLineEdit()
        self.w_flam = QCheckBox()
        self.w_fn_cv = QCheckBox()
        self.w_pat = QLineEdit()
        self.w_convol = QCheckBox()
        self.w_fwhm = QLineEdit()

        # ##### The options map
        # (*) A few options have been commented out because they are probably
        # irrelevant nowadays, but may be shown again some time.

        o = self.__add_option(
            self.w_logging_level, 'ihpn', 'logging_level', 'debug',
            'logging level',
            'These are the available options:<ul>' + '<li>debug' + '<li>info' +
            '<li>warning' + '<li>error' + '<li>critical' + '<li>halt</ul>')
        o.flag_devel = True
        o.possible_values = [
            "debug", "info", "warning", "error", "critical", "halt"
        ]
        o = self.__add_option(
            self.w_logging_console, 'ihpn', 'logging_console', True,
            'Log to console?',
            'Whether or not to log messages to standard output (usually the command console)'
        )
        o.flag_devel = True
        o = self.__add_option(
            self.w_logging_file, 'ihpn', 'logging_file', False, 'Log to file?',
            'Whether or not to log messages to log file ' +
            '(specified by option --fn_logging)')
        o.flag_devel = True
        o = self.__add_option(
            self.w_explain, 'ihpn', 'explain', False,
            'Save additional debugging information?',
            'This flag informs the Fortran code to save additional information in file explain.txt '
            + '(debugging purposes; output varies, or flag may be ignored)')
        o.flag_devel = True
        o = self.__add_option(
            self.w_fn_logging, 'ihpn', 'fn_logging', None, 'log filename',
            'default: <executable name>_dump.log, <i>e.g.</i>, <b>pfant_dump.log</b>'
        )
        o.type = str
        o.flag_devel = True
        self.__add_option(
            self.w_fn_main, 'ihpn', 'fn_main',
            pyfant.FileMain.default_filename,
            'input file name: main configuration',
            'Contains star parameters and additional software configuration.<br><br>'
            '<b>Attention</b>: the following command-line options, if used, will '
            'override values in the main configuration file: '
            '--llzero, --llfin, --pas, --flprefix, --fwhm.')
        # (*) self.__add_option(self.w_fn_progress, 'ihpn', 'fn_progress', 'file name',
        # 'progress.txt',
        # (*)  'output file name - progress indicator')

        #
        # innewmarcs, hydro2, pfant
        #
        self.__add_option(
            self.w_fn_modeles, 'ihp', 'fn_modeles',
            pyfant.FileModBin.default_filename, 'atmospheric model file name',
            'This is a binary file containing information about atmospheric model. '
            'This file is created by innewmarcs.')

        #
        # innewmarcs, pfant
        #
        self.__add_option(
            self.w_opa, 'ip', 'opa', True, 'Use MARCS opacities?',
            'Whether or not to include MARCS opacity coefficients (absorption and scattering) '
            'in the continuum.')
        # the following option is a pfant-only option but it is better to put it here
        o = self.__add_option(
            self.w_absoru, 'p', 'absoru', True, 'Use absoru() kappa?',
            'Whether or not to include coefficients calculated by subroutine absoru() '
            'in the continuum.')
        o.flag_devel = False  # True
        self.__add_option(
            self.w_fn_opa, 'ip', 'fn_opa', pyfant.FileOpa.default_filename,
            'Opacities filename',
            'This is a text file in the MARCS ".opa" format. This file can be generated through '
            'interpolation using <em>innewmarcs</em>.'
            '<p>Files downloaded directly from the MARCS '
            'website should also work, although it is expected that you will use <em>innewmarcs</em>'
            'to interpolate this opacities file based on a grid of models.')

        #
        # innewmarcs-only
        #
        # (*) self.__add_option(self.w_modcode, 'i', 'modcode', 'string up to 25 characters',
        # 'NoName',
        # (*)  '"Model name"')
        self.__add_option(
            self.w_fn_modgrid, 'i', 'fn_modgrid', "grid.mod",
            'atmospheric model grid (<b>without opacities</b>)',
            'This is a binary file containing a grid of atmospheric models for interpolation.'
            '<p>Whether this file or the one specified by <em>--fn_moo</em> will be used '
            'will depend on the <em>--opa</em>option.')
        self.__add_option(
            self.w_fn_moo, 'i', 'fn_moo', pyfant.FileMoo.default_filename,
            'atmospheric model grid (<b>with opacities</b>)',
            'This is a binary file containing a grid of atmospheric models for interpolation, '
            'opacities included.'
            '<p>Whether this file or the one specified by <em>--fn_modgrid</em> will be used '
            'will depend on the <em>--opa</em>option.')
        self.__add_option(
            self.w_allow, 'i', 'allow', False,
            'Allow point out of atmospheric model grid?',
            'If this option is disabled, target '
            ' (glog, teff, asalog) point for interpolation must lie inside the 3D '
            'atmospheric model grid.')

        #
        # hydro2-only
        #
        self.__add_option(self.w_amores, 'h', 'amores', True,
                          'AMOrtissement de RESonnance?', '')
        o = self.__add_option(
            self.w_kq, 'h', 'kq', 1, 'theorie', '<ul>'
            '<li>0: THEORIE DE GRIEM' + '<li>1: THEORIE QUASISTATIQUE</ul>')
        o.possible_values = [0, 1]

        o = self.__add_option(
            self.w_zph, 'h', 'zph', 12., 'hydrogen-reference-abundance',
            'abundance d\'H pour laquelle sont donn&eacute;es les abondances metalliques'
        )
        o.min = 0.
        o.max = 24.  # actually I would like to remove this option

        #
        # hydro2, pfant
        #
        o = self.__add_option(
            self.w_llzero, 'hp', 'llzero', 6000.,
            "lower boundary of calculation interval (&Aring;)",
            'default: &lt;main_llzero&gt; ' + _FROM_MAIN)
        o.flag_main = True
        o.color = COLOR_CONFIG
        o.type = float
        o = self.__add_option(
            self.w_llfin, 'hp', 'llfin', 6200.,
            'upper boundary of calculation interval (&Aring;)',
            'default: &lt;main_llfin&gt; ' + _FROM_MAIN)
        o.flag_main = True
        o.color = COLOR_CONFIG
        o.type = float
        self.__add_option(
            self.w_fn_absoru2, 'hp', 'fn_absoru2',
            pyfant.FileAbsoru2.default_filename, 'input file name - absoru2',
            'This file contains physical data for pfant and hydro2 "absoru" module'
        )
        self.__add_option(
            self.w_fn_hmap, 'hp', 'fn_hmap', pyfant.FileHmap.default_filename,
            'input file name - hydrogen lines data',
            'Contains a table with<pre>' +
            'filename, niv inf, niv sup, central lambda, kiex, c1</pre>'
            'for each hydrogen line.')
        o = self.__add_option(
            self.w_kik, 'hp', 'kik', 0,
            'option affecting the flux integration', '<ul>' +
            '<li>0: integration using 6/7 points depending on <em>ptdisk</em> '
            'parameter in main configuration file;' +
            '<li>1: 26-point integration</ul>')
        o.possible_values = [0, 1]

        #
        # pfant-only
        #
        o = self.__add_option(self.w_aint, 'p', 'aint', 10,
                              'interval length per iteration (&Aring;)',
                              'default: &lt;main_aint&gt; ' + _FROM_MAIN)
        o.flag_devel = True
        o = self.__add_option(
            self.w_interp, 'p', 'interp', 1,
            'interpolation for subroutine turbul()',
            'interpolation type for subroutine turbul()<ul>' +
            '<li>1: linear;' + '<li>2: parabolic</ul>')
        o.possible_values = [1, 2]
        # > @todo Find names for each file and update options help
        self.__add_option(self.w_fn_dissoc, 'p', 'fn_dissoc',
                          pyfant.FileDissoc.default_filename,
                          'input file name - dissociative equilibrium', '')
        self.__add_option(self.w_fn_partit, 'p', 'fn_partit',
                          pyfant.FilePartit.default_filename,
                          'input file name - partition functions', '')
        self.__add_option(self.w_fn_abonds, 'p', 'fn_abonds',
                          pyfant.FileAbonds.default_filename,
                          'input file name - atomic abundances', '')
        self.__add_option(self.w_fn_atoms, 'p', 'fn_atoms',
                          pyfant.FileAtoms.default_filename,
                          'input file name - atomic lines', '')
        self.__add_option(self.w_fn_molecules, 'p', 'fn_molecules',
                          pyfant.FileMolecules.default_filename,
                          'input file name - molecular lines', '')
        self.__add_option(self.w_no_molecules, 'p', 'no_molecules', False,
                          'Skip molecules?',
                          'If set, skips the calculation of molecular lines.')
        self.__add_option(
            self.w_no_atoms, 'p', 'no_atoms', False, 'Skip atomic lines?',
            'If set, skips the calculation of atomic lines (except hydrogen).')
        self.__add_option(self.w_no_h, 'p', 'no_h', False,
                          'Skip hydrogen lines?',
                          'If set, skips the calculation of hydrogen lines.')
        o = self.__add_option(
            self.w_zinf, 'p', 'zinf', 0.5, '(zinf per-line in dfile:atoms)',
            'This is the distance from center of line to consider in atomic line calculation.<br><br>'
            +
            'If this option is used, it will override all the zinf defined ' +
            'in the atomic lines file with a single value.')
        o.flag_devel = True
        o = self.__add_option(self.w_pas, 'p', 'pas', 0.02,
                              'calculation delta-lambda (&Aring;)',
                              'default: &lt;main_pas&gt; ' + _FROM_MAIN)
        o.flag_main = True
        o.color = COLOR_CONFIG
        o = self.__add_option(
            self.w_abs, 'p', 'abs', False,
            'Use MARCS absorption coefficients?',
            'Whether or not to include MARCS <b>absorption</b> coefficients in the continuum'
            '<p>This option only has effect if <em>--opa<em> is True.')
        o.flag_devel = False
        o = self.__add_option(
            self.w_sca, 'p', 'sca', True, 'Use MARCS scattering coefficients?',
            'Whether or not to include MARCS <b>scattering</b> coefficients in the continuum'
            '<p>This option only has effect if <em>--opa<em> is True.')
        o.flag_devel = False

        #
        # pfant, nulbad
        #
        o = self.__add_option(
            self.w_flprefix, 'pn', 'flprefix', 'flux',
            'pfant output - prefix for flux output files',
            'Three files will be created based on this prefix:<ul>' +
            '<li><flprefix>.spec: un-normalized spectrum' +
            '<li><flprefix>.cont: continuum' +
            '<li><flprefix>.norm: normalized spectrum</ul><br>'
            'default: &lt;main_flprefix&gt; ' + _FROM_MAIN)
        o.flag_main = True
        o.color = COLOR_CONFIG

        #
        # nulbad-only
        #
        self.__add_option(self.w_fn_flux, 'n', 'fn_flux', 'flux.norm',
                          'nulbad input - flux file name',
                          'default: &lt;main_flprefix>.norm ' + _FROM_MAIN)
        o.flag_main = True
        o.color = COLOR_CONFIG
        self.__add_option(
            self.w_flam, 'n', 'flam', False,
            'Perform Fnu-to-FLambda transformation?',
            'If True, Fnu-to-FLambda transformation is done before the convolution'
        )
        self.__add_option(
            self.w_fn_cv, 'n', 'fn_cv', True,
            'nulbad output -- convolved spectrum file name',
            'default: &lt;flux file name&gt;.nulbad.&lt;fwhm&gt;')
        self.__add_option(
            self.w_pat, 'n', 'pat', 0.02,
            'wavelength delta-lambda of nulbad output spectrum (&Aring;)',
            'default: same as delta-lambda of input spectrum')
        self.__add_option(self.w_convol, 'n', 'convol', True,
                          'Apply convolution?', '')
        o = self.__add_option(self.w_fwhm, 'n', 'fwhm', 0.12,
                              'full-width-half-maximum of Gaussian function',
                              'default: &lt;main_fwhm&gt; ' + _FROM_MAIN + ')')
        o.flag_main = True
        o.color = COLOR_CONFIG

        for j, letter in enumerate(IHPN):
            label = QLabel("<b>%s</b>" % letter)
            label.setToolTip("Option is used by %s?" % _EXE_NAMES[letter])
            lo.addWidget(label, 0, 3 + j, Qt.AlignCenter)
        label = QLabel("<b>in use?</b>")
        label.setToolTip("Option will appear in command line?")
        lo.addWidget(label, 0, 2)

        i = 1  # index of next row in layout
        for option in self.omap:
            try:
                for j, letter in enumerate(IHPN):
                    # unicode is for a "v"-like check mark
                    flag_checked = letter in option.ihpn
                    # label = QLabel(QString(chr(10003)) if flag_checked else "")
                    label = QLabel("\u2713" if flag_checked else "")
                    if flag_checked:
                        label.setToolTip("This option is used by %s." %
                                         _EXE_NAMES[letter])

                    option.other_widgets.append(label)
                    lo.addWidget(label, i, 3 + j, Qt.AlignCenter)
                label = option.label = \
                    QLabel(option.get_label_text())
                label.setAlignment(Qt.AlignRight)
                checkbox = option.checkbox = QCheckBox()
                checkbox.installEventFilter(self)
                checkbox.stateChanged.connect(self.on_in_use_checkbox_clicked)
                edit = option.edit
                edit.installEventFilter(self)

                lo.addWidget(label, i, 0)
                lo.addWidget(edit, i, 1)
                lo.addWidget(checkbox, i, 2, Qt.AlignCenter)
                i += 1
                for w in [option.label, option.edit]:
                    w.setToolTip(option.long_descr)

                if isinstance(edit, QCheckBox):
                    edit.stateChanged.connect(self.on_edited)
                else:
                    edit.textEdited.connect(self.on_edited)

                    # todo No consensus yet if it is better to show the default values
                    # option.update_edit_with_default()
            except:
                a99.get_python_logger().exception("Processing option '%s'" %
                                                  option.name)
                raise
        self.__update_from_data(pyfant.FileOptions(), True)

        # ### Second widget of splitter
        # layout containing description area and a error label
        wlu = QWidget()
        lu = QVBoxLayout(wlu)
        a99.set_margin(lu, 0)
        lu.setSpacing(4)
        x = self.textEditDescr = QTextEdit(self)
        x.setReadOnly(True)
        # x.setGeometry(0, 0, 100, 0)
        # x.setWordWrap(True)
        x.setStyleSheet("QTextEdit {color: %s}" % a99.COLOR_DESCR)
        lu.addWidget(x)

        x = self.labelError = QLabel(self)
        x.setStyleSheet("QLabel {color: %s}" % a99.COLOR_ERROR)
        lu.addWidget(x)

        sp.addWidget(wlu)

        # ### Adjust splitter proportion
        sp.setStretchFactor(0, 8)
        sp.setStretchFactor(1, 2)

        self.__update_gui_visible_options()
        a99.style_checkboxes(self)
        self.setEnabled(False)  # disabled until load() is called
        self.flag_process_changes = True
Пример #8
0
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.f = None  # FileAtoms object
        self.flag_sort = False
        self.atom_index = None
        self.atom = None  # Atom instance
        self.flag_changed = False
        self.save_dir = "."
        # Form with the table to edit the lines
        self.form_lines = None
        self.form_histogram = None

        # Information about the plots
        self.marker_row = None  # points into current atom, self.atom
        self.plot_info = [PlotInfo() for _ in range(NUM_PLOTS)]
        # keptself.set_flag_plot(ATOM_ATTR_NAMES.index("kiex")-1, True)
        self.set_flag_plot(ATOM_ATTR_NAMES.index("algf") - 1, True)

        # ** "Atoms browser"

        # ** ** left of splitter
        self.labelAtoms = QLabel('Atoms list (Ctrl+1)')
        a = self.listWidgetAtoms = QListWidget()
        a.currentRowChanged.connect(self.on_listWidgetAtoms_currentRowChanged)
        # a.setEditTriggers(QAbstractItemView.DoubleClicked)
        # a.setEditTriggers(QAbstractItemView.AllEditTriggers)
        a.setContextMenuPolicy(Qt.CustomContextMenu)

        self.labelAtoms.setBuddy(self.listWidgetAtoms)

        l = self.layoutAtoms = QVBoxLayout()
        a99.set_margin(l, 0)
        l.setSpacing(1)
        l.addWidget(self.labelAtoms)
        l.addWidget(self.listWidgetAtoms)

        a = self.widgetAtoms = QWidget()
        a.setLayout(self.layoutAtoms)

        # ** ** right of splitter

        # ** ** ** ** Plot widget

        # ** ** ** ** ** Toolbar above plot

        am = self.buttonSort = QPushButton("Sort wave (Alt+&W)")
        am.clicked.connect(self.on_buttonSort_clicked)
        am.setCheckable(True)
        am.setToolTip("Sort spectral lines in ascending order of wavelength")
        if self.flag_sort:
            am.setChecked(True)

        # adds checkable buttons sj, jj
        self.plot_buttons = bb = []
        for i in range(NUM_PLOTS):  # sj, jj etc
            s = ATOM_HEADERS[i + 1]
            b = QPushButton("%s (Alt+&%d)" % (s, i + 1))
            b.clicked.connect(self.on_button_plot_clicked)
            b.setCheckable(True)
            if self.flag_plot(i):
                b.setChecked(True)
            bb.append(b)

        a11 = self.buttonEditLines = QPushButton("Edit lines (Ctrl+3)")
        a11.clicked.connect(self.on_buttonEditLines_clicked)
        a2 = self.labelNumLines = QLabel("--")
        a3 = self.spacer0 = QSpacerItem(0, 0, QSizePolicy.Expanding,
                                        QSizePolicy.Minimum)

        l0 = self.layoutPlotToolbar = QHBoxLayout()
        l0.addWidget(am)
        for b in bb:
            l0.addWidget(b)
        l0.addWidget(a11)
        l0.addWidget(a2)
        l0.addItem(a3)
        a99.set_margin(l0, 1)
        a = self.widgetPlotToolbar = QWidget()
        a.setLayout(l0)
        a.setFixedHeight(40)

        # ** ** ** ** ** ** Plot widget

        # http://stackoverflow.com/questions/12459811
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.canvas.mpl_connect('button_press_event', self.on_plot_click)
        self.toolbar = NavigationToolbar2QT(self.canvas, self)
        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        a99.set_margin(layout, 0)

        a = self.widgetPlot = QWidget()
        a.setLayout(layout)

        l1 = self.layoutPlot = QVBoxLayout()
        l1.addWidget(self.widgetPlotToolbar)
        l1.addWidget(self.widgetPlot)
        a99.set_margin(l1, 0)

        a = self.widgetPlot = QWidget()
        a.setLayout(l1)

        # ** splitter: (list of Atoms) | (plot)
        a = self.splitter = QSplitter(Qt.Horizontal)
        a.addWidget(self.widgetAtoms)
        a.addWidget(self.widgetPlot)
        a.setStretchFactor(0, 2)
        a.setStretchFactor(1, 10)

        # * # * # * # * # * # * # *
        # Now the menu bar

        # self.menubar = QMenuBar(self)
        # self.menubar.setGeometry(QRect(0, 0, 772, 18))
        # self.menubar.setObjectName(_fromUtf8("menubar"))
        b = self.menuBar()
        m = self.menu_file = b.addMenu("&File")
        self.act_save = ac = m.addAction("&Save")
        ac.setShortcut("Ctrl+S")
        ac.triggered.connect(self.on_save)
        self.act_save_as = ac = m.addAction("Save &as...")
        ac.setShortcut("Ctrl+Shift+S")
        ac.triggered.connect(self.on_save_as)
        m.addSeparator()
        ac = m.addAction("&Quit")
        ac.setShortcut("Ctrl+Q")
        ac.triggered.connect(self.close)

        m = self.menu_tools = b.addMenu("&Tools")
        self.act_save = ac = m.addAction("&Histogram")
        ac.triggered.connect(self.on_histogram)

        # * # * # * # * # * # * # *
        # Final adjustments

        self.splitter.setFont(a99.MONO_FONT)
        self.setCentralWidget(self.splitter)
        a99.place_left_top(self)
Пример #9
0
    def __init__(self, *args):
        a99.WBase.__init__(self, *args)

        self._molconsts = pyfant.MolConsts()
        self._flag_valid = True

        # activated when populating table
        self._flag_populating = False
        # # _flag_populating_* collection
        self._flag_populating_molecule = False
        self._flag_populating_system = False
        self._flag_populating_states = False
        self._flag_populating_pfantmol = False
        self._flag_updating_gui = False

        # activated when searching for statel, state2l
        self._flag_searching_states = False
        # activated when searching for pfantmol
        self._flag_searching_pfantmol = False
        # activated when searching for system
        self._flag_searching_system = False

        # # Internal state

        # FileMolDB object, auxiliary object needed for operations
        self._moldb = None

        # Fields of interest from table 'pfantmol'
        # TODO cro disabled but still left to get rid of this field in the same way I got rid of pfantmol.s
        self._fieldnames_pfantmol = [
            "fe",
            "do",
            "am",
            "bm",
            "ua",
            "ub",
            "te",
        ]
        # Fields of interest from table 'state'
        self._fieldnames_state = [
            "omega_e", "omega_ex_e", "omega_ey_e", "B_e", "alpha_e", "D_e",
            "beta_e", "A"
        ]
        # Fields of interest from table 'system'
        self._fieldnames_system = [
            "from_label", "from_mult", "from_spdf", "to_label", "to_mult",
            "to_spdf"
        ]
        self._flag_built_edits = False
        for fn in self._fieldnames_state:
            assert fn not in self._fieldnames_pfantmol
            assert fn not in self._fieldnames_system
        for fn in self._fieldnames_pfantmol:
            assert fn not in self._fieldnames_system
        self._fieldnames = [
        ]  # will be filled in later copy.copy(self._fieldnames_pfantmol)
        # self._fieldnames.extend(self._fieldnames_state)
        # self._fieldnames.extend(self._fieldnames_system)

        # dictionary {(field name): (edit object), }
        # (will be populated later below together with edit widgets creation)
        self._edit_map = {}
        self._edit_map_statel = {}
        self._edit_map_state2l = {}
        self._edit_map_pfantmol = {}
        self._edit_map_system = {}

        # id from table 'molecule'. In sync with combobox_molecule items
        self._ids_molecule = []
        # id from table 'pfantmol'. In sync with combobox_pfantmol
        self._ids_pfantmol = []
        # id from table 'state'. In sync with combobox_statel and combobox_state2l
        self._ids_state = []
        # id from table 'system'. In sync with combobox_system
        self._ids_system = []

        # # GUI design

        l = self.layout_main = QVBoxLayout(self)
        a99.set_margin(l, _LAYMN_MAIN)
        l.setSpacing(_LAYSP_MAIN)

        # ## Select molecule combobox
        l0 = self.layout_molecule = QHBoxLayout()
        l.addLayout(l0)
        l0.setSpacing(_LAYSP_CB)
        la = self.label_molecule = QLabel()
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        l0.addWidget(la)
        cb = self.combobox_molecule = QComboBox()
        cb.currentIndexChanged.connect(
            self.combobox_molecule_currentIndexChanged)
        l0.addWidget(cb)

        la.setBuddy(cb)

        # ## Frame with the combobox to select the "system"

        fr = self.frame_system = a99.get_frame()
        l.addWidget(fr)
        l1 = self.layout_frame_system = QVBoxLayout(fr)
        l1.setSpacing(_LAYSP_V)
        a99.set_margin(l1, _LAYMN_V)

        # ### Select system combobox
        l2 = self.layout_system = QHBoxLayout()
        l1.addLayout(l2)
        l2.setSpacing(_LAYSP_CB)
        la = self.label_system = QLabel()
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        l2.addWidget(la)
        cb = self.combobox_system = QComboBox()
        cb.currentIndexChanged.connect(
            self.combobox_system_currentIndexChanged)
        l2.addWidget(cb)

        la.setBuddy(cb)

        la = self.label_fcf = QLabel()
        la.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        l2.addWidget(la)

        # ### State constants edit fields

        lg = self.layout_grid_system = QGridLayout()
        l1.addLayout(lg)
        a99.set_margin(lg, _LAYMN_GRID)
        lg.setSpacing(_LAYSP_GRID)

        # #### Frame for pfantmol combobox end edit fields

        lfp = self.layout_outer_frame_pfantmol = QVBoxLayout()
        l1.addLayout(lfp)
        lfp.setSpacing(_LAYSP_FRAME1)
        lfp.setContentsMargins(
            _LAYMN_FRAME1,
            0,
            _LAYMN_FRAME1,
            _LAYMN_FRAME1,
        )

        fr = self.frame_pfantmol = a99.get_frame()
        lfp.addWidget(fr)
        l5 = self.layout_frame_pfantmol = QVBoxLayout(fr)
        l5.setSpacing(_LAYSP_V)
        a99.set_margin(l5, _LAYMN_V)

        # ##### Label and combobox in H layout
        l55 = self.layout_pfantmol = QHBoxLayout()
        l5.addLayout(l55)
        l55.setSpacing(_LAYSP_CB)

        la = self.label_pfantmol = QLabel("<b>&PFANT molecule</b>")
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        l55.addWidget(la)

        cb = self.combobox_pfantmol = QComboBox()
        cb.currentIndexChanged.connect(
            self.combobox_pfantmol_currentIndexChanged)
        l55.addWidget(cb)

        la.setBuddy(cb)

        # ##### PFANT Molecular constants edit fields
        lg = self.layout_grid_pfantmol = QGridLayout()
        a99.set_margin(lg, _LAYMN_GRID)
        lg.setSpacing(_LAYSP_GRID)
        l5.addLayout(lg)

        # #### Statel and State2l

        fr = self.frame_states = a99.get_frame()
        self.layout_main.addWidget(fr)

        l33 = self.layout_frame_states = QVBoxLayout(fr)
        l33.setSpacing(_LAYSP_V)
        a99.set_margin(l33, _LAYMN_V)

        la = self.label_states = QLabel(
            "<b>Constants for individual states</b>")
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        l33.addWidget(la)

        # This layout will have two frames layed horizontally
        lll = self.layout_states = QHBoxLayout()
        lll.setSpacing(_LAYSP_FRAME1)
        lll.setContentsMargins(
            _LAYMN_FRAME1,
            0,
            _LAYMN_FRAME1,
            _LAYMN_FRAME1,
        )
        l33.addLayout(lll)

        # ##### Frame for Diatomic molecular constants for statel

        fr = self.frame_statel = a99.get_frame()
        lll.addWidget(fr)
        l3 = self.layout_frame_statel = QVBoxLayout(fr)
        l3.setSpacing(_LAYSP_V)
        a99.set_margin(l3, _LAYMN_V)

        # ###### Select statel combobox
        l4 = self.layout_statel = QHBoxLayout()
        l3.addLayout(l4)
        l4.setSpacing(_LAYSP_CB)
        la = self.label_statel = QLabel(
            "<b>Diatomic molecular constants for state'</b>")
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        l4.addWidget(la)
        cb = self.combobox_statel = QComboBox()
        cb.currentIndexChanged.connect(
            self.combobox_statel_currentIndexChanged)
        l4.addWidget(cb)

        la.setBuddy(cb)

        # ###### Statel edit fields

        lg = self.layout_grid_statel = QGridLayout()
        a99.set_margin(lg, _LAYMN_GRID)
        lg.setSpacing(_LAYSP_GRID)
        l3.addLayout(lg)

        # ##### Frame for Diatomic molecular constants for state2l

        fr = self.frame_state2l = a99.get_frame()
        lll.addWidget(fr)
        l3 = self.layout_frame_state2l = QVBoxLayout(fr)
        l3.setSpacing(_LAYSP_V)
        a99.set_margin(l3, _LAYMN_V)

        # ###### Select state2l combobox
        l4 = self.layout_state2l = QHBoxLayout()
        l3.addLayout(l4)
        l4.setSpacing(_LAYSP_CB)
        la = self.label_state2l = QLabel(
            "<b>Diatomic molecular constants for state''</b>")
        la.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        l4.addWidget(la)
        cb = self.combobox_state2l = QComboBox()
        cb.currentIndexChanged.connect(
            self.combobox_state2l_currentIndexChanged)
        l4.addWidget(cb)

        la.setBuddy(cb)

        # ###### State2l edit fields

        lg = self.layout_grid_state2l = QGridLayout()
        a99.set_margin(lg, _LAYMN_GRID)
        lg.setSpacing(_LAYSP_GRID)
        l3.addLayout(lg)

        # ## Toolbar at bottom
        self.layout_toolbar = self._get_toolbar_bottom()

        a99.nerdify(self)
Пример #10
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        # Whether all the values in the fields are valid or not
        self.flag_valid = False
        # Internal flag to prevent taking action when some field is updated programatically
        self.flag_process_changes = False
        self.f = None  # FileAbonds object

        # Internals
        d = self.__default_dissoc = pyfant.FileDissoc()
        d.init_default()

        la = self.formLayout = QVBoxLayout()
        a99.set_margin(la, 0)
        la.setSpacing(4)

        self.setLayout(la)

        # # Sort/Insert/append/delete toolbar

        l = self.c29378 = QHBoxLayout()
        la.addLayout(l)
        a99.set_margin(l, 0)
        l.setSpacing(4)
        b = self.button_sort_a = QPushButton("Sort &alphabetically")
        l.addWidget(b)
        b.clicked.connect(self.on_sort_a)
        b = self.button_sort_z = QPushButton("Sort by atomic &number")
        l.addWidget(b)
        b.clicked.connect(self.on_sort_z)
        l.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))

        l = self.c34985 = QHBoxLayout()
        la.addLayout(l)
        a99.set_margin(l, 0)
        l.setSpacing(4)
        b = self.button_insert = QPushButton("&Insert")
        l.addWidget(b)
        b.clicked.connect(self.on_insert)
        b = self.button_append = QPushButton("A&ppend")
        l.addWidget(b)
        b.clicked.connect(self.on_append)
        b = self.button_delete = QPushButton("&Delete")
        l.addWidget(b)
        b.clicked.connect(self.on_delete)
        l.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))

        # # Splitter notes box; the table; and the errors area

        sp = self.splitter = QSplitter(Qt.Vertical)
        la.addWidget(sp)

        # # Edit box for the notes

        w = self.c3f1x2 = QWidget()
        sp.addWidget(w)
        l = self.c114_2 = QHBoxLayout(w)
        a99.set_margin(l, 0)
        l.setSpacing(4)
        label = self.c33_1 = QLabel("&Notes")
        l.addWidget(label)
        edit = self.textEditNotes = QPlainTextEdit()
        edit.textChanged.connect(self.on_textEditNotes_textChanged)
        l.addWidget(edit)
        label.setBuddy(edit)
        T = "Use this space to write annotations such as references"
        label.setToolTip(T)
        edit.setToolTip(T)

        # ## The table widget

        a = self.tableWidget = QTableWidget()
        sp.addWidget(a)
        a.setSelectionMode(QAbstractItemView.SingleSelection)
        # a.currentCellChanged.connect(self.on_tableWidget_currentCellChanged)
        a.cellChanged.connect(self.on_tableWidget_cellChanged)
        a.setEditTriggers(QAbstractItemView.DoubleClicked
                          | QAbstractItemView.EditKeyPressed)
        a.setFont(a99.MONO_FONT)
        a.installEventFilter(self)

        # ## The errors area

        w = self.csslff = QWidget()
        sp.addWidget(w)
        l = self.c49378 = QVBoxLayout(w)
        a99.set_margin(l, 0)
        l.setSpacing(1)

        x = self.c88888 = QLabel("<b>Errors</b>")
        l.addWidget(x)

        x = self.textEditError = QTextEdit(self)
        l.addWidget(x)
        x.setReadOnly(True)
        x.setStyleSheet("QTextEdit {color: %s}" % a99.COLOR_ERROR)
        x.setFont(a99.MONO_FONT)

        # ## Splitter stretch factors
        # These need to be set a posteriori otherwise they do
        # not work properly.
        sp.setStretchFactor(0, 0)
        sp.setStretchFactor(1, 1)
        sp.setStretchFactor(2, 0)

        # finally...
        self.setEnabled(False)  # Disabled until load() is called
        self.flag_process_changes = True
Пример #11
0
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.f = None  # FileMolecules object
        self.flag_sort = False
        self.mol_index = None
        self.sol_index = None
        self.mol = None
        self.sol = None
        self.save_dir = "."
        self.flag_changed = False
        self.form_lines = None

        # Information about the plots
        self.marker_row = None  # points into current set-of-lines, self.sol
        self.plot_info = [PlotInfo() for _ in range(NUM_PLOTS)]
        self.set_flag_plot(SOL_ATTR_NAMES.index("sj")-1, True)
        self.set_flag_plot(SOL_ATTR_NAMES.index("jj")-1, True)

        # ** tab "General file info"
        a = self.plainTextEditFileInfo = QPlainTextEdit()
        a.setFont(a99.MONO_FONT)


        # ** "Molecules browser"

        # ** ** left of splitter
        self.labelMol = QLabel('Molecules list (Ctrl+1)')
        a = self.listWidgetMol = QListWidget()
        a.currentRowChanged.connect(self.on_listWidgetMol_currentRowChanged)
        # a.setEditTriggers(QAbstractItemView.DoubleClicked)
        # a.setEditTriggers(QAbstractItemView.AllEditTriggers)
        a.setContextMenuPolicy(Qt.CustomContextMenu)
        a.customContextMenuRequested.connect(self.on_listWidgetMol_customContextMenuRequested)
        a.itemDoubleClicked.connect(self.on_listWidgetMol_doubleClicked)
        a.installEventFilter(self)

        l = self.layoutMol = QVBoxLayout()
        a99.set_margin(l, 0)
        l.setSpacing(1)
        l.addWidget(self.labelMol)
        l.addWidget(self.listWidgetMol)

        a = self.widgetMol = QWidget()
        a.setLayout(self.layoutMol)


        # ** ** right of splitter

        # ** ** ** tab "Molecule info"
        a = self.plainTextEditMolInfo = QPlainTextEdit()
        a.setFont(a99.MONO_FONT)

        # ** ** ** tab "Molecular lines"

        # ** ** ** ** left

        # P = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
        self.labelSol = QLabel('Sets of lines (Ctrl+2)')

        a = self.listWidgetSol = QListWidget()
        a.setFont(a99.MONO_FONT)
        # a.setFixedWidth(100)
        a.currentRowChanged.connect(self.on_listWidgetSol_currentRowChanged)
        a.setContextMenuPolicy(Qt.CustomContextMenu)
        a.customContextMenuRequested.connect(self.on_listWidgetSol_customContextMenuRequested)
        a.itemDoubleClicked.connect(self.on_listWidgetSol_doubleClicked)
        a.installEventFilter(self)

        l = self.layoutSol = QVBoxLayout()
        a99.set_margin(l, 0)
        l.setSpacing(1)
        l.addWidget(self.labelSol)
        l.addWidget(self.listWidgetSol)

        a = self.widgetSol = QWidget()
        a.setLayout(self.layoutSol)

        # ** ** ** ** right

        # ** ** ** ** ** Toolbar above plot

        am = self.buttonSort = QPushButton("Sort wave (Alt+&W)")
        am.clicked.connect(self.on_buttonSort_clicked)
        am.setCheckable(True)
        am.setToolTip("Sort spectral lines in ascending order of wavelength")
        if self.flag_sort:
            am.setChecked(True)

        # adds checkable buttons sj, jj
        self.plot_buttons = bb = []
        for i in range(NUM_PLOTS):  # sj, jj etc
            s = SOL_HEADERS[i+1]
            b = QPushButton("%s (Alt+&%d)" % (s, i+1))
            b.clicked.connect(self.on_button_plot_clicked)
            b.setCheckable(True)
            if self.flag_plot(i):
                b.setChecked(True)
            bb.append(b)

        a11 = self.buttonEditLines = QPushButton("Edit lines (Ctrl+3)")
        a11.clicked.connect(self.on_buttonEditLines_clicked)
        a2 = self.labelNumLines = QLabel("--")
        a3 = self.spacer0 = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)

        l0 = self.layoutSolToolbar = QHBoxLayout()
        l0.addWidget(am)
        for b in bb:
            l0.addWidget(b)
        l0.addWidget(a11)
        l0.addWidget(a2)
        l0.addItem(a3)
        a99.set_margin(l0, 1)
        a = self.widgetSolToolbar = QWidget()
        a.setLayout(l0)
        a.setFixedHeight(40)

        # ** ** ** ** ** Set-of-lines info + Plot TABS

        # ** ** ** ** ** ** tab "Set-of-lines info"
        a = self.plainTextEditSolInfo = QPlainTextEdit()
        a.setFont(a99.MONO_FONT)

        # ** ** ** ** ** ** Plot tab

        # http://stackoverflow.com/questions/12459811
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.canvas.mpl_connect('button_press_event', self.on_plot_click)
        self.toolbar = NavigationToolbar2QT(self.canvas, self)
        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        a99.set_margin(layout, 0)

        a = self.widgetSolPlot = QWidget()
        a.setLayout(layout)

        l1 = self.layoutSolPlot = QVBoxLayout()
        l1.addWidget(self.widgetSolToolbar)
        l1.addWidget(self.widgetSolPlot)
        a99.set_margin(l1, 0)

        a = self.widgetSolPlot = QWidget()
        a.setLayout(l1)


        # ** ** ** ** **  Set-of-lines info + Plot TABS
        a = self.tabWidgetSol = QTabWidget(self)
        a.addTab(self.plainTextEditSolInfo, "Set-of-lines Info (Alt+&N)")
        a.addTab(self.widgetSolPlot, "Set-of-lines plots (Alt+&P)")
        a.setCurrentIndex(1)
        a.setFont(a99.MONO_FONT)

        # ** ** ** ** ** splitter: (list of set-of-lines) | (plot)
        a = self.splitterSol = QSplitter(Qt.Horizontal)
        a.addWidget(self.widgetSol)
        a.addWidget(self.tabWidgetSol)
        a.setStretchFactor(0, 2)
        a.setStretchFactor(1, 10)

        a = self.tabWidgetMol = QTabWidget()
        a.addTab(self.plainTextEditMolInfo, "Molecule info (Alt+&M)")
        a.addTab(self.splitterSol, "Sets of lines (Alt+&L)")
        a.setCurrentIndex(1)
        a.setFont(a99.MONO_FONT)

        # ** splitter: (list of molecules) | (molecules tab widget)
        a = self.splitterMol = QSplitter(Qt.Horizontal)
        a.addWidget(self.widgetMol)
        a.addWidget(self.tabWidgetMol)
        a.setStretchFactor(0, 2)
        a.setStretchFactor(1, 10)

        # tab "File" (main tab widget
        a = self.tabWidgetFile = QTabWidget(self)
        a.addTab(self.plainTextEditFileInfo, "General File Info (Alt+&I)")
        a.addTab(self.splitterMol, "Molecules Browser (Alt+&B)")
        a.setCurrentIndex(1)
        a.setFont(a99.MONO_FONT)


        # * # * # * # * # * # * # *
        # Now the menu bar

        # self.menubar = QMenuBar(self)
        # self.menubar.setGeometry(QRect(0, 0, 772, 18))
        # self.menubar.setObjectName(_fromUtf8("menubar"))
        b = self.menuBar()
        m = self.menu_file = b.addMenu("&File")
        self.act_save = ac = m.addAction("&Save")
        ac.setShortcut("Ctrl+S")
        ac.triggered.connect(self.on_save)
        self.act_save_as = ac = m.addAction("Save &as...")
        ac.setShortcut("Ctrl+Shift+S")
        ac.triggered.connect(self.on_save_as)
        m.addSeparator()
        ac = m.addAction("&Quit")
        ac.setShortcut("Ctrl+Q")
        ac.triggered.connect(self.close)

        # * # * # * # * # * # * # *
        # Final adjustments

        self.setCentralWidget(self.tabWidgetFile)
        a99.place_left_top(self)
Пример #12
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        # Whether all the values in the fields are valid or not
        self.flag_valid = False
        # Internal flag to prevent taking action when some field is updated programatically
        self.flag_process_changes = False
        self.f = None  # FileMain object

        # # Central layout
        la = self.layout_main = QVBoxLayout()
        a99.set_margin(la, 0)
        self.setLayout(la)

        # ## Splitter with scroll area and descripton+error area
        sp = self.splitter = QSplitter(Qt.Vertical)
        la.addWidget(sp)

        # ### Widget + grid layout to be first in splitter
        sa = self.c33441 = QScrollArea()
        sp.addWidget(sa)
        sa.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        sa.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        # Widget that will be handled by the scrollable area
        w = self.scrollWidget = QWidget()
        sa.setWidget(self.scrollWidget)
        sa.setWidgetResizable(True)
        #        la.addWidget(w)

        lw = QVBoxLayout()
        w.setLayout(lw)
        # Form layout
        lg = self.formLayout = QGridLayout()
        lw.addLayout(lg)
        a99.set_margin(lg, 0)
        lg.setVerticalSpacing(4)
        lg.setHorizontalSpacing(5)
        lw.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding))

        # field map: [(label widget, edit widget, field name, short description,
        #              field name color, long description), ...]
        map = self._map = []

        x = self.label_titrav = QLabel()
        y = self.lineEdit_titrav = QLineEdit()
        # y.editingFinished.connect(self._on_editing_finished)
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        x.setBuddy(y)
        map.append(
            (x, y, "t&itrav", "star name", COLOR_STAR, "Name of the star"))

        x = self.label_teff = QLabel()
        y = self.lineEdit_teff = QLineEdit()
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        y.setValidator(QDoubleValidator(0, 1e10, 0))
        x.setBuddy(y)
        map.append(
            (x, y, "&teff", "effective temperature", COLOR_STAR, "Sun: 5777"))

        x = self.label_glog = QLabel()
        y = self.lineEdit_glog = QLineEdit()
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        y.setValidator(QDoubleValidator(0, 1e10, 5))
        x.setBuddy(y)
        map.append((x, y, "&glog", "gravity", COLOR_STAR, "Sun: 4.44"))

        x = self.label_asalog = QLabel()
        y = self.lineEdit_asalog = QLineEdit()
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        y.setValidator(QDoubleValidator(-10, 10, 5))
        x.setBuddy(y)
        map.append((x, y, "&asalog", "metallicity", COLOR_STAR, "Sun: 0"))

        x = self.label_vvt = QLabel()
        y = self.lineEdit_vvt = QLineEdit()
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        y.setValidator(QDoubleValidator(0, 900, 2))
        x.setBuddy(y)
        map.append((x, y, "&vvt", "velocity of microturbulence", COLOR_STAR,
                    "Sun: 0.9"))

        x = self.label_nhe = QLabel()
        y = self.lineEdit_nhe = QLineEdit()
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        y.setValidator(QDoubleValidator(0, 10, 5))
        x.setBuddy(y)
        map.append(
            (x, y, "&nhe", "abundance of Helium", COLOR_STAR, "Sun: 0.1"))

        x = self.label_ptdisk = QLabel()
        y = self.checkBox_ptdisk = QCheckBox()
        y.setTristate(False)
        y.installEventFilter(self)
        y.stateChanged.connect(self.on_edited)
        x.setBuddy(y)
        map.append(
            (x, y, "pt&disk", "point of disk?", COLOR_CONFIG, DESCR_PTDISK))

        x = self.label_mu = QLabel()
        y = self.lineEdit_mu = QLineEdit()
        y.installEventFilter(self)
        y.textEdited.connect(self.on_edited)
        y.setValidator(QDoubleValidator(-1, 1, 5))
        x.setBuddy(y)
        map.append((
            x, y, "&mu", "cosine of angle", COLOR_CONFIG,
            "This is the cosine of the angle formed by center of "
            "the star disk, the point of observation, and the Earth as vertex. "
            "<br><br>This value will be used only if " +
            a99.enc_name("ptdisk", COLOR_CONFIG) + " is True.<br>\n<pre>\n"
            "             point of observation   \n"
            "            /                       \n"
            "           /                        \n"
            "          /                         \n"
            "         /                          \n"
            "        /                           \n"
            "       / ) acos(mu)                 \n"
            "Earth /------------------- center of star disk\n</pre>"))

        x = self.label_flprefix = QLabel()
        y = self.lineEdit_flprefix = QLineEdit()
        # y.editingFinished.connect(self._on_editing_finished)
        y.textEdited.connect(self.on_edited)
        y.installEventFilter(self)
        x.setBuddy(y)
        map.append((x, y, "flprefi&x", "prefix of filename", COLOR_CONFIG,
                    "pfant will create three output files:<ul>"
                    "<li>" + a99.enc_name("flprefix", COLOR_CONFIG) +
                    ".cont (continuum),"
                    "<li>" + a99.enc_name("flprefix", COLOR_CONFIG) +
                    ".norm (normalized spectrum), and"
                    "<li>" + a99.enc_name("flprefix", COLOR_CONFIG) +
                    ".spec (continuum*normalized)</ul>"))

        x = self.label_pas = QLabel()
        y = self.lineEdit_pas = QLineEdit()
        y.installEventFilter(self)
        y.textEdited.connect(self.on_edited)
        y.setValidator(QDoubleValidator(0, 10, 5))
        x.setBuddy(y)
        map.append((
            x, y, "&pas", "calculation step (&Aring;)", COLOR_CONFIG,
            "The synthetic spectrum will have points " +
            a99.enc_name("pas", COLOR_CONFIG) + " &Aring; distant from "
            "each other.<br><br>Use this to specify the resolution of the synthetic spectrum."
        ))

        x = self.label_llzero = QLabel()
        y = self.lineEdit_llzero = QLineEdit()
        y.installEventFilter(self)
        y.textEdited.connect(self.on_edited)
        y.setValidator(QDoubleValidator(0, 10, 5))
        x.setBuddy(y)
        map.append(
            (x, y, "ll&zero", "lower boundary of synthesis interval (&Aring;)",
             COLOR_CONFIG, LLZERO_LLFIN))

        x = self.label_llfin = QLabel()
        y = self.lineEdit_llfin = QLineEdit()
        y.installEventFilter(self)
        y.textEdited.connect(self.on_edited)
        y.setValidator(QDoubleValidator(0, 10, 5))
        x.setBuddy(y)
        map.append(
            (x, y, "&llfin", "upper boundary of synthesis interval (&Aring;)",
             COLOR_CONFIG, LLZERO_LLFIN))

        x = self.label_aint = QLabel()
        y = self.lineEdit_aint = QLineEdit()
        y.installEventFilter(self)
        y.textEdited.connect(self.on_edited)
        y.setValidator(QDoubleValidator(0, 10, 5))
        x.setBuddy(y)
        map.append(
            (x, y, "&aint", "length of sub-interval (&Aring;)", COLOR_CONFIG,
             "This is length of each calculation sub-interval "
             "(the calculation interval [" +
             a99.enc_name("llzero", COLOR_CONFIG) + ", " +
             a99.enc_name("llfin", COLOR_CONFIG) +
             "] is split in sub-intervals of roughly " +
             a99.enc_name("aint", COLOR_CONFIG) + " &Aring;)."
             "<br><br>Note: " + a99.enc_name("aint", COLOR_CONFIG) +
             " must be a multiple of " + a99.enc_name("pas", COLOR_CONFIG) +
             "." + LLZERO_LLFIN))

        x = self.label_fwhm = QLabel()
        y = self.lineEdit_fwhm = QLineEdit()
        y.installEventFilter(self)
        y.textEdited.connect(self.on_edited)
        y.setValidator(QDoubleValidator(0, 10, 5))
        x.setBuddy(y)
        map.append((
            x, y, "f&whm", "convolution full-width-half-maximum", COLOR_CONFIG,
            "This parameter specifies the full-width-half-maximum "
            "of a Gaussian curve to convolve the synthetic spectrum with. <br><br>It is "
            "used by <em>nulbad</em> (Fortran code that calculates such convolution)."
        ))

        for i, (label, edit, name, short_descr, color,
                long_descr) in enumerate(map):
            # label.setStyleSheet("QLabel {text-align: right}")
            assert isinstance(label, QLabel)
            label.setText(a99.enc_name_descr(name, short_descr, color))
            label.setAlignment(Qt.AlignRight)
            lg.addWidget(label, i, 0)
            lg.addWidget(edit, i, 1)
            label.setToolTip(long_descr)
            edit.setToolTip(long_descr)

        # ### Second widget of splitter
        # layout containing description area and a error label
        wlu = QWidget()
        lu = QVBoxLayout(wlu)
        a99.set_margin(lu, 0)
        lu.setSpacing(1)
        x = self.c23862 = QLabel("<b>Help</b>")
        lu.addWidget(x)
        x = self.textEditDescr = QTextEdit(self)
        x.setReadOnly(True)
        x.setStyleSheet("QTextEdit {color: %s}" % a99.COLOR_DESCR)
        lu.addWidget(x)
        x = self.c23862 = QLabel("<b>Errors</b>")
        lu.addWidget(x)
        x = self.labelError = QLabel(self)
        x.setStyleSheet("QLabel {color: %s}" % a99.COLOR_ERROR)
        lu.addWidget(self.labelError)
        sp.addWidget(wlu)

        self.setEnabled(False)  # disabled until load() is called
        a99.style_checkboxes(self)
        self.flag_process_changes = True