Exemple #1
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)
Exemple #2
0
    def __init__(self, parent, client, **settings):
        QDialog.__init__(self, parent)
        loadUi(self, 'tools/calculator.ui')

        self.closeBtn.clicked.connect(self.doclose)

        self.braggfmlLabel.setPixmap(QPixmap(
            path.join(path.dirname(__file__), 'calculator_images',
                      'braggfml.png')))
        for fld in bragg_fields:
            getattr(self, 'chk' + fld).toggled.connect(self.gen_checked(fld))

        self._miezesettings = settings.get('mieze', [])
        if not self._miezesettings:
            self.tabWidget.removeTab(1)
        else:
            self.mzwavelengthInput.textChanged.connect(self.mzcalc)
            self.mzdistanceInput.textChanged.connect(self.mzcalc)
            self.mzformulaLabel.setPixmap(QPixmap(
                path.join(path.dirname(__file__), 'calculator_images',
                          'miezefml.png')))

            self.mztimeTable.setHeaderLabels(['Setting', u'MIEZE time τ'])
            for setting in self._miezesettings:
                self.mztimeTable.addTopLevelItem(QTreeWidgetItem([setting, '']))

        for fld in neutron_fields:
            getattr(self, 'prop' + fld).textEdited.connect(self.n_calc)

        self.presets = DlgPresets('nicoscalctool', [
            (self.tabWidget, 0),
            (self.mzwavelengthInput, '10'), (self.mzdistanceInput, '100'),
            (self.inputLambda, '4.5'), (self.input2Theta, '0'),
            (self.inputD, '10'), (self.inputN, '1'), (self.inputQ, '0'),
            (self.chkLambda, 1), (self.chk2Theta, 0), (self.chkN, 1),
            (self.chkD, 1), (self.chkQ, 0), (self.chkSampleDet, 1),
            (self.inputSampleDet, '0'),
            (self.propL, '1.8'), (self.propK, '3.4907'),
            (self.propE, '25.2482'), (self.propNy, '6.1050'),
            (self.propT, '292.9934'), (self.propV, '2197.80'),
        ])
        self.presets.load()
        self.braggcalc()
        self.n_calc('')

        dblval = DoubleValidator(self)
        for fld in bragg_fields:
            inputbox = getattr(self, 'input'+fld)
            inputbox.textChanged.connect(self.braggcalc)
            inputbox.setValidator(dblval)
Exemple #3
0
class ArbyFitDialog(QDialog):
    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)

    def on_oftenUsed_itemClicked(self, item):
        params, func = ArbitraryFitter.arby_functions[item.text()]
        self.function.setText(func)
        self.fitparams.setPlainText('\n'.join(params))

    def getFunction(self):
        self.presets.save()

        fcnstr = self.function.text()
        try:
            xmin = float(self.xfrom.text())
        except ValueError:
            xmin = None
        try:
            xmax = float(self.xto.text())
        except ValueError:
            xmax = None
        if xmin is not None and xmax is not None and xmin > xmax:
            xmax, xmin = xmin, xmax
        params, values = [], []
        for line in self.fitparams.toPlainText().splitlines():
            name_value = line.strip().split('=', 2)
            if len(name_value) < 2:
                continue
            params.append(name_value[0])
            try:
                values.append(float(name_value[1]))
            except ValueError:
                values.append(1.0)

        return fcnstr, params, values, xmin, xmax
