示例#1
0
    def modifyData(self):
        visible_curves = self.visibleCurves()
        # get input from the user: which curves should be modified how
        dlg = dialogFromUi(self, 'panels/modify.ui')

        def checkAll():
            for i in range(dlg.list.count()):
                dlg.list.item(i).setCheckState(Qt.Checked)

        dlg.selectall.clicked.connect(checkAll)
        for i, descr in visible_curves:
            li = QListWidgetItem(descr, dlg.list)
            if len(visible_curves) == 1:
                li.setCheckState(Qt.Checked)
                dlg.operation.setFocus()
            else:
                li.setCheckState(Qt.Unchecked)
        if dlg.exec_() != QDialog.Accepted:
            return
        # evaluate selection
        op = dlg.operation.text()
        curves = []
        for i in range(dlg.list.count()):
            li = dlg.list.item(i)
            if li.checkState() == Qt.Checked:
                curves.append(i)

        # modify curve data
        for i in curves:
            curve = self.plotcurves[visible_curves[i][0]]
            self._modifyCurve(curve, op)
        self.update()
示例#2
0
 def __init__(self, parent):
     QDialog.__init__(self, parent)
     loadUi(self, 'panels/fit_arby.ui')
     self.presets = DlgPresets('fit_arby',
                               [(self.function, ''), (self.fitparams, ''),
                                (self.xfrom, ''), (self.xto, '')])
     self.presets.load()
     for name in sorted(ArbitraryFitter.arby_functions):
         QListWidgetItem(name, self.oftenUsed)
示例#3
0
 def on_newBtn_clicked(self):
     dlg = ConfigEditDialog(self, self.client, self.instrument,
                            self.configs)
     if not dlg.exec_():
         return
     self.applyBtn.setEnabled(True)
     config = configFromFrame(dlg.frm)
     self.configs.append(config)
     new_item = QListWidgetItem(config['name'], self.list)
     self.list.setCurrentItem(new_item)
示例#4
0
 def __init__(self, setups, typ, parent=None):
     QDialog.__init__(self, parent)
     uic.loadUi(
         path.abspath(
             path.join(path.dirname(__file__), '..', 'ui', 'dialogs',
                       'addxcludedialog.ui')), self)
     self.setWindowTitle('New %s ... ' % typ)
     self.labelHeader.setText('Add new %s:' % typ)
     for setup in setups:
         QListWidgetItem(setup, self.listWidgetSetups)
示例#5
0
 def __init__(self, parameters, existingParameters, parent=None):
     QDialog.__init__(self, parent)
     uic.loadUi(
         path.abspath(
             path.join(path.dirname(__file__), '..', 'ui', 'dialogs',
                       'addparameterdialog.ui')), self)
     self.lineEditCustomParameter.setHidden(True)
     missingParameters = [
         key for key in parameters.keys()
         if key not in existingParameters.keys() and not key.startswith('_')
     ]
     if missingParameters:
         for key in sorted(missingParameters):
             listItem = QListWidgetItem(key, self.listWidgetSelectParameter)
             listItem.setToolTip(parameters[key].description)
             self.listWidgetSelectParameter.addItem(listItem)
     else:
         self.checkBoxCustomParameter.setChecked(True)
         self.checkBoxCustomParameter.setEnabled(False)
         self.lineEditCustomParameter.setEnabled(True)
示例#6
0
 def on_newBtn_clicked(self):
     dlg = ConfigEditDialog(self, self.client, self.instrument,
                            self.configs)
     if not dlg.exec_():
         return
     self.dirty = True
     config = configFromFrame(dlg.frm)
     dlg.frm.whatLbl.setText('New sample configuration')
     self.configs.append(config)
     newitem = QListWidgetItem(config['name'], self.list)
     self.list.setCurrentItem(newitem)
     self.on_list_itemClicked(newitem)
示例#7
0
    def __init__(self, parent, measdef, client):
        self.measdef = measdef
        self.samplefile = None
        self.client = client
        DlgUtils.__init__(self, 'Sample selection')
        QDialog.__init__(self, parent)
        loadUi(self, findResource('nicos_ess/loki/gui/ui_files/samples.ui'))

        self._init_samplefile = False
        self.samplefile = measdef.samplefile
        if self.samplefile is not None:
            self._init_samplefile = True
            self.on_sampleFileBtn_toggled(True)
            self._init_samplefile = False
        else:
            self.on_currentSamplesBtn_toggled(True)

        if self.measdef.samples:
            for sam in self.measdef.samples[0]:
                newitem = QListWidgetItem(sam['sample'].getValue(),
                                          self.selList)
                newitem.setData(SAMPLE_NUM, sam['sample'].extra[0])
示例#8
0
 def on_settingAdd_clicked(self):
     dlg = dialogFromUi(self, 'dialogs/settings_conn.ui')
     if dlg.exec_() != QDialog.Accepted:
         return
     if not dlg.name.text():
         return
     name = dlg.name.text()
     while name in self.connpresets:
         name += '_'
     cdata = ConnectionData(dlg.host.text(), dlg.port.value(),
                            dlg.login.text(), None, dlg.viewonly.isChecked())
     self.connpresets[name] = cdata
     QListWidgetItem(name + ' (%s:%s)' % (cdata.host, cdata.port),
                     self.settinglist).setData(32, name)
示例#9
0
 def add_to_flist(self, filename, fformat, scroll=True):
     shortname = path.basename(filename)
     if self.fileList.count() > 2 and \
        self.fileList.item(self.fileList.count()-2).text() == shortname:
         return
     item = QListWidgetItem(shortname)
     item.setData(32, filename)
     item.setData(33, fformat)
     self.fileList.insertItem(self.fileList.count()-1, item)
     if scroll:
         self.fileList.scrollToBottom()
示例#10
0
    def on_retrieveBtn_clicked(self):
        sampleconf = self.client.eval('Exp.sample.samples', [])
        sampleconf = sorted(sampleconf.items())
        self.configs = [dict(c[1]) for c in sampleconf if 'thickness' in c[1]]
        # convert readonlydict to normal dict
        for config in self.configs:
            config['position'] = dict(config['position'].items())
        newitem = None
        for config in self.configs:
            newitem = QListWidgetItem(config['name'], self.list)
        # select the last item
        if newitem:
            self.list.setCurrentItem(newitem)
            self.on_list_itemClicked(newitem)

        self.fileGroup.setEnabled(False)
        self.sampleGroup.setEnabled(True)
示例#11
0
 def setScript(self, script):
     self.traceView.clear()
     lines = script.splitlines()
     longest = len(str(len(lines)))
     padding = ' ' * (longest + 3)
     height = QFontMetrics(self.traceView.font()).height()
     for (i, line) in enumerate(lines):
         item = QListWidgetItem(self.otherlineicon, padding + line,
                                self.traceView)
         item.setSizeHint(QSize(-1, height))
         item.setData(Qt.UserRole, '%*d |' % (longest, i+1))
         self.traceView.addItem(item)
     self.current_line = -1
