Ejemplo n.º 1
0
    def on_subtractBtn_clicked(self):
        from ufit.gui.scanitem import ScanDataItem
        dlg = QDialog(self)
        loadUi(dlg, 'subtract.ui')
        data2obj = dlg.setList.populate(ScanDataItem)
        if dlg.exec_() != QDialog.Accepted:
            return
        witems = dlg.setList.selectedItems()
        if not witems:
            return
        try:
            prec = float(dlg.precisionEdit.text())
        except ValueError:
            QMessageBox.warning(self, 'Error',
                                'Please enter a valid precision.')
            return

        new_data = self.data.subtract(data2obj[witems[0].type()].data, prec,
                                      dlg.destructBox.isChecked())

        if not dlg.destructBox.isChecked():
            new_model = self.model.copy()
            from ufit.gui.scanitem import ScanDataItem
            session.add_item(ScanDataItem(new_data, new_model),
                             self.item.group)
        else:
            self.replotRequest.emit(None)
            session.set_dirty()
Ejemplo n.º 2
0
 def _update_settings(self):
     """Update settings from controls."""
     s = self.item.settings
     old_title = s.title
     title = s.title = self.titleBox.text()
     if title != old_title:
         self.item.update_htmldesc()
     xaxis = str(self.xaxisBox.currentText())
     yaxis = str(self.yaxisBox.currentText())
     if xaxis != s.xaxis or yaxis != s.yaxis:
         # new axes selected => discard limits on replot
         self.mapdata = None
     if xaxis == yaxis:
         QMessageBox.warning(self, 'Error', 'Please select distinct X '
                             'and Y axes.')
         return
     s.xaxis = xaxis
     s.yaxis = yaxis
     s.interp = self.stepBox.value()
     s.zmin = maybe_float(self.zminEdit.text(), -1e300)
     s.zmax = maybe_float(self.zmaxEdit.text(), 1e300)
     s.yscale = maybe_float(self.scaleEdit.text(), 1.0)
     s.usemask = self.usemaskBox.isChecked()
     s.dots = self.dotsBox.isChecked()
     s.contour = self.contourBox.isChecked()
     s.logz = self.logBox.isChecked()
     s.gauss2d = self.fitBox.isChecked()
     session.set_dirty()