Exemple #4
0
class CalculatorTool(QDialog):
    """Provides a dialog for several neutron-related calculations.

    The dialog offers several tabs for calculations (elastic scattering,
    conversion between wavelength and energy etc.)
    """

    def __init__(self, parent, client, **settings):
        QDialog.__init__(self, parent)
        loadUi(self, 'tools/calculator.ui')

        self.closeBtn.clicked.connect(self.doclose)

        self.braggfmlLabel.setPixmap(QPixmap(
            path.join(path.dirname(__file__), 'calculator_images',
                      'braggfml.png')))
        for fld in bragg_fields:
            getattr(self, 'chk' + fld).toggled.connect(self.gen_checked(fld))

        self._miezesettings = settings.get('mieze', [])
        if not self._miezesettings:
            self.tabWidget.removeTab(1)
        else:
            self.mzwavelengthInput.textChanged.connect(self.mzcalc)
            self.mzdistanceInput.textChanged.connect(self.mzcalc)
            self.mzformulaLabel.setPixmap(QPixmap(
                path.join(path.dirname(__file__), 'calculator_images',
                          'miezefml.png')))

            self.mztimeTable.setHeaderLabels(['Setting', u'MIEZE time τ'])
            for setting in self._miezesettings:
                self.mztimeTable.addTopLevelItem(QTreeWidgetItem([setting, '']))

        for fld in neutron_fields:
            getattr(self, 'prop' + fld).textEdited.connect(self.n_calc)

        self.presets = DlgPresets('nicoscalctool', [
            (self.tabWidget, 0),
            (self.mzwavelengthInput, '10'), (self.mzdistanceInput, '100'),
            (self.inputLambda, '4.5'), (self.input2Theta, '0'),
            (self.inputD, '10'), (self.inputN, '1'), (self.inputQ, '0'),
            (self.chkLambda, 1), (self.chk2Theta, 0), (self.chkN, 1),
            (self.chkD, 1), (self.chkQ, 0), (self.chkSampleDet, 1),
            (self.inputSampleDet, '0'),
            (self.propL, '1.8'), (self.propK, '3.4907'),
            (self.propE, '25.2482'), (self.propNy, '6.1050'),
            (self.propT, '292.9934'), (self.propV, '2197.80'),
        ])
        self.presets.load()
        self.braggcalc()
        self.n_calc('')

        dblval = DoubleValidator(self)
        for fld in bragg_fields:
            inputbox = getattr(self, 'input'+fld)
            inputbox.textChanged.connect(self.braggcalc)
            inputbox.setValidator(dblval)

    def closeEvent(self, event):
        self.deleteLater()
        self.accept()

    def doclose(self, *ignored):
        self.presets.save()
        self.close()

    def gen_checked(self, fld):
        def checked(state):
            getattr(self, 'input' + fld).setEnabled(state)
            self.braggcalc()
        return checked

    def braggcalc(self, *ignored):
        given = {}
        needed = {}
        for fld, conv in zip(bragg_fields, bragg_convs):
            if fld == 'SampleDet':
                continue
            if getattr(self, 'chk'+fld).isChecked():
                given[fld] = tofloat(getattr(self, 'input'+fld)) * conv
            else:
                needed[fld] = conv
        if len(given) < 3:
            self.errorLabel.setText('Error: Not enough variables given.')
            return
        elif len(given) > 3:
            self.errorLabel.setText('Error: Too many variables given.')
            return
        elif 'Q' in given and 'D' in given and 'N' in given:
            self.errorLabel.setText('Error: All of n, d, q given.')
            return
        elif 'Q' in given and 'Lambda' in given and '2Theta' in given:
            self.errorLabel.setText('Error: All of q, lambda, 2theta given.')
            return
        try:
            # let's see what to calculate first:
            if '2Theta' in given and 'Lambda' in given:
                # three of four variables in Bragg's equation known
                if 'N' in given:
                    given['D'] = given['N']*given['Lambda']/2/math.sin(given['2Theta']/2)
                else:
                    given['N'] = 2*given['D']*math.sin(given['2Theta']/2)/given['Lambda']
                given['Q'] = given['N']*2*PI/given['D']
            else:
                # two of three variables in q = 2pi(n/d) known
                if 'N' in given and 'D' in given:
                    given['Q'] = given['N']*2*PI/given['D']
                elif 'Q' in given and 'D' in given:
                    given['N'] = given['D']*given['Q']/2/PI
                else:
                    given['D'] = given['N']*2*PI/given['Q']
                # then, only lambda or 2theta is missing
                if 'Lambda' in given:
                    arg = given['N']*given['Lambda']/2/given['D']
                    if not 0 <= arg <= 1:
                        raise ValueError('impossible scattering angle')
                    given['2Theta'] = 2*math.asin(arg)
                else:
                    given['Lambda'] = 2*given['D']*math.sin(given['2Theta']/2)/given['N']
        except ZeroDivisionError as err:
            self.errorLabel.setText('Error: division by zero.')
        except ValueError as err:
            self.errorLabel.setText('Error: %s.' % err)
        else:
            self.errorLabel.setText('')
            # now, fill the disabled text fields
            for fld, conv in iteritems(needed):
                getattr(self, 'input'+fld).setText('%.3f' % (given[fld]/conv))
            if self.chkSampleDet.isChecked():
                sd = tofloat(self.inputSampleDet)
                dd = math.tan(given['2Theta']) * sd
                self.distance.setText('%.2f' % dd)
            else:
                self.distance.setText('')

    def n_calc(self, text):
        try:
            if self.sender() is self.propK:
                lam = 2*PI/float(text)
            elif self.sender() is self.propE:
                lam = H/math.sqrt(2*M_N*float(text)*MEV) * 1e10
            elif self.sender() is self.propNy:
                lam = math.sqrt(H/(2*M_N*float(text)*1e12)) * 1e10
            elif self.sender() is self.propT:
                lam = H/math.sqrt(2*M_N*K_B*float(text)) * 1e10
            elif self.sender() is self.propV:
                lam = H/M_N/float(text) * 1e10
            else:
                lam = float(self.propL.text())
            if self.sender() is not self.propL:
                self.propL.setText('%.4f' % lam)
            if self.sender() is not self.propK:
                self.propK.setText('%.4f' % (2*PI/lam))
            if self.sender() is not self.propE:
                self.propE.setText('%.4f' % (H**2/(2*M_N*lam**2*1e-20)/MEV))
            if self.sender() is not self.propNy:
                self.propNy.setText('%.4f' % (H/(2*M_N*lam**2*1e-20)/1e12))
            if self.sender() is not self.propT:
                self.propT.setText('%.4f' % (H**2/(2*M_N*K_B*lam**2*1e-20)))
            if self.sender() is not self.propV:
                self.propV.setText('%.2f' % (H/M_N/(lam*1e-10)))
        except Exception as err:
            self.propError.setText('Error: %s' % err)
        else:
            self.propError.setText('')

    def mzcalc(self, *ignored):
        L_s = tofloat(self.mzdistanceInput) * 1e-2  # in cm
        lam = tofloat(self.mzwavelengthInput) * 1e-10  # in Ang

        for i, setting in enumerate(self._miezesettings):
            f1, f2, bs = re.match(r'([\dp]+)_([\dp]+)(_BS)?', setting).groups()
            f1 = float(f1.replace('p', '.')) * 1000  # in kHz
            f2 = float(f2.replace('p', '.')) * 1000  # in kHz
            dOmega = (f2 - f1) * 2 * PI
            if bs:
                dOmega *= 2
            tau = (prefactor * lam**3 * dOmega * L_s) * 1e12  # in ps
            self.mztimeTable.topLevelItem(i).setText(1, '%.1f ps' % tau)