示例#12
0
 def setLiveItems(self, n):
     nitems = len(self.liveitems)
     if n < nitems:
         nfiles = self.fileList.count()
         for i in range(nitems - 1, n - 1, -1):
             self.liveitems.pop(i)
             self.fileList.takeItem(nfiles - nitems + i)
         if self._livechannel > n:
             self._livechannel = 0 if n > 0 else None
     else:
         for i in range(nitems, n):
             item = QListWidgetItem('<Live #%d>' % (i + 1))
             item.setData(FILENAME, i)
             item.setData(FILEFORMAT, '')
             item.setData(FILETAG, 'live')
             self.fileList.insertItem(self.fileList.count(), item)
             self.liveitems.append(item)
     if n == 1:
         self.liveitems[0].setText('<Live>')
     else:
         self.liveitems[0].setText('<Live #1>')
示例#13
0
    def selectCurve(self):
        """Let the user select a visible plot curve.

        If there is only one curve, return it directly.
        """
        visible_curves = self.visibleDataCurves()
        if not visible_curves:
            return
        if len(visible_curves) > 1:
            dlg = dialogFromUi(self, 'panels/selector.ui')
            dlg.setWindowTitle('Select curve to fit')
            dlg.label.setText('Select a curve:')
            for _, descr in visible_curves:
                QListWidgetItem(descr, dlg.list)
            dlg.list.setCurrentRow(0)
            if dlg.exec_() != QDialog.Accepted:
                return
            fitcurve = visible_curves[dlg.list.currentRow()][0]
        else:
            fitcurve = visible_curves[0][0]
        return self.plotcurves[fitcurve]
示例#14
0
 def setScript(self, script):
     self.traceView.clear()
     lines = script.splitlines()
     longest = len(str(len(lines)))
     padding = ' ' * (longest + 3)
     metrics = QFontMetrics(self.traceView.font())
     height = metrics.height()
     lineno_width = metrics.size(0, ' ' * (longest + 2)).width()
     self.traceView.itemDelegate()._margin_offset = lineno_width
     for (i, line) in enumerate(lines):
         item = QListWidgetItem(self.otherlineicon, padding + line,
                                self.traceView)
         item.setSizeHint(QSize(-1, height))
         item.setData(Qt.UserRole, '%*d' % (longest, i + 1))
         self.traceView.addItem(item)
     self.current_line = -1
示例#15
0
 def on_openFileBtn_clicked(self):
     initialdir = self.client.eval('session.experiment.scriptpath', '')
     fn = QFileDialog.getOpenFileName(self, 'Open sample file', initialdir,
                                      'Sample files (*.py)')[0]
     if not fn:
         return
     try:
         self.configs = parse_sampleconf(fn)
     except Exception as err:
         self.showError('Could not read file: %s\n\n'
                        'Are you sure this is a sample file?' % err)
     else:
         self.fileGroup.setEnabled(False)
         self.sampleGroup.setEnabled(True)
         newitem = None
         for config in self.configs:
             newitem = QListWidgetItem(config['name'], self.list)
         # select the last item
         if newitem:
             self.list.setCurrentItem(newitem)
         self.on_list_itemClicked(newitem)
         self.filename = fn
示例#16
0
文件: live.py 项目: ess-dmsc/nicos
    def add_to_flist(self, filename, filetype, tag, uid=None, scroll=True):
        # liveonly mode doesn't display a filelist
        if self._liveOnlyIndex is not None:
            return

        shortname = path.basename(filename)
        item = QListWidgetItem(shortname)
        item.setData(FILENAME, filename)
        item.setData(FILETYPE, filetype)
        item.setData(FILETAG, tag)
        item.setData(FILEUID, uid)
        self.fileList.insertItem(self.fileList.count(), item)
        if uid:
            self.remove_obsolete_cached_files()
        if scroll:
            self.fileList.scrollToBottom()
        return item
示例#17
0
    def __init__(self, parent, measdef, client):
        self.measdef = measdef
        self.client = client
        QDialog.__init__(self, parent)
        loadUi(self, findResource('nicos_ess/loki/gui/ui_files/devices.ui'))

        self.frame = QFrame(self)
        self.scrollArea.setWidget(self.frame)
        self.frame.setLayout(QVBoxLayout())
        self.frame.layout().setContentsMargins(0, 0, 10, 0)
        self.frame.layout().addStretch()

        devlist = client.getDeviceList('nicos.core.device.Moveable')
        for dev in devlist:
            if dev not in DEV_NOT_ALLOWED:
                QListWidgetItem(dev, self.devList)

        self._widgets = []

        for group in measdef.devices:
            devs = group[0].keys()
            w = self._addWidget(devs)
            for entry in group:
                w.addRow([entry[x] for x in devs])