Ejemplo n.º 3
0
    def on_fftBtn_clicked(self):
        try:
            npoints = int(self.fftNpointsEdit.text())
        except ValueError:
            QMessageBox.warning(self, 'Error',
                                'Please enter a valid number of points.')
            return
        xmin = self.data.x.min()
        xmax = self.data.x.max()
        xinterp = linspace(xmin, xmax, npoints)
        yinterp = interp1d(self.data.x, self.data.y, kind='linear')
        yfft = fft(yinterp(xinterp))
        p2 = abs(yfft) / npoints
        p1 = p2[:npoints // 2 + 2]
        p1[1:-1] *= 2
        dx = (xmax - xmin) / (npoints - 1)

        new_data = ScanData.from_arrays(name='FFT(' + self.data.name + ')',
                                        x=(1. / dx) *
                                        arange(npoints // 2 + 2) / npoints,
                                        y=p1,
                                        dy=0.01 * ones(p1.shape),
                                        xcol='1/' + self.data.xaxis,
                                        ycol='|P1|')
        new_model = self.model.copy()
        from ufit.gui.scanitem import ScanDataItem
        session.add_item(ScanDataItem(new_data, new_model), self.item.group)
Ejemplo n.º 4
0
 def on_mergeBtn_clicked(self):
     try:
         precision = float(self.mergeEdit.text())
     except ValueError:
         QMessageBox.warning(self, 'Error', 'Enter a valid precision.')
         return
     new_data = self.datas[0].merge(precision, *self.datas[1:])
     session.add_item(ScanDataItem(new_data), self.items[-1].group)
Ejemplo n.º 5
0
 def save_session(self):
     if session.filename is None:
         return self.save_session_as()
     try:
         session.save()
     except Exception as err:
         logger.exception('Saving session failed')
         QMessageBox.warning(self, 'Error', 'Saving failed: %s' % err)
         return False
     return True
Ejemplo n.º 6
0
 def on_actionExportParams_triggered(self):
     items = self.selected_items(ScanDataItem)
     dlg = ParamExportDialog(self, items)
     if dlg.exec_() != QDialog.Accepted:
         return
     expfilename = self._get_export_filename()
     if expfilename:
         try:
             dlg.do_export(expfilename)
         except Exception as e:
             logger.exception('While exporting parameters')
             QMessageBox.warning(self, 'Error', 'Could not export '
                                 'parameters: %s' % e)
Ejemplo n.º 7
0
 def on_tbl_itemChanged(self, item):
     if self._updating:
         return
     try:
         new_value = eval(str(item.text()))
     except Exception:
         QMessageBox.error(self, 'Error',
                           'The new value is not a valid expression.')
         return
     else:
         key = str(self.tbl.item(item.row(), 0).text())
         self.data.meta[key] = new_value
     self.replotRequest.emit(None)
     session.set_dirty()
Ejemplo n.º 8
0
 def save_session_as(self):
     initialdir = session.dirname
     filename, _ = QFileDialog.getSaveFileName(self, 'Select file name',
                                               initialdir,
                                               'ufit files (*.ufit)')
     if filename == '':
         return False
     session.set_filename(path_to_str(filename))
     try:
         session.save()
     except Exception as err:
         logger.exception('Saving session failed')
         QMessageBox.warning(self, 'Error', 'Saving failed: %s' % err)
         return False
     return True
Ejemplo n.º 9
0
 def on_rebinBtn_clicked(self):
     try:
         binsize = float(self.precisionEdit.text())
     except ValueError:
         QMessageBox.warning(self, 'Error', 'Enter a valid precision.')
         return
     new_array, new_meta = rebin(self.data._data, binsize, self.data.meta)
     self.data.__init__(new_meta,
                        new_array,
                        self.data.xcol,
                        self.data.ycol,
                        self.data.ncol,
                        self.data.nscale,
                        name=self.data.name,
                        sources=self.data.sources)
     self.replotRequest.emit(None)
     session.set_dirty()
Ejemplo n.º 10
0
    def on_numorHelpBtn_clicked(self):
        QMessageBox.information(
            self, 'Numor Help', '''\
The numor string contains file numbers, with the following operators:

, loads multiple files
- loads multiple sequential files
+ merges multiple files
> merges multiple sequential files

For example:

* 10-15,23  loads files 10 through 15 and 23 in 7 separate datasets.
* 10+11,23+24 loads two datasets consisting of files 10 and 11 merged \
into one set, as well as files 23 and 24.
* 10>15+23 merges files 10 through 15 and 23 into one single dataset.
* 10,11,12+13,14 loads four sets.
''')
Ejemplo n.º 11
0
    def do_fit(self):
        if self.picking:
            QMessageBox.information(self, 'Fitting',
                                    'Please finish the picking operation first.')
            return
        self.update_from_controls()
        self.statusLabel.setText('Working...')
        self.statusLabel.repaint()
        QApplication.processEvents()
        try:
            res = self.model.fit(self.data, **self.fit_kws)
        except Exception as e:
            self.logger.exception('Error during fit')
            self.statusLabel.setText('Error during fit: %s' % e)
            return
        self.on_modelFitted(self.item, res)

        self.replotRequest.emit(True)
        session.set_dirty()
Ejemplo n.º 12
0
 def on_actionRemoveData_triggered(self):
     items = self.selected_items()
     if not items:
         return
     if QMessageBox.question(
             self, 'ufit', 'OK to remove %d item(s)?' % len(items),
             QMessageBox.Yes | QMessageBox.No) == QMessageBox.No:
         return
     session.remove_items(items)
     self.re_expand_tree()
Ejemplo n.º 13
0
 def eval_model(self, final=False):
     modeldef = str(self.modeldefEdit.toPlainText()).replace('\n', ' ')
     if not modeldef:
         QMessageBox.information(self, 'Error', 'No model defined.')
         return
     try:
         model = eval_model(modeldef)
     except Exception as e:
         self.logger.exception('Could not evaluate model')
         QMessageBox.information(self, 'Error',
                                 'Could not evaluate model: %s' % e)
         return
     if final:
         self._finish_picking()
         self.last_model = model
         self.newModel.emit(model, False, True)
         self.closeRequest.emit()
     else:
         self.statusLbl.setText('Model definition is good.')
Ejemplo n.º 14
0
 def exec_callback(self):
     try:
         from ufit.gui.console import ConsoleWindow
     except ImportError:
         logger.exception('Qt console window cannot be opened without '
                          'IPython; import error was:')
         QMessageBox.information(
             self, 'ufit', 'Please install IPython with qtconsole to '
             'activate this function.')
         return
     w = ConsoleWindow(self)
     w.ipython.executeCommand('from ufit.lab import *')
     w.ipython.pushVariables({
         'fig':
         self.canvas.figure,
         'ax':
         self.canvas.figure.gca(),
         'D': [item for group in session.groups for item in group.items],
     })
     w.show()
Ejemplo n.º 15
0
 def check_save(self):
     if not self.isWindowModified():  # nothing there to be saved
         return True
     resp = QMessageBox.question(
         self, 'ufit', 'Save current session?\n%s' % session.filename,
         QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
     if resp == QMessageBox.Yes:
         return self.save_session()
     elif resp == QMessageBox.No:
         return True
     return False
Ejemplo n.º 16
0
    def set_template(self, dtempl, numor, silent=True):
        self.templateEdit.setText(str_to_path(dtempl))
        with self.sgroup as settings:
            settings.setValue('last_data_template', dtempl)
        self.loader.template = dtempl
        try:
            cols, xguess, yguess, dyguess, mguess, nmon = \
                self.loader.guess_cols(numor)
        except Exception as e:
            if not silent:
                self.logger.exception('Could not read column names')
                QMessageBox.information(self, 'Error',
                                        'Could not read column names: %s' % e)
            return
        self.xcolBox.clear()
        self.xcolBox.addItem('auto')
        self.xcolBox.setCurrentIndex(0)
        self.ycolBox.clear()
        self.ycolBox.addItem('auto')
        self.ycolBox.setCurrentIndex(0)
        self.dycolBox.clear()
        self.dycolBox.addItem('auto')
        self.dycolBox.addItem('sqrt(Y)')
        self.dycolBox.setCurrentIndex(0)
        self.moncolBox.clear()
        self.moncolBox.addItem('auto')
        self.moncolBox.addItem('none')
        self.moncolBox.setCurrentIndex(0)
        self.filtercolBox.clear()
        self.filtercolBox.addItem('none')
        self.filtercolBox.setCurrentIndex(0)

        for i, name in enumerate(cols):
            self.xcolBox.addItem(name)
            self.ycolBox.addItem(name)
            self.dycolBox.addItem(name)
            self.moncolBox.addItem(name)
            self.filtercolBox.addItem(name)
        self.monscaleEdit.setText(str(nmon or 1))
        self.numorsEdit.setText(str(numor))
        self.open_data()
Ejemplo n.º 17
0
 def on_actionReorder_triggered(self):
     dlg = QDialog(self)
     loadUi(dlg, 'reorder.ui')
     data2obj = dlg.itemList.populate()
     if not dlg.exec_():
         return
     new_structure = []
     for i in range(dlg.itemList.count()):
         new_index = dlg.itemList.item(i).type()
         obj = data2obj[new_index]
         if isinstance(obj, ItemGroup):
             new_structure.append((obj, []))
         else:
             if not new_structure:
                 QMessageBox.warning(
                     self, 'ufit', 'Reordering invalid: every data item '
                     'must be below a group')
                 return
             new_structure[-1][1].append(obj)
     session.reorder_groups(new_structure)
     self.re_expand_tree()
Ejemplo n.º 18
0
 def load_session(self, filename=None):
     if not filename:
         # Recent files action
         action = self.sender()
         if isinstance(action, QAction):
             if not self.check_save():
                 return
             filename = action.data()
     try:
         session.load(filename)
         with self.sgroup as settings:
             settings.setValue('loadfiledirectory', path.dirname(filename))
     except Exception as err:
         logger.exception('Loading session %r failed' % filename)
         QMessageBox.warning(self, 'Error', 'Loading failed: %s' % err)
     else:
         self.re_expand_tree()
         self.setWindowModified(False)
         # if there are annotations, show the window automatically
         if session.props.get('annotations'):
             self.on_actionAnnotations_triggered()
Ejemplo n.º 19
0
 def on_addCustomBtn_clicked(self):
     dlg = QDialog(self)
     loadUi(dlg, 'custommodel.ui')
     while 1:
         if dlg.exec_() != QDialog.Accepted:
             return
         modelname = str(dlg.nameBox.text())
         params = str(dlg.paramBox.text())
         value = str(dlg.valueEdit.toPlainText()).strip()
         if not ident_re.match(modelname):
             QMessageBox.warning(
                 self, 'Error', 'Please enter a valid model '
                 'name (must be a Python identifier using '
                 'only alphabetic characters and digits).')
             continue
         if not params:
             QMessageBox.warning(self, 'Error',
                                 'Please enter some parameters.')
             continue
         for param in params.split():
             if not ident_re.match(param):
                 QMessageBox.warning(
                     self, 'Error', 'Parameter name %s is not valid (must '
                     'be a Python identifier using only alphabetic '
                     'characters and digits).' % param)
                 params = None
                 break
         if not params:
             continue
         break
     self.insert_model_code('Custom(%r, %r, %r)' %
                            (modelname, params, value))
Ejemplo n.º 20
0
    def save_figure(self, *args):
        filetypes = self.canvas.get_supported_filetypes_grouped()
        sorted_filetypes = sorted(filetypes.items())

        start = self.canvas.get_default_filename()
        filters = []
        for name, exts in sorted_filetypes:
            if 'eps' in exts or 'emf' in exts or 'jpg' in exts or \
               'pgf' in exts or 'raw' in exts:
                continue
            exts_list = " ".join(['*.%s' % ext for ext in exts])
            filter = '%s (%s)' % (name, exts_list)
            filters.append(filter)
        filters = ';;'.join(filters)
        fname, _ = QFileDialog.getSaveFileName(self,
                                               'Choose a filename to save to',
                                               start, filters)
        if fname:
            try:
                self.canvas.print_figure(text_type(fname))
            except Exception as e:
                logger.exception('Error saving file')
                QMessageBox.critical(self, 'Error saving file', str(e))
Ejemplo n.º 21
0
 def rebuild_map(self, quiet=True):
     s = self.item.settings
     try:
         self.mapdata = bin_mapping(s.xaxis,
                                    s.yaxis,
                                    self.item.datas,
                                    usemask=s.usemask,
                                    log=s.logz,
                                    yscale=s.yscale,
                                    interpolate=s.interp,
                                    minmax=(s.zmin, s.zmax))
         return True
     except Exception as err:
         self.logger.exception('While creating mapping')
         if not quiet:
             err_text = str(err)
             # Qhull errors are *very* verbose. Discard everything except
             # the first paragraph.
             err_text = err_text.partition('\n\n')[0]
             QMessageBox.warning(
                 self, 'Mapping error',
                 'Could not create mapping: %s (have you '
                 'selected the right columns?)' % err_text)
         return False
Ejemplo n.º 22
0
 def open_data(self, final=False):
     try:
         prec = float(self.precisionEdit.text())
     except ValueError:
         QMessageBox.information(self, 'Error', 'Enter a valid precision.')
         return
     floatmerge = self.rbFloatMerge.isChecked()
     xcol = str(self.xcolBox.currentText())
     ycol = str(self.ycolBox.currentText())
     dycol = str(self.dycolBox.currentText())
     mcol = str(self.moncolBox.currentText())
     fcol = str(self.filtercolBox.currentText())
     if mcol == 'none':
         mcol = None
     if dycol == 'sqrt(Y)':
         dycol = None
     try:
         mscale = int(self.monscaleEdit.text())
     except Exception:
         QMessageBox.information(self, 'Error',
                                 'Monitor scale must be integer.')
         return
     if fcol == 'none':
         filter = None
     else:
         try:
             val = float(self.filtervalEdit.text())
         except ValueError:
             val = bytes(self.filtervalEdit.text(), 'utf-8')
         filter = {fcol: val}
     dtempl = path_to_str(self.templateEdit.text())
     self.loader.template = dtempl
     numors = str(self.numorsEdit.text())
     try:
         datas = self.loader.load_numors(numors, prec, xcol, ycol, dycol,
                                         mcol, mscale, floatmerge, filter)
     except Exception as e:
         self.logger.exception('Error while loading data file')
         QMessageBox.information(self, 'Error', str(e))
         return
     self.last_data = datas
     if final:
         self.newDatas.emit(datas, self.groupBox.currentText())
         self.closeRequest.emit()
     else:
         self.plot()
Ejemplo n.º 23
0
 def export_python(self, filename):
     QMessageBox.information(self, 'Error', 'Cannot export Python from an '
                             'image.')
Ejemplo n.º 24
0
 def export_fits(self, filename):
     QMessageBox.information(self, 'Error', 'Cannot export fits from an '
                             'image.')
Ejemplo n.º 25
0
 def export_python(self, filename):
     QMessageBox.information(self, 'Error', 'Cannot export Python from a '
                             'mapping.')
Ejemplo n.º 26
0
 def export_fits(self, filename):
     QMessageBox.information(self, 'Error', 'Cannot export fits from a '
                             'mapping.')
Ejemplo n.º 27
0
 def on_globalfitBtn_clicked(self):
     QMessageBox.warning(self, 'Sorry', 'Not implemented yet.')
Ejemplo n.º 28
0
def main():
    app = QApplication([])
    app.setOrganizationName('ufit')
    app.setApplicationName('gui')

    pixmap = QPixmap(':/splash.png')
    splash = QSplashScreen(pixmap, Qt.WindowStaysOnTopHint)
    splash.showMessage(u'Loading...' + u'\xa0' * 10 + '\n\n',
                       Qt.AlignRight | Qt.AlignBottom)
    splash.show()
    time.sleep(0.1)
    with SettingGroup('main') as settings:
        if settings.value('current_version', '') != __version__:
            settings.setValue('current_version', __version__)
            # Execute here the actions to be performed only once after
            # each update (there is nothing there for now, but it could
            # be useful some day...)
            logger.info('Upgrade to version %s finished' % __version__)
    app.processEvents()

    def log_unhandled(*exc_info):
        logger.error('Unhandled exception in Qt callback', exc_info=exc_info)

    sys.excepthook = log_unhandled

    t1 = time.time()
    logger.info('Startup: import finished (%.3f s), starting GUI...' %
                (t1 - t0))

    mainwindow = UFitMain()

    parser = optparse.OptionParser(usage='''\
    Usage: %prog [-b directory] [.ufit file | data file]
    ''')
    parser.add_option('-b',
                      '--browse',
                      action='store',
                      metavar='DIR',
                      help='open browse window in specified directory')

    opts, args = parser.parse_args()

    if len(args) >= 1:
        datafile = path.abspath(args[0])
        if path.isdir(datafile):
            # directory given, treat it as -b argument (browse)
            opts.browse = datafile
        elif datafile.endswith('.ufit'):
            try:
                mainwindow.filename = datafile
                mainwindow.load_session(datafile)
            except Exception as err:
                QMessageBox.warning(mainwindow, 'Error',
                                    'Loading failed: %s' % err)
                mainwindow.filename = None
        else:
            dtempl, numor = extract_template(datafile)
            mainwindow.dloader.set_template(dtempl, numor, silent=False)
    mainwindow.show()
    if opts.browse:
        mainwindow.dloader.open_browser(opts.browse)

    t2 = time.time()
    logger.info('Startup: loading finished (%.3f s), main window opened' %
                (t2 - t1))
    splash.deleteLater()
    app.exec_()