Exemple #5
0
    def __init__(self, parent, client, **settings):
        QDialog.__init__(self, parent)
        loadUi(self, 'tools/scan.ui')

        self.scanButtonGroup = QButtonGroup()
        self.scanButtonGroup.addButton(self.scanSingle)
        self.scanButtonGroup.addButton(self.scanCentered)
        self.qscanButtonGroup = QButtonGroup()
        self.qscanButtonGroup.addButton(self.qscanSingle)
        self.qscanButtonGroup.addButton(self.qscanCentered)
        self.qscanButtonGroup.addButton(self.qscanRandom)
        self.qscanButtonGroup.addButton(self.qscanLong)
        self.qscanButtonGroup.addButton(self.qscanTrans)
        self.presetButtonGroup = QButtonGroup()
        self.presetButtonGroup.addButton(self.presetTime)
        self.presetButtonGroup.addButton(self.presetMonitor)

        self.scanButtonGroup.buttonClicked.connect(self.updateCommand)
        self.qscanButtonGroup.buttonClicked.connect(self.updateCommand)
        self.presetButtonGroup.buttonClicked.connect(self.updateCommand)
        self.stepsInput.valueChanged.connect(self.updateCommand)
        self.timeInput.valueChanged.connect(self.updateCommand)
        self.monitorInput.valueChanged.connect(self.updateCommand)

        self.deviceList.itemSelectionChanged.connect(self.updateCommand)

        self.scanPreset.textChanged.connect(self.updateCommand)
        self.scanNumsteps.textChanged.connect(self.updateCommand)
        self.scanStep.textChanged.connect(self.updateCommand)
        self.scanStart.textChanged.connect(self.updateCommand)
        self.deviceName.textChanged.connect(self.updateCommand)
        self.scanRange.textChanged.connect(self.updateCommand)

        self.hInput.textChanged.connect(self.updateCommand)
        self.kInput.textChanged.connect(self.updateCommand)
        self.lInput.textChanged.connect(self.updateCommand)
        self.EInput.textChanged.connect(self.updateCommand)
        self.deltahInput.textChanged.connect(self.updateCommand)
        self.deltakInput.textChanged.connect(self.updateCommand)
        self.deltalInput.textChanged.connect(self.updateCommand)
        self.deltaEInput.textChanged.connect(self.updateCommand)
        self.deltaqInput.textChanged.connect(self.updateCommand)

        self.generateBtn.clicked.connect(self.createCommand)
        self.clearAllBtn.clicked.connect(self.clearAll)
        self.quitBtn.clicked.connect(self.close)
        self.scanCalc.clicked.connect(self.calc_scan)
        self.qscanCalc.clicked.connect(self.calc_qscan)

        self.qscanSingle.clicked.connect(self.set_qlabels)
        self.qscanCentered.clicked.connect(self.set_qlabels)
        self.qscanLong.clicked.connect(self.set_qlabels)
        self.qscanTrans.clicked.connect(self.set_qlabels)
        self.qscanRandom.clicked.connect(self.set_qlabels)

        self._devices = sorted(
            parent.client.eval(
                '[(dev.name, dev.unit) '
                'for (name, dev) in session.devices.items() '
                'if name in session.explicit_devices and hasattr(dev, "maw")]',
                []))

        self.tabWidget.setTabEnabled(0, self._devices != [])
        for name, unit in self._devices:
            self.deviceList.addItem("%s [%s]" % (name, unit))

        dval = DoubleValidator(self)
        ival = QIntValidator(self)

        # qscan tab
        self.hInput.setValidator(dval)
        self.kInput.setValidator(dval)
        self.lInput.setValidator(dval)
        self.EInput.setValidator(dval)
        self.deltahInput.setValidator(dval)
        self.deltakInput.setValidator(dval)
        self.deltalInput.setValidator(dval)
        self.deltaEInput.setValidator(dval)
        self.deltaqInput.setValidator(dval)

        # disabled for now
        self.qscanRandom.setVisible(False)
        self.qscanTrans.setVisible(False)
        self.qscanLong.setVisible(False)

        # scan/cscan tab
        self.scanStart.setValidator(dval)
        self.scanStep.setValidator(dval)
        self.scanNumsteps.setValidator(ival)
        self.scanPreset.setValidator(dval)
        self.scanMovetime.setValidator(dval)

        self.presets = DlgPresets(
            'scaninput',
            [
                # qscan tab
                (self.qscanSingle, 1),
                (self.qscanCentered, 0),
                (self.qscanLong, 0),
                (self.qscanTrans, 0),
                (self.qscanRandom, 0),
                (self.monitorInput, 10000),
                (self.timeInput, 120),
                (self.presetTime, 1),
                (self.presetMonitor, 0),
                (self.hInput, '0.0'),
                (self.kInput, '0.0'),
                (self.lInput, '0.0'),
                (self.EInput, '0.0'),
                (self.deltahInput, '0.0'),
                (self.deltakInput, '0.0'),
                (self.deltalInput, '0.0'),
                (self.deltaEInput, '0.0'),
                (self.deltaqInput, '0.0'),
                (self.stepsInput, 10),
                # scan tab
                (self.scanSingle, 1),
                (self.scanCentered, 0),
                (self.scanStart, '0.0'),
                (self.scanStep, '0.0'),
                (self.scanNumsteps, '0'),
                (self.scanPreset, '0.0'),
                (self.deviceList, 'om [deg]'),
                (self.deviceName, ''),
                (self.scanMovetime, '0'),
                # the tab itself
                (self.tabWidget, 0),
            ])
        self.presets.load()
        self.set_qlabels()