示例#18
0
class LiveDataPanel(Panel):
    panelName = 'Live data view'

    def __init__(self, parent, client, options):
        Panel.__init__(self, parent, client, options)
        loadUi(self, findResource('nicos_mlz/mira/gui/live.ui'))

        self._format = None
        self._runtime = 0
        self._no_direct_display = False
        self._range_active = False

        self.statusBar = QStatusBar(self)
        policy = self.statusBar.sizePolicy()
        policy.setVerticalPolicy(QSizePolicy.Fixed)
        self.statusBar.setSizePolicy(policy)
        self.statusBar.setSizeGripEnabled(False)
        self.layout().addWidget(self.statusBar)

        if CascadeWidget:
            self.widget = CascadeWidget(self)
            self.widget.setContextMenuPolicy(Qt.CustomContextMenu)
            self.widgetLayout.addWidget(self.widget)
        else:
            raise RuntimeError('The Cascade live widget is not available')

        self.rangeFrom = QDoubleSpinBox(self)
        self.rangeTo = QDoubleSpinBox(self)
        for ctrl in [self.rangeFrom, self.rangeTo]:
            ctrl.setRange(0, 100000000)
            ctrl.setEnabled(False)
            ctrl.setMaximumWidth(90)
            ctrl.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,
                                           QSizePolicy.Fixed))
            ctrl.valueChanged.connect(self.on_rangeChanged)

        self.liveitem = QListWidgetItem('<Live>', self.fileList)
        self.liveitem.setData(32, '')
        self.liveitem.setData(33, '')

        self.splitter.setSizes([20, 80])
        self.splitter.restoreState(self.splitterstate)

        client.livedata.connect(self.on_client_livedata)
        if client.isconnected:
            self.on_client_connected()
        client.connected.connect(self.on_client_connected)
        client.setup.connect(self.on_client_connected)

        self.actionLogScale.toggled.connect(self.widget.SetLog10)
        self.actionSelectChannels.triggered.connect(self.widget.showSumDlg)
        self.widget.customContextMenuRequested.connect(
            self.on_widget_customContextMenuRequested)

    def loadSettings(self, settings):
        self.splitterstate = settings.value('splitter', '', QByteArray)

    def saveSettings(self, settings):
        settings.setValue('splitter', self.splitter.saveState())

    def getMenus(self):
        self.menu = menu = QMenu('&Live data', self)
        menu.addAction(self.actionLoadTOF)
        menu.addAction(self.actionLoadPAD)
        menu.addSeparator()
        menu.addAction(self.actionWriteXml)
        menu.addAction(self.actionPrint)
        menu.addSeparator()
        menu.addAction(self.actionSetAsROI)
        menu.addAction(self.actionUnzoom)
        menu.addAction(self.actionLogScale)
        menu.addAction(self.actionNormalized)
        menu.addAction(self.actionLegend)
        return [menu]

    def getToolbars(self):
        bar = QToolBar('Live data')
        bar.addAction(self.actionWriteXml)
        bar.addAction(self.actionPrint)
        bar.addSeparator()
        bar.addAction(self.actionLogScale)
        bar.addSeparator()
        bar.addAction(self.actionUnzoom)
        bar.addAction(self.actionSetAsROI)
        bar.addSeparator()
        bar.addAction(self.actionSelectChannels)
        bar.addSeparator()
        bar.addAction(self.actionCustomRange)
        bar.addWidget(self.rangeFrom)
        bar.addWidget(QLabel(' to '))
        bar.addWidget(self.rangeTo)
        bar.addSeparator()
        bar.addAction(self.actionOverviewMode)
        bar.addAction(self.actionPhaseMode)
        bar.addAction(self.actionContrastMode)
        return [bar]

    def on_widget_customContextMenuRequested(self, point):
        self.menu.popup(self.mapToGlobal(point))

    def on_client_connected(self):
        self.client.tell('eventunmask', ['livedata'])
        datapath = self.client.eval('session.experiment.datapath', '')
        if not datapath:
            return
        caspath = path.join(datapath, 'cascade')
        if path.isdir(caspath):
            for fn in sorted(os.listdir(caspath)):
                if fn.endswith('.pad'):
                    self.add_to_flist(path.join(caspath, fn), 'pad', False)
                elif fn.endswith('tof'):
                    self.add_to_flist(path.join(caspath, fn), 'tof', False)

    def on_client_livedata(self, params, blobs):
        tag, _uid, _det, filename, dtype, nx, ny, nt, runtime = params
        # TODO: remove compatibility code
        if not isinstance(filename, str):
            filename, nx, ny, nt = filename[0], nx[0], ny[0], nt[0]

        if dtype == '<u4' and nx == 128 and ny == 128 and tag != 'MiraXML':
            if nt == 1:
                self._format = 'pad'
            elif nt == 128:
                self._format = 'tof'
            self._runtime = runtime
            self._filename = filename
        else:
            if filename and tag != 'MiraXML':
                self._filename = filename
                self._format = filename[-3:]
            else:
                # print 'Unsupported live data format:', params
                self._format = None

        for blob in blobs:
            self._process_livedata(blob)

    def _process_livedata(self, data):
        if self._format not in ('pad', 'tof'):
            return
        if data:
            self._last_data = data
        if not self._no_direct_display and data:
            runtime = self._runtime or 1e-6
            if self._format == 'pad':
                self.widget.LoadPadMem(data, 128*128*4)
                cts = self.widget.GetPad().GetCounts()
                self.statusBar.showMessage('cps: %.2f | total: %s' %
                                           (cts/runtime, cts))
            else:
                self.widget.LoadTofMem(data, 128*128*128*4)
                cts = self.widget.GetTof().GetCounts()
                self.statusBar.showMessage('cps: %.2f | total: %s' %
                                           (cts/runtime, cts))
            self.updateRange()
        if self._filename and not self._filename.startswith(('live@', '<Live>@')):
            # and path.isfile(self._filename):
            if 'mira_cas' not in self._filename:
                self.add_to_flist(self._filename, self._format)

    def on_fileList_itemClicked(self, item):
        if item is None:
            return
        fname = item.data(32)
        fformat = item.data(33)
        if not fname:
            if self._no_direct_display:
                self._no_direct_display = False
                if self._format == 'pad':
                    self.widget.LoadPadMem(self._last_data, 128*128*4)
                    cts = self.widget.GetPad().GetCounts()
                    self.statusBar.showMessage('total: %s' % cts)
                elif self._format == 'tof':
                    self.widget.LoadTofMem(self._last_data, 128*128*128*4)
                    cts = self.widget.GetTof().GetCounts()
                    self.statusBar.showMessage('total: %s' % cts)
                self.updateRange()
        else:
            self._no_direct_display = True
            if fformat == 'pad':
                self.widget.LoadPadFile(fname)
                cts = self.widget.GetPad().GetCounts()
                self.statusBar.showMessage('total: %s' % cts)
            elif fformat == 'tof':
                self.widget.LoadTofFile(fname)
                cts = self.widget.GetTof().GetCounts()
                self.statusBar.showMessage('total: %s' % cts)
            self.updateRange()

    def on_fileList_currentItemChanged(self, item, previous):
        self.on_fileList_itemClicked(item)

    @pyqtSlot()
    def on_actionLoadTOF_triggered(self):
        filename = QFileDialog.getOpenFileName(self,
            'Open TOF File', '', 'TOF File (*.tof *.TOF);;All files (*)')[0]
        if filename:
            self.widget.LoadTofFile(filename)
            self.add_to_flist(filename, 'tof')

    @pyqtSlot()
    def on_actionLoadPAD_triggered(self):
        filename = QFileDialog.getOpenFileName(self,
            'Open PAD File', '', 'PAD File (*.pad *.PAD);;All files (*)')[0]
        if filename:
            self.widget.LoadPadFile(filename)
            self.updateRange()
            self.add_to_flist(filename, 'pad')

    def add_to_flist(self, filename, fformat, scroll=True):
        shortname = path.basename(filename)
        if self.fileList.count() > 2 and \
           self.fileList.item(self.fileList.count()-2).text() == shortname:
            return
        item = QListWidgetItem(shortname)
        item.setData(32, filename)
        item.setData(33, fformat)
        self.fileList.insertItem(self.fileList.count()-1, item)
        if scroll:
            self.fileList.scrollToBottom()

    @pyqtSlot()
    def on_actionWriteXml_triggered(self):
        pad = self.widget.GetPad()
        if pad is None:
            return self.showError('No 2-d image is shown.')
        filename = str(QFileDialog.getSaveFileName(
            self, 'Select file name', '', 'XML files (*.xml)')[0])
        if not filename:
            return
        if not filename.endswith('.xml'):
            filename += '.xml'
        if TmpImage:
            tmpimg = TmpImage()
            tmpimg.ConvertPAD(pad)
            tmpimg.WriteXML(filename)

    @pyqtSlot()
    def on_actionSetAsROI_triggered(self):
        zoom = self.widget.GetPlot().GetZoomer().zoomRect()
        self.client.run('psd_channel.roi = (%s, %s, %s, %s)' %
                        (int(zoom.left()), int(zoom.top()),
                         int(zoom.right()), int(zoom.bottom())))

    @pyqtSlot()
    def on_actionUnzoom_triggered(self):
        self.widget.GetPlot().GetZoomer().zoom(0)

    @pyqtSlot()
    def on_actionPrint_triggered(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setColorMode(QPrinter.Color)
        printer.setOrientation(QPrinter.Landscape)
        printer.setOutputFileName('')
        if QPrintDialog(printer, self).exec_() == QDialog.Accepted:
            self.widget.GetPlot().print_(printer)
        self.statusBar.showMessage('Plot successfully printed to %s.' %
                                   str(printer.printerName()))

    def on_actionCustomRange_toggled(self, on):
        self.rangeFrom.setEnabled(on)
        self.rangeTo.setEnabled(on)
        self.widget.SetAutoCountRange(not on)
        self._range_active = on
        if on:
            self.on_rangeChanged(0)
        else:
            self.updateRange()

    def on_rangeChanged(self, val):
        if self._range_active:
            self.widget.SetCountRange(self.rangeFrom.value(),
                                      self.rangeTo.value())

    def updateRange(self):
        if not self.actionCustomRange.isChecked():
            crange = self.widget.GetData2d().range()
            self.rangeFrom.setValue(crange.minValue())
            self.rangeTo.setValue(crange.maxValue())

    def closeEvent(self, event):
        with self.sgroup as settings:
            settings.setValue('geometry', self.saveGeometry())
        event.accept()

    @pyqtSlot()
    def on_actionOverviewMode_triggered(self):
        self.widget.viewOverview()

    @pyqtSlot()
    def on_actionPhaseMode_triggered(self):
        self.widget.SetFoil(7)
        self.widget.viewPhases()

    @pyqtSlot()
    def on_actionContrastMode_triggered(self):
        self.widget.SetFoil(7)
        self.widget.viewContrasts()
示例#19
0
 def on_rightBtn_clicked(self):
     for item in self.allList.selectedItems():
         newitem = QListWidgetItem(item.text(), self.selList)
         newitem.setData(SAMPLE_NUM, item.data(SAMPLE_NUM))
示例#20
0
 def __init__(self, parent, client):
     Cmdlet.__init__(self, parent, client,
                     findResource('nicos_mlz/kws3/gui/restore.ui'))
     for devname in self._getDeviceList():
         item = QListWidgetItem(devname, self.devList)
         item.setCheckState(Qt.Unchecked)
示例#21
0
    def on_actionGenerate_triggered(self):
        def read_axes():
            ax1, ax2 = dlg._info[2], dlg._info[4]
            for (ax, box) in [(ax1, dlg.ax1Box), (ax2, dlg.ax2Box)]:
                if not ax:
                    continue
                x = self.client.eval('%s.read()' % ax, None)
                if x is None:
                    QMessageBox.warning(dlg, 'Error',
                                        'Could not read %s.' % ax)
                    return
                box.setText('%.1f' % x)

        def btn_toggled(checked):
            if checked:
                dlg._info = dlg.sender()._info
                ax1, ax2 = dlg._info[2], dlg._info[4]
                for ax, lbl, box, revbox in [
                        (ax1, dlg.ax1Lbl, dlg.ax1Box, dlg.ax1RevBox),
                        (ax2, dlg.ax2Lbl, dlg.ax2Box, None)
                ]:
                    if ax:
                        lbl.setText(ax)
                        lbl.show()
                        box.show()
                        if revbox:
                            revbox.show()
                            revbox.setText('%s starts at far end' % ax)
                    else:
                        lbl.hide()
                        box.hide()
                        if revbox:
                            revbox.hide()

        dlg = dialogFromUi(self, findResource(
            'nicos_mlz/kws1/gui/sampleconf_gen.ui'))
        dlg.ax1Box.setValidator(DoubleValidator(self))
        dlg.ax2Box.setValidator(DoubleValidator(self))
        dlg.readBtn.clicked.connect(read_axes)
        nrows = int(math.ceil(len(self.holder_info) / 2.0))
        row, col = 0, 0
        for name, info in self.holder_info:
            btn = QRadioButton(name, dlg)
            btn._info = info
            btn.toggled.connect(btn_toggled)
            dlg.optionFrame.layout().addWidget(btn, row, col)
            if (row, col) == (0, 0):
                btn.setChecked(True)
            row += 1
            if row == nrows:
                row = 0
                col += 1
        if not dlg.exec_():
            return
        rows, levels, ax1, dax1, ax2, dax2 = dlg._info
        sax1 = float(dlg.ax1Box.text()) if ax1 else 0
        sax2 = float(dlg.ax2Box.text()) if ax2 else 0
        if dlg.ax1RevBox.isChecked():
            dax1 = -dax1

        n = 0
        for i in range(levels):
            for j in range(rows):
                n += 1
                position = {}
                if ax1:
                    position[ax1] = round(sax1 + j * dax1, 1)
                if ax2:
                    position[ax2] = round(sax2 + i * dax2, 1)
                config = dict(
                    name = str(n),
                    comment = '',
                    detoffset = -335.0,
                    thickness = 1.0,
                    timefactor = 1.0,
                    aperture = (0, 0, 10, 10),
                    position = position,
                )
                self.configs.append(config)
        firstitem = None
        for config in self.configs:
            newitem = QListWidgetItem(config['name'], self.list)
            firstitem = firstitem or newitem
        # select the first item
        self.list.setCurrentItem(firstitem)
        self.on_list_itemClicked(firstitem)

        self.fileGroup.setEnabled(False)
        self.sampleGroup.setEnabled(True)
        self.dirty = True
示例#22
0
文件: live.py 项目: umithardal/nicos
class LiveDataPanel(Panel):
    panelName = 'Live data view'

    def __init__(self, parent, client, options):
        Panel.__init__(self, parent, client, options)
        loadUi(self, findResource('nicos_mlz/antares/gui/live.ui'))

        self._format = None
        self._runtime = 0
        self._no_direct_display = False
        self._range_active = False

        self.statusBar = QStatusBar(self)
        policy = self.statusBar.sizePolicy()
        policy.setVerticalPolicy(QSizePolicy.Fixed)
        self.statusBar.setSizePolicy(policy)
        self.statusBar.setSizeGripEnabled(False)
        self.layout().addWidget(self.statusBar)

        self.widget = LWWidget(self)
        self.widget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.widgetLayout.addWidget(self.widget)

        self.rangeFrom = QDoubleSpinBox(self)
        self.rangeTo = QDoubleSpinBox(self)
        for ctrl in [self.rangeFrom, self.rangeTo]:
            ctrl.setEnabled(False)
            ctrl.setMaximumWidth(90)
            ctrl.setSizePolicy(
                QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
            ctrl.valueChanged.connect(self.on_rangeChanged)

        self.liveitem = QListWidgetItem('<Live>', self.fileList)
        self.liveitem.setData(32, '')
        self.liveitem.setData(33, '')

        self.splitter.setSizes([20, 80])
        self.splitter.restoreState(self.splitterstate)

        client.livedata.connect(self.on_client_livedata)
        client.liveparams.connect(self.on_client_liveparams)
        if client.isconnected:
            self.on_client_connected()
        client.connected.connect(self.on_client_connected)
        client.setup.connect(self.on_client_connected)

        self.actionLogScale.toggled.connect(self.widget.setLog10)
        self.widget.customContextMenuRequested.connect(
            self.on_widget_customContextMenuRequested)

    def loadSettings(self, settings):
        self.splitterstate = settings.value('splitter', '', QByteArray)

    def saveSettings(self, settings):
        settings.setValue('splitter', self.splitter.saveState())

    def getMenus(self):
        self.menu = menu = QMenu('&Live data', self)
        # menu.addAction(self.actionLoadTOF)
        # menu.addAction(self.actionLoadPAD)
        # menu.addSeparator()
        # menu.addAction(self.actionWriteXml)
        menu.addAction(self.actionPrint)
        menu.addSeparator()
        menu.addAction(self.actionSetAsROI)
        menu.addAction(self.actionUnzoom)
        menu.addAction(self.actionLogScale)
        menu.addAction(self.actionNormalized)
        menu.addAction(self.actionLegend)
        return [menu]

    def getToolbars(self):
        bar = QToolBar('Live data')
        # bar.addAction(self.actionWriteXml)
        bar.addAction(self.actionPrint)
        bar.addSeparator()
        bar.addAction(self.actionLogScale)
        bar.addSeparator()
        bar.addAction(self.actionUnzoom)
        bar.addAction(self.actionSetAsROI)
        # bar.addSeparator()
        # bar.addAction(self.actionSelectChannels)
        return [bar]

    def on_widget_customContextMenuRequested(self, point):
        self.menu.popup(self.mapToGlobal(point))

    def on_client_connected(self):
        self.client.tell('eventunmask', ['livedata', 'liveparams'])
        datapath = self.client.eval('session.experiment.datapath', '')
        if not datapath:
            return
        caspath = path.join(datapath, 'cascade')
        if path.isdir(caspath):
            for fn in sorted(os.listdir(caspath)):
                if fn.endswith('.pad'):
                    self.add_to_flist(path.join(caspath, fn), 'pad', False)
                elif fn.endswith('tof'):
                    self.add_to_flist(path.join(caspath, fn), 'tof', False)

    def on_client_liveparams(self, params):
        _tag, _uid, _det, _fname, dtype, nx, ny, nz, runtime = params
        # TODO: remove compatibility code
        if not isinstance(nx, integer_types):
            nx, ny, nz = nx[0], ny[0], nz[0]

        self._runtime = runtime
        if dtype not in DATATYPES:
            self._format = None
            self.log.warning('Unsupported live data format: %r', params)
            return
        self._format = dtype
        self._nx = nx
        self._ny = ny
        self._nz = nz

    def on_client_livedata(self, data):
        if self._format:
            self.widget.setData(
                LWData(self._nx, self._ny, self._nz, self._format, data))

    @pyqtSlot()
    def on_actionSetAsROI_triggered(self):
        zoom = self.widget.plot().getZoomer().zoomRect()
        # XXX this is detector specific!
        self.client.run('det.setRelativeRoi(%s, %s, %s, %s)' %
                        (int(zoom.left()), int(zoom.top()), int(
                            zoom.right()), int(zoom.bottom())))

    @pyqtSlot()
    def on_actionUnzoom_triggered(self):
        self.widget.plot().getZoomer().zoom(0)

    @pyqtSlot()
    def on_actionPrint_triggered(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setColorMode(QPrinter.Color)
        printer.setOrientation(QPrinter.Landscape)
        printer.setOutputFileName('')
        if QPrintDialog(printer, self).exec_() == QDialog.Accepted:
            self.widget.plot().print_(printer)

    def on_actionCustomRange_toggled(self, on):
        self.rangeFrom.setEnabled(on)
        self.rangeTo.setEnabled(on)
        self.widget.SetAutoCountRange(not on)
        self._range_active = on
        if on:
            self.on_rangeChanged(0)
        else:
            self.updateRange()

    def on_rangeChanged(self, val):
        if self._range_active:
            self.widget.SetCountRange(self.rangeFrom.value(),
                                      self.rangeTo.value())

    def updateRange(self):
        if not self.actionCustomRange.isChecked():
            crange = self.widget.GetData2d().range()
            self.rangeFrom.setValue(crange.minValue())
            self.rangeTo.setValue(crange.maxValue())

    def closeEvent(self, event):
        with self.sgroup as settings:
            settings.setValue('geometry', self.saveGeometry())
        event.accept()
示例#23
0
 def _createViewFromDialog(self, info, row=None):
     if not info['devices'].strip():
         return
     keys_indices = [
         extractKeyAndIndex(d.strip()) for d in info['devices'].split(',')
     ]
     if self.client is not None:
         meta = self._getMetainfo(keys_indices)
     else:
         meta = ({}, {})
     name = info['name']
     if not name:
         name = info['devices']
     if info['simpleTime']:
         name += ' (%s)' % info['simpleTimeSpec']
     window = None
     if info['simpleTime']:
         try:
             itime, _ = get_time_and_interval(info['simpleTimeSpec'])
         except ValueError:
             return
         fromtime = currenttime() - itime
         totime = None
         if info['slidingWindow']:
             window = itime
     else:
         if info['frombox']:
             fromtime = mktime(localtime(info['fromdate']))
         else:
             fromtime = None
         if info['tobox']:
             totime = mktime(localtime(info['todate']))
         else:
             totime = None
     try:
         interval = float(info['interval'])
     except ValueError:
         interval = 5.0
     if info['customY']:
         try:
             yfrom = float(info['customYFrom'])
         except ValueError:
             return
         try:
             yto = float(info['customYTo'])
         except ValueError:
             return
     else:
         yfrom = yto = None
     view = View(self, name, keys_indices, interval, fromtime, totime,
                 yfrom, yto, window, meta, info, self.gethistory_callback)
     self.views.append(view)
     view.listitem = QListWidgetItem(view.name)
     if row is not None:
         self.viewList.insertItem(row, view.listitem)
     else:
         self.viewList.addItem(view.listitem)
     self.openView(view)
     if view.totime is None:
         for key in view.uniq_keys:
             self.keyviews.setdefault(key, []).append(view)
     return view
示例#24
0
    def on_actionGenerate_triggered(self):
        def read_axes():
            ax1, ax2 = dlg._info[2], dlg._info[4]
            for (ax, box) in [(ax1, dlg.ax1Box), (ax2, dlg.ax2Box)]:
                if not ax:
                    continue
                x = self.client.eval('%s.read()' % ax, None)
                if x is None:
                    QMessageBox.warning(dlg, 'Error', f'Could not read {ax}.')
                    return
                box.setText(f'x:.1f')

        def btn_toggled(checked):
            if checked:
                dlg._info = dlg.sender()._info
                ax1, ax2 = dlg._info[2], dlg._info[4]
                for ax, lbl, box, revbox in [
                    (ax1, dlg.ax1Lbl, dlg.ax1Box, dlg.ax1RevBox),
                    (ax2, dlg.ax2Lbl, dlg.ax2Box, None)
                ]:
                    if ax:
                        lbl.setText(ax)
                        lbl.show()
                        box.show()
                        if revbox:
                            revbox.show()
                            revbox.setText(f'{ax} starts at far end')
                    else:
                        lbl.hide()
                        box.hide()
                        if revbox:
                            revbox.hide()

        if not self.holder_info:
            self.showError('Cannot auto-generate sample list as no sample '
                           'changers are defined')
            return

        dlg = dialogFromUi(
            self,
            findResource('nicos_ess/loki/gui/ui_files/sampleconf_gen.ui'))
        dlg.ax1Box.setValidator(DoubleValidator(self))
        dlg.ax2Box.setValidator(DoubleValidator(self))
        dlg.readBtn.clicked.connect(read_axes)
        n_rows = int(math.ceil(len(self.holder_info) / 2.0))
        row, col = 0, 0
        for name, info in self.holder_info:
            btn = QRadioButton(name, dlg)
            btn._info = info
            btn.toggled.connect(btn_toggled)
            dlg.optionFrame.layout().addWidget(btn, row, col)
            if (row, col) == (0, 0):
                btn.setChecked(True)
            row += 1
            if row == n_rows:
                row = 0
                col += 1
        if dlg.exec_() != QDialog.Accepted:
            return

        self._generate_configs(dlg)

        first_item = None
        for config in self.configs:
            new_item = QListWidgetItem(config['name'], self.list)
            first_item = first_item or new_item
        # select the first item
        self.list.setCurrentItem(first_item)
        self.on_list_itemClicked(first_item)

        self.sampleGroup.setEnabled(True)
        self.applyBtn.setEnabled(True)
示例#25
0
    def __init__(self):
        loadUi(self, 'panels/history.ui')

        self.user_color = Qt.white
        self.user_font = QFont('Monospace')

        self.views = []
        # stack of views to display
        self.viewStack = []
        # maps watched keys to their views
        self.keyviews = {}
        # current plot object
        self.currentPlot = None
        self.fitclass = LinearFitter
        self.fitfuncmap = {}

        self.enablePlotActions(False)

        self.presetmenu = QMenu('&Presets', self)

        for (name, view) in self.last_views:
            item = QListWidgetItem(name, self.viewList)
            item.setForeground(QBrush(QColor('#aaaaaa')))
            item.setData(Qt.UserRole, view)

        self.menus = None
        self.bar = None

        # NOTE: for this class, automatic connections don't work on PyQt4 >=
        # 4.12 since this class is not derived from QObject. But on older PyQt4
        # and PyQt5, they do work, so we change use the usual naming scheme
        # slightly to avoid double connections.
        self.viewList.currentItemChanged.connect(
            self.on__viewList_currentItemChanged)
        self.viewList.itemClicked.connect(self.on__viewList_itemClicked)
        self.viewList.itemDoubleClicked.connect(
            self.on__viewList_itemDoubleClicked)
        self.actionNew.triggered.connect(self.on__actionNew_triggered)
        self.actionEditView.triggered.connect(
            self.on__actionEditView_triggered)
        self.actionCloseView.triggered.connect(
            self.on__actionCloseView_triggered)
        self.actionResetView.triggered.connect(
            self.on__actionResetView_triggered)
        self.actionDeleteView.triggered.connect(
            self.on__actionDeleteView_triggered)
        self.actionSavePlot.triggered.connect(
            self.on__actionSavePlot_triggered)
        self.actionPrint.triggered.connect(self.on__actionPrint_triggered)
        self.actionUnzoom.triggered.connect(self.on__actionUnzoom_triggered)
        self.actionLogScale.toggled.connect(self.on__actionLogScale_toggled)
        self.actionAutoScale.toggled.connect(self.on__actionAutoScale_toggled)
        self.actionScaleX.toggled.connect(self.on__actionScaleX_toggled)
        self.actionScaleY.toggled.connect(self.on__actionScaleY_toggled)
        self.actionLegend.toggled.connect(self.on__actionLegend_toggled)
        self.actionSymbols.toggled.connect(self.on__actionSymbols_toggled)
        self.actionLines.toggled.connect(self.on__actionLines_toggled)
        self.actionSaveData.triggered.connect(
            self.on__actionSaveData_triggered)
        self.actionFitPeak.triggered.connect(self.on__actionFitPeak_triggered)
        self.actionFitArby.triggered.connect(self.on__actionFitArby_triggered)
        self.actionFitPeakGaussian.triggered.connect(
            self.on__actionFitPeakGaussian_triggered)
        self.actionFitPeakLorentzian.triggered.connect(
            self.on__actionFitPeakLorentzian_triggered)
        self.actionFitPeakPV.triggered.connect(
            self.on__actionFitPeakPV_triggered)
        self.actionFitPeakPVII.triggered.connect(
            self.on__actionFitPeakPVII_triggered)
        self.actionFitTc.triggered.connect(self.on__actionFitTc_triggered)
        self.actionFitCosine.triggered.connect(
            self.on__actionFitCosine_triggered)
        self.actionFitSigmoid.triggered.connect(
            self.on__actionFitSigmoid_triggered)
        self.actionFitLinear.triggered.connect(
            self.on__actionFitLinear_triggered)
        self.actionFitExponential.triggered.connect(
            self.on__actionFitExponential_triggered)
示例#26
0
    def on_client_connected(self):
        self.detectors.clear()
        self.sampleenv.clear()

        default_flags = Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | \
            Qt.ItemIsEnabled

        # fill detectors
        detectors = self.client.getDeviceList(
            'nicos.core.device.Measurable',
            exclude_class='nicos.devices.generic.detector.PassiveChannel')
        self._orig_detlist = self.client.eval('session.experiment.detlist', [])
        for detname in detectors:
            item = QListWidgetItem(detname, self.detectors)
            item.setFlags(default_flags)
            item.setCheckState(Qt.Checked if detname in
                               self._orig_detlist else Qt.Unchecked)

        # fill environment
        envdevs = self.client.getDeviceList(
            'nicos.core.device.Readable',
            exclude_class='nicos.core.device.Measurable')
        self._orig_envlist = self.client.eval('session.experiment.envlist', [])
        for devname in envdevs:
            item = QListWidgetItem(devname, self.sampleenv)
            item.setFlags(default_flags)
            item.setCheckState(Qt.Checked if devname in
                               self._orig_envlist else Qt.Unchecked)
        if self.client.viewonly:
            self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
        else:
            self.buttonBox.setStandardButtons(QDialogButtonBox.Apply
                                              | QDialogButtonBox.Close)
示例#27
0
 def on_client_connected(self):
     # fill setups
     self._setupinfo = self.client.eval('session.readSetupInfo()', {})
     all_loaded = self.client.eval('session.loaded_setups', set())
     self._prev_aliases = self.client.eval(
         '{d.name: d.alias for d in session.devices.values() '
         'if "alias" in d.parameters}', {})
     self._loaded = set()
     self._loaded_basic = None
     self.basicSetup.clear()
     self.optSetups.clear()
     self.errorLabel.hide()
     default_flags = Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | \
         Qt.ItemIsEnabled
     keep = QListWidgetItem('<keep current>', self.basicSetup)
     if self._setupinfo is not None:
         for name, info in sorted(self._setupinfo.items()):
             if info is None:
                 self.errorLabel.show()
                 continue
             if info['group'] == 'basic':
                 QListWidgetItem(name, self.basicSetup)
                 if name in all_loaded:
                     self._loaded_basic = name
                     self._loaded.add(name)
             elif info['group'] == 'optional':
                 item = QListWidgetItem(name, self.optSetups)
                 item.setFlags(default_flags)
                 item.setData(Qt.UserRole, 0)
                 if name in all_loaded:
                     self._loaded.add(name)
                 item.setCheckState(Qt.Checked if name in
                                    all_loaded else Qt.Unchecked)
             elif info['group'] == 'plugplay':
                 item = QListWidgetItem(name, self.optSetups)
                 item.setFlags(default_flags)
                 item.setData(Qt.UserRole, 1)
                 if name in all_loaded:
                     self._loaded.add(name)
                 elif not self.showPnpBox.isChecked():
                     item.setHidden(True)
                 item.setCheckState(Qt.Checked if name in
                                    all_loaded else Qt.Unchecked)
     self.basicSetup.setCurrentItem(keep)
     self._prev_alias_config = self._alias_config
     if self.client.viewonly:
         self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
         self.buttonBox.removeButton(self._reload_btn)
     else:
         self.buttonBox.setStandardButtons(QDialogButtonBox.Apply
                                           | QDialogButtonBox.Close)
         self.buttonBox.addButton(self._reload_btn,
                                  QDialogButtonBox.ResetRole)
示例#28
0
class LiveDataPanel(Panel):
    """Provides a generic "detector live view" for 2-D images.

    For most instruments, a specific panel must be implemented that takes care
    of the individual live display needs.

    Options:

    * ``instrument`` -- the instrument name that is passed on to the livewidget
      module.
    * ``filetypes`` default[] - List of filename extensions whose content should
      be displayed.  This list extends the list of 'fits', 'raw', 'tiff', and
      'TIFF'.
    * ``cachesize`` (default 20) - Number of entries in the live data cache.
      The live data cache allows to display of previous taken data.
    * ``showcached`` (default False) - If True the taken live data will be
      cached.
    """

    panelName = 'Live data view'
    bar = None
    menu = None

    def __init__(self, parent, client, options):
        Panel.__init__(self, parent, client, options)
        loadUi(self, 'panels/live.ui')

        self._allowed_tags = set()
        self._last_tag = None
        self._last_fname = None
        self._last_format = None
        self._runtime = 0
        self._no_direct_display = False
        self._range_active = False
        self._cachesize = 20
        self._datacache = BoundedOrderedDict(maxlen=self._cachesize)
        self._datapathok = False

        self.statusBar = QStatusBar(self, sizeGripEnabled=False)
        policy = self.statusBar.sizePolicy()
        policy.setVerticalPolicy(QSizePolicy.Fixed)
        self.statusBar.setSizePolicy(policy)
        self.statusBar.setSizeGripEnabled(False)
        self.layout().addWidget(self.statusBar)

        self.widget = LWWidget(self)
        self.widget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.widget.setControls(Logscale | MinimumMaximum | BrightnessContrast
                                | Integrate | Histogram)
        self.widgetLayout.addWidget(self.widget)

        self.liveitem = QListWidgetItem('<Live>', self.fileList)
        self.liveitem.setData(32, '')
        self.liveitem.setData(33, '')

        self.splitter.setSizes([20, 80])
        self.splitter.restoreState(self.splitterstate)

        # configure instrument specific behavior
        self._instrument = options.get('instrument', '')
        self.widget.setInstrumentOption(self._instrument)
        if self._instrument == 'toftof':
            self.widget.setAxisLabels('time channels', 'detectors')
        elif self._instrument == 'imaging':
            self.widget.setControls(ShowGrid | Logscale | Grayscale | Normalize
                                    | Darkfield | Despeckle | CreateProfile
                                    | Histogram | MinimumMaximum)
        elif self._instrument == 'laue':
            self.widget.setControls(ShowGrid | Grayscale | Darkfield
                                    | Despeckle | CreateProfile | Histogram
                                    | MinimumMaximum)
            self.widget.setStandardColorMap(True, False)
        elif self._instrument == 'poli':
            self.widget.setControls(ShowGrid | Logscale | Grayscale | Despeckle
                                    | CreateProfile | Histogram
                                    | MinimumMaximum | BrightnessContrast)
        if self._instrument in ('dns', 'dnspsd'):
            self.widget.setKeepAspect(False)
        else:
            self.widget.setKeepAspect(True)
        # configure allowed file types
        opt_filetypes = options.get('filetypes', list(FILETYPES))
        self._allowed_tags = set(opt_filetypes) & set(FILETYPES)

        # configure caching
        self._showcached = options.get('showcached', False)
        self._cachesize = options.get('cachesize', 20)
        if self._cachesize < 1:
            self._cachesize = 1  # always cache the last live image
        self._datacache = BoundedOrderedDict(maxlen=self._cachesize)

        client.livedata.connect(self.on_client_livedata)
        client.liveparams.connect(self.on_client_liveparams)
        client.connected.connect(self.on_client_connected)
        client.setup.connect(self.on_client_connected)

        self.actionLogScale.toggled.connect(self.widget.setLog10)
        self.widget.profileUpdate.connect(self.on_widget_profileUpdate)
        self.widget.customContextMenuRequested.connect(
            self.on_widget_customContextMenuRequested)

        self._toftof_profile = None

    def loadSettings(self, settings):
        self.splitterstate = settings.value('splitter', '', QByteArray)

    def saveSettings(self, settings):
        settings.setValue('splitter', self.splitter.saveState())
        settings.setValue('geometry', self.saveGeometry())
        if self._toftof_profile:
            self._toftof_profile.close()

    def getMenus(self):
        if not self.menu:
            menu = QMenu('&Live data', self)
            menu.addAction(self.actionPrint)
            menu.addSeparator()
            menu.addAction(self.actionUnzoom)
            menu.addAction(self.actionLogScale)
            self.menu = menu
        return [self.menu]

    def getToolbars(self):
        if not self.bar:
            bar = QToolBar('Live data')
            bar.addAction(self.actionPrint)
            bar.addSeparator()
            bar.addAction(self.actionLogScale)
            bar.addSeparator()
            bar.addAction(self.actionUnzoom)
            self.bar = bar
        return [self.bar]

    def on_widget_customContextMenuRequested(self, point):
        self.menu.popup(self.mapToGlobal(point))

    def on_widget_profileUpdate(self, proftype, nbins, x, y):
        if self._instrument != 'toftof':
            return
        if self._toftof_profile is None:
            self._toftof_profile = ToftofProfileWindow(self)
        self._toftof_profile.update(proftype, nbins, x, y)
        self._toftof_profile.show()

    def on_client_connected(self):
        self.client.tell('eventunmask', ['livedata', 'liveparams'])
        datapath = self.client.eval('session.experiment.datapath', '')
        if not datapath or not path.isdir(datapath):
            self._showcached = True  # always show  cached data if datapath is not accessible
            return
        if self._instrument == 'imaging':
            for fn in sorted(os.listdir(datapath)):
                if fn.endswith('.fits'):
                    self.add_to_flist(path.join(datapath, fn), '', 'fits',
                                      False)

    def on_client_liveparams(self, params):
        tag, _uid, det, fname, dtype, nx, ny, nz, runtime = params
        if (self._instrument == 'dns' and det != 'det') or \
           (self._instrument == 'dnspsd' and det != 'qm_det'):
            self._last_tag = self._last_fname = ''
            return
        if not isinstance(fname, string_types):
            fname, nx, ny, nz = fname[0], nx[0], ny[0], nz[0]

        self._runtime = runtime
        normalized_type = numpy.dtype(dtype).str if dtype != '' else ''  # pylint: disable=compare-to-empty-string
        if not fname and normalized_type not in DATATYPES:
            self._last_format = self._last_fname = None
            self.log.warning('Unsupported live data format: %s', params)
            return
        self._last_tag = tag.lower()
        self._last_fname = fname
        self._last_format = normalized_type
        self._nx = nx
        self._ny = ny
        self._nz = nz

    def on_client_livedata(self, data):
        # pylint: disable=len-as-condition
        d = None
        if self._last_fname:
            if path.isfile(
                    self._last_fname) and self._last_tag in self._allowed_tags:
                # in the case of a filename, we add it to the list
                self.add_to_flist(self._last_fname, self._last_format,
                                  self._last_tag)
                d = LWData(self._last_fname)
            elif len(
                    data
            ) and self._last_format and self._last_tag in self._allowed_tags or self._last_tag == 'live':
                d = LWData(self._nx, self._ny, self._nz, self._last_format,
                           data)
                self._datacache[self._last_fname] = (self._nx, self._ny,
                                                     self._nz,
                                                     self._last_format, data)
                if self._showcached:
                    self.add_to_flist(self._last_fname,
                                      self._last_format,
                                      self._last_tag,
                                      cached=True)
        # always allow live data
        if self._last_tag == 'live':
            if len(data) and self._last_format:
                # we got live data with a specified format
                d = LWData(self._nx, self._ny, self._nz, self._last_format,
                           data)
        # but display it right now only if on <Live> setting
        if self._no_direct_display or not d:
            return
        self.widget.setData(d)

    def add_to_flist(self, filename, fformat, ftag, cached=False, scroll=True):
        shortname = path.basename(filename)
        item = QListWidgetItem(shortname)
        item.setData(32, filename)
        item.setData(33, fformat)
        item.setData(34, ftag)
        item.setData(35, cached)
        self.fileList.insertItem(self.fileList.count() - 1, item)
        if cached:
            self.del_obsolete_cached_data()

        if scroll:
            self.fileList.scrollToBottom()

    def del_obsolete_cached_data(self):
        cached_item_rows = list()
        for row in range(self.fileList.count()):
            item = self.fileList.item(row)
            if item.data(35):
                cached_item_rows.append(row)
        if len(cached_item_rows) > self._cachesize:
            for row in cached_item_rows[0:-self._cachesize]:
                self.fileList.takeItem(row)

    def on_fileList_itemClicked(self, item):
        if item is None:
            return
        fname = item.data(32)
        ftag = item.data(34)
        cached = item.data(35)
        if fname == '':  # pylint: disable=compare-to-empty-string
            # show always latest live image
            if self._no_direct_display:
                self._no_direct_display = False
                d = None
                if self._last_fname and path.isfile(self._last_fname) and \
                   self._last_tag in self._allowed_tags:
                    d = LWData(self._last_fname)
                elif self._datacache:
                    val = self._datacache.getlast()
                    d = LWData(*val)
                if d:
                    self.widget.setData(d)
        else:
            # show image from file
            self._no_direct_display = True
            if fname and str(ftag) in self._allowed_tags or str(
                    ftag) == 'live':
                if cached:
                    d = self._datacache.get(fname, None)
                    if d:
                        self.widget.setData(LWData(*d))
                else:
                    self.widget.setData(LWData(fname))

    def on_fileList_currentItemChanged(self, item, previous):
        self.on_fileList_itemClicked(item)

    @pyqtSlot()
    def on_actionUnzoom_triggered(self):
        self.widget.plot().getZoomer().zoom(0)

    @pyqtSlot()
    def on_actionPrint_triggered(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setColorMode(QPrinter.Color)
        printer.setOrientation(QPrinter.Landscape)
        printer.setOutputFileName('')
        if QPrintDialog(printer, self).exec_() == QDialog.Accepted:
            self.widget.plot().print_(printer)
            self.statusBar.showMessage('Plot successfully printed to %s.' %
                                       str(printer.printerName()))
示例#29
0
    def __init__(self, parent, client, options):
        Panel.__init__(self, parent, client, options)
        loadUi(self, 'panels/live.ui')

        self._allowed_tags = set()
        self._last_tag = None
        self._last_fname = None
        self._last_format = None
        self._runtime = 0
        self._no_direct_display = False
        self._range_active = False
        self._cachesize = 20
        self._datacache = BoundedOrderedDict(maxlen=self._cachesize)
        self._datapathok = False

        self.statusBar = QStatusBar(self, sizeGripEnabled=False)
        policy = self.statusBar.sizePolicy()
        policy.setVerticalPolicy(QSizePolicy.Fixed)
        self.statusBar.setSizePolicy(policy)
        self.statusBar.setSizeGripEnabled(False)
        self.layout().addWidget(self.statusBar)

        self.widget = LWWidget(self)
        self.widget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.widget.setControls(Logscale | MinimumMaximum | BrightnessContrast
                                | Integrate | Histogram)
        self.widgetLayout.addWidget(self.widget)

        self.liveitem = QListWidgetItem('<Live>', self.fileList)
        self.liveitem.setData(32, '')
        self.liveitem.setData(33, '')

        self.splitter.setSizes([20, 80])
        self.splitter.restoreState(self.splitterstate)

        # configure instrument specific behavior
        self._instrument = options.get('instrument', '')
        self.widget.setInstrumentOption(self._instrument)
        if self._instrument == 'toftof':
            self.widget.setAxisLabels('time channels', 'detectors')
        elif self._instrument == 'imaging':
            self.widget.setControls(ShowGrid | Logscale | Grayscale | Normalize
                                    | Darkfield | Despeckle | CreateProfile
                                    | Histogram | MinimumMaximum)
        elif self._instrument == 'laue':
            self.widget.setControls(ShowGrid | Grayscale | Darkfield
                                    | Despeckle | CreateProfile | Histogram
                                    | MinimumMaximum)
            self.widget.setStandardColorMap(True, False)
        elif self._instrument == 'poli':
            self.widget.setControls(ShowGrid | Logscale | Grayscale | Despeckle
                                    | CreateProfile | Histogram
                                    | MinimumMaximum | BrightnessContrast)
        if self._instrument in ('dns', 'dnspsd'):
            self.widget.setKeepAspect(False)
        else:
            self.widget.setKeepAspect(True)
        # configure allowed file types
        opt_filetypes = options.get('filetypes', list(FILETYPES))
        self._allowed_tags = set(opt_filetypes) & set(FILETYPES)

        # configure caching
        self._showcached = options.get('showcached', False)
        self._cachesize = options.get('cachesize', 20)
        if self._cachesize < 1:
            self._cachesize = 1  # always cache the last live image
        self._datacache = BoundedOrderedDict(maxlen=self._cachesize)

        client.livedata.connect(self.on_client_livedata)
        client.liveparams.connect(self.on_client_liveparams)
        client.connected.connect(self.on_client_connected)
        client.setup.connect(self.on_client_connected)

        self.actionLogScale.toggled.connect(self.widget.setLog10)
        self.widget.profileUpdate.connect(self.on_widget_profileUpdate)
        self.widget.customContextMenuRequested.connect(
            self.on_widget_customContextMenuRequested)

        self._toftof_profile = None