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)
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)
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
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()
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), ]
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)
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é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 (Å)", 'default: <main_llzero> ' + _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 (Å)', 'default: <main_llfin> ' + _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 (Å)', 'default: <main_aint> ' + _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 (Å)', 'default: <main_pas> ' + _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: <main_flprefix> ' + _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: <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: <flux file name>.nulbad.<fwhm>') self.__add_option( self.w_pat, 'n', 'pat', 0.02, 'wavelength delta-lambda of nulbad output spectrum (Å)', '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: <main_fwhm> ' + _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
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)
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)
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
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)
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 (Å)", COLOR_CONFIG, "The synthetic spectrum will have points " + a99.enc_name("pas", COLOR_CONFIG) + " Å 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 (Å)", 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 (Å)", 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 (Å)", 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) + " Å)." "<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