Exemple #6
0
class ScanTool(QDialog):
    addCode = pyqtSignal(str)

    def __init__(self, parent, client, **settings):
        QDialog.__init__(self, parent)
        loadUi(self, 'tools/scan.ui')

        self.scanButtonGroup = QButtonGroup()
        self.scanButtonGroup.addButton(self.scanSingle)
        self.scanButtonGroup.addButton(self.scanCentered)
        self.qscanButtonGroup = QButtonGroup()
        self.qscanButtonGroup.addButton(self.qscanSingle)
        self.qscanButtonGroup.addButton(self.qscanCentered)
        self.qscanButtonGroup.addButton(self.qscanRandom)
        self.qscanButtonGroup.addButton(self.qscanLong)
        self.qscanButtonGroup.addButton(self.qscanTrans)
        self.presetButtonGroup = QButtonGroup()
        self.presetButtonGroup.addButton(self.presetTime)
        self.presetButtonGroup.addButton(self.presetMonitor)

        self.scanButtonGroup.buttonClicked.connect(self.updateCommand)
        self.qscanButtonGroup.buttonClicked.connect(self.updateCommand)
        self.presetButtonGroup.buttonClicked.connect(self.updateCommand)
        self.stepsInput.valueChanged.connect(self.updateCommand)
        self.timeInput.valueChanged.connect(self.updateCommand)
        self.monitorInput.valueChanged.connect(self.updateCommand)

        self.deviceList.itemSelectionChanged.connect(self.updateCommand)

        self.scanPreset.textChanged.connect(self.updateCommand)
        self.scanNumsteps.textChanged.connect(self.updateCommand)
        self.scanStep.textChanged.connect(self.updateCommand)
        self.scanStart.textChanged.connect(self.updateCommand)
        self.deviceName.textChanged.connect(self.updateCommand)
        self.scanRange.textChanged.connect(self.updateCommand)

        self.hInput.textChanged.connect(self.updateCommand)
        self.kInput.textChanged.connect(self.updateCommand)
        self.lInput.textChanged.connect(self.updateCommand)
        self.EInput.textChanged.connect(self.updateCommand)
        self.deltahInput.textChanged.connect(self.updateCommand)
        self.deltakInput.textChanged.connect(self.updateCommand)
        self.deltalInput.textChanged.connect(self.updateCommand)
        self.deltaEInput.textChanged.connect(self.updateCommand)
        self.deltaqInput.textChanged.connect(self.updateCommand)

        self.generateBtn.clicked.connect(self.createCommand)
        self.clearAllBtn.clicked.connect(self.clearAll)
        self.quitBtn.clicked.connect(self.close)
        self.scanCalc.clicked.connect(self.calc_scan)
        self.qscanCalc.clicked.connect(self.calc_qscan)

        self.qscanSingle.clicked.connect(self.set_qlabels)
        self.qscanCentered.clicked.connect(self.set_qlabels)
        self.qscanLong.clicked.connect(self.set_qlabels)
        self.qscanTrans.clicked.connect(self.set_qlabels)
        self.qscanRandom.clicked.connect(self.set_qlabels)

        self._devices = sorted(
            parent.client.eval(
                '[(dev.name, dev.unit) '
                'for (name, dev) in session.devices.items() '
                'if name in session.explicit_devices and hasattr(dev, "maw")]',
                []))

        self.tabWidget.setTabEnabled(0, self._devices != [])
        for name, unit in self._devices:
            self.deviceList.addItem("%s [%s]" % (name, unit))

        dval = DoubleValidator(self)
        ival = QIntValidator(self)

        # qscan tab
        self.hInput.setValidator(dval)
        self.kInput.setValidator(dval)
        self.lInput.setValidator(dval)
        self.EInput.setValidator(dval)
        self.deltahInput.setValidator(dval)
        self.deltakInput.setValidator(dval)
        self.deltalInput.setValidator(dval)
        self.deltaEInput.setValidator(dval)
        self.deltaqInput.setValidator(dval)

        # disabled for now
        self.qscanRandom.setVisible(False)
        self.qscanTrans.setVisible(False)
        self.qscanLong.setVisible(False)

        # scan/cscan tab
        self.scanStart.setValidator(dval)
        self.scanStep.setValidator(dval)
        self.scanNumsteps.setValidator(ival)
        self.scanPreset.setValidator(dval)
        self.scanMovetime.setValidator(dval)

        self.presets = DlgPresets(
            'scaninput',
            [
                # qscan tab
                (self.qscanSingle, 1),
                (self.qscanCentered, 0),
                (self.qscanLong, 0),
                (self.qscanTrans, 0),
                (self.qscanRandom, 0),
                (self.monitorInput, 10000),
                (self.timeInput, 120),
                (self.presetTime, 1),
                (self.presetMonitor, 0),
                (self.hInput, '0.0'),
                (self.kInput, '0.0'),
                (self.lInput, '0.0'),
                (self.EInput, '0.0'),
                (self.deltahInput, '0.0'),
                (self.deltakInput, '0.0'),
                (self.deltalInput, '0.0'),
                (self.deltaEInput, '0.0'),
                (self.deltaqInput, '0.0'),
                (self.stepsInput, 10),
                # scan tab
                (self.scanSingle, 1),
                (self.scanCentered, 0),
                (self.scanStart, '0.0'),
                (self.scanStep, '0.0'),
                (self.scanNumsteps, '0'),
                (self.scanPreset, '0.0'),
                (self.deviceList, 'om [deg]'),
                (self.deviceName, ''),
                (self.scanMovetime, '0'),
                # the tab itself
                (self.tabWidget, 0),
            ])
        self.presets.load()
        self.set_qlabels()

    def set_qlabels(self, *args):
        if self.qscanCentered.isChecked() or self.qscanSingle.isChecked():
            self.label_dh.setText('<b>∆h</b>')
            self.label_dk.setText('<b>∆k</b>')
            self.label_dl.setText('<b>∆l</b>')
            self.deltahInput.setEnabled(True)
            self.deltakInput.setEnabled(True)
            self.deltalInput.setEnabled(True)
            self.deltaqInput.setEnabled(False)
        elif self.qscanLong.isChecked() or self.qscanTrans.isChecked():
            self.label_dh.setText('')
            self.label_dk.setText('')
            self.label_dl.setText('')
            self.deltahInput.setEnabled(False)
            self.deltakInput.setEnabled(False)
            self.deltalInput.setEnabled(False)
            self.deltaqInput.setEnabled(True)
        elif self.qscanRandom.isChecked():
            self.label_dh.setText('<b>u</b>')
            self.label_dk.setText('<b>v</b>')
            self.label_dl.setText('<b>w</b>')
            self.deltahInput.setEnabled(True)
            self.deltakInput.setEnabled(True)
            self.deltalInput.setEnabled(True)
            self.deltaqInput.setEnabled(True)

    def close(self, *args):
        """Close the window and save the settings."""
        self.presets.save()
        return True

    def closeEvent(self, event):
        self.presets.save()
        self.deleteLater()
        self.accept()

    def clearAll(self):
        # Clear scan
        self.scanStart.clear()
        self.scanStep.clear()
        self.scanNumsteps.clear()
        self.scanPreset.clear()
        self.scanRange.clear()
        self.scanEstimation.clear()
        self.scanMovetime.clear()
        # Clear qscan
        self.hInput.clear()
        self.deltahInput.clear()
        self.kInput.clear()
        self.deltakInput.clear()
        self.lInput.clear()
        self.deltalInput.clear()
        self.EInput.clear()
        self.deltaEInput.clear()
        self.deltaqInput.clear()

    def calc_scan(self):
        stepsize = tofloat(self.scanStep.text())
        numstep = toint(self.scanNumsteps.text())
        startpos = tofloat(self.scanStart.text())
        movetime = tofloat(self.scanMovetime.text())
        preset = tofloat(self.scanPreset.text())

        if self.scanSingle.isChecked():
            endpos = startpos + (stepsize - 1) * numstep
            self.scanRange.setText('- %.2f' % endpos)
            seconds = (movetime + preset) * numstep
        else:
            lowerend = startpos - stepsize * numstep
            upperend = startpos + stepsize * numstep
            self.scanRange.setText('%.2f - %.2f' % (lowerend, upperend))
            seconds = (movetime + preset) * (2 * numstep + 1)

        self.scanEstimation.setText(fmt_time(seconds))
        return seconds

    def calc_qscan(self):
        numstep = toint(self.stepsInput.text())
        if self.qscanCentered.isChecked() or self.qscanLong.isChecked() or \
           self.qscanTrans.isChecked():
            numstep = 2 * numstep + 1
        if self.presetTime.isChecked():
            preset = tofloat(self.timeInput.text())
            seconds = numstep * preset
            self.qscanEstimation.setText(fmt_time(seconds))
            return seconds
        else:
            self.qscanEstimation.setText('no estimation possible')
            return 0

    def updateCommand(self, *args):
        self.cmdResult.setText('<b>%s</b>' % self._getCommand())

    def _getCommand(self):
        tab = self.tabWidget.currentIndex()

        def timeest(secs):
            if secs == 0:
                return ''
            return '#- %d sec (%s)\n' % (secs, fmt_time(secs))

        # Qscan
        if tab == 1:
            params = [
                ('h', self.hInput, tofloat),
                ('k', self.kInput, tofloat),
                ('l', self.lInput, tofloat),
                ('E', self.EInput, tofloat),
                ('n', self.stepsInput, toint),
                ('dh', self.deltahInput, tofloat),
                ('dk', self.deltakInput, tofloat),
                ('dl', self.deltalInput, tofloat),
                ('dE', self.deltaEInput, tofloat),
                ('dq', self.deltaqInput, tofloat),
                ('t', self.timeInput, tofloat),
                ('m', self.monitorInput, toint),
            ]
            d = {name: func(ctl.text()) for (name, ctl, func) in params}

            if self.qscanSingle.isChecked():
                cmdname = 'qscan'
            elif self:
                cmdname = 'qcscan'
            else:
                return  # for now

            scan = cmdname + '([%(h)s, %(k)s, %(l)s, %(E)s], ' \
                '[%(dh)s, %(dk)s, %(dl)s, %(dE)s], %(n)s' % d

            if self.presetTime.isChecked():
                scan += ', t=%s)' % d['t']
            else:
                scan += ', m1=%s)' % d['m']

            cmd = timeest(self.calc_qscan())
            cmd += scan

        # scan
        else:
            devname = self.deviceName.text()
            if not devname:
                devname = self._devices[self.deviceList.currentRow()][0]

            if self.scanCentered.isChecked():
                cmdname = 'cscan'
            else:
                cmdname = 'scan'

            params = [devname]
            for (_pn, ctl, fn) in (('start', self.scanStart,
                                    tofloat), ('step', self.scanStep, tofloat),
                                   ('numsteps', self.scanNumsteps, toint),
                                   ('preset', self.scanPreset, tofloat)):
                val = fn(ctl.text())
                params.append(str(val))

            cmd = timeest(self.calc_scan())
            cmd += '%s(%s)' % (cmdname, ', '.join(params))
        return cmd + '\n'

    def createCommand(self):
        self.addCode.emit(self._getCommand())