Пример #1
0
    def init_envectlayout(self):
        ''' In commandLayout - Initialization of the resulting energy vector section, with elow, ehigh and dE'''

        envect_box = QGroupBox()
        envect_box.setTitle("Energy vector parameters")
        envect_box.setSizePolicy(0, 0)
        envectlayout = QGridLayout()
        envectlayout.setSpacing(10)

        self.elow_le = QLineEdit("{:.2f}".format(cts.elow), self)
        self.ehigh_le = QLineEdit("{:.2f}".format(cts.ehigh), self)
        self.dE_le = QLineEdit(str(cts.dE), self)

        self.elow_le.returnPressed.connect(self.update_envect_fn)
        self.ehigh_le.returnPressed.connect(self.update_envect_fn)
        self.dE_le.returnPressed.connect(self.update_envect_fn)

        envectlayout.addWidget(QLabel("E low (eV)"), 0, 0)
        envectlayout.addWidget(self.elow_le, 1, 0)
        envectlayout.addWidget(QLabel("E high (eV)"), 0, 1)
        envectlayout.addWidget(self.ehigh_le, 1, 1)
        envectlayout.addWidget(QLabel("dE (eV)"), 0, 2)
        envectlayout.addWidget(self.dE_le, 1, 2)

        envect_box.setLayout(envectlayout)

        for widget in envect_box.children():
            if isinstance(widget, QLabel) or isinstance(widget, QLineEdit):
                widget.setSizePolicy(0, 0)
                widget.setFixedSize(55, 20)

        self.commandlayout.addWidget(envect_box)
        self.update_envect_fn()
Пример #2
0
 def _getVClampCtrlBox(self):
     vClampPanel = QGroupBox(self)
     self._vClampCtrlBox = vClampPanel
     self._holdingVLabel = QLabel("Holding Voltage (mV)", vClampPanel)
     self._holdingVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.holdingV']), vClampPanel)
     self._holdingTimeLabel = QLabel("Holding Time (ms)", vClampPanel)
     self._holdingTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.holdingT']), vClampPanel)
     self._prePulseVLabel = QLabel("Pre-pulse Voltage (mV)", vClampPanel)
     self._prePulseVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.prepulseV']), vClampPanel)
     self._prePulseTimeLabel = QLabel("Pre-pulse Time (ms)", vClampPanel)
     self._prePulseTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.prepulseT']), vClampPanel)
     self._clampVLabel = QLabel("Clamp Voltage (mV)", vClampPanel)
     self._clampVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.clampV']), vClampPanel)
     self._clampTimeLabel = QLabel("Clamp Time (ms)", vClampPanel)
     self._clampTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.clampT']), vClampPanel)
     for child in vClampPanel.children():
         if isinstance(child, QLineEdit):
             set_default_line_edit_size(child)
     layout = QGridLayout(vClampPanel)
     layout.addWidget(self._holdingVLabel, 0, 0)
     layout.addWidget(self._holdingVEdit, 0, 1)
     layout.addWidget(self._holdingTimeLabel, 1, 0)
     layout.addWidget(self._holdingTimeEdit, 1, 1)
     layout.addWidget(self._prePulseVLabel, 2, 0)
     layout.addWidget(self._prePulseVEdit, 2, 1)
     layout.addWidget(self._prePulseTimeLabel,3,0)
     layout.addWidget(self._prePulseTimeEdit, 3, 1)
     layout.addWidget(self._clampVLabel, 4, 0)
     layout.addWidget(self._clampVEdit, 4, 1)
     layout.addWidget(self._clampTimeLabel, 5, 0)
     layout.addWidget(self._clampTimeEdit, 5, 1)
     layout.setRowStretch(6, 1.0)
     vClampPanel.setLayout(layout)
     return self._vClampCtrlBox
Пример #3
0
    def init_rabbitlayout(self):
        ''' In commandLayout - Initialization of the "RABBIT" section'''
        rabbitlayout = QGridLayout()
        rabbit_box = QGroupBox("RABBIT", self)
        rabbit_box.setFixedSize(300, 100)

        self.normalrab_btn = QPushButton("Normal", self)
        self.FTcontrast_btn = QPushButton("FT/Contrast", self)
        self.rainbowrab_btn = QPushButton("Rainbow", self)
        self.clear_btn = QPushButton("Clear", self)

        self.normalrab_btn.clicked.connect(self.normalrab_lr)
        self.FTcontrast_btn.clicked.connect(self.FTcontrast_lr)
        self.rainbowrab_btn.clicked.connect(self.rainbowrab_lr)
        self.clear_btn.clicked.connect(self.clear_lr)

        rabbitlayout.addWidget(self.normalrab_btn, 0, 0)
        rabbitlayout.addWidget(self.FTcontrast_btn, 0, 1)
        rabbitlayout.addWidget(self.rainbowrab_btn, 0, 2)
        rabbitlayout.addWidget(self.clear_btn, 1, 0)

        rabbit_box.setLayout(rabbitlayout)

        for widget in rabbit_box.children():
            if isinstance(widget, QPushButton):
                widget.setSizePolicy(0, 0)
                widget.setEnabled(False)

        self.commandLayout.addWidget(rabbit_box)
 def selected_radio(self, groupBox: QGroupBox) -> str:
     # Get all radio buttons
     radioBtns = [
         radio for radio in groupBox.children()
         if isinstance(radio, QRadioButton)
     ]
     # Find choosen radio and return text
     for radio in radioBtns:
         if radio.isChecked():
             return radio.text()
Пример #5
0
class Dialog(QDialog):
    def __init__(self, form):
        super(Dialog, self).__init__()
        self.form = form
        self.formGroupBox = QGroupBox(form.identifier)
        self.create_form(form)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.formGroupBox)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Form")

    def create_form(self, form):
        layout = QFormLayout()

        for question in form.block:
            show = question.evaluate_show_condition(self.form)
            question.pyqt5_render(layout, show)
            question.widget.onChange(form.update_show_condition_on_change)

        self.formGroupBox.setLayout(layout)

    # TODO unique file name
    @pyqtSlot()
    def accept(self):
        result = {}

        for child in self.formGroupBox.children()[1:]:
            question = self.form.find_question_of_widget(child)

            if question:
                result[question.identifier] = child.value()

        print(result)

        with open('out.json', 'w') as file:
            file.write(dumps(result))

        self.close()
        QMessageBox.information(
            self, 'Submission',
            'Your answers have been submitted successfully.', QMessageBox.Ok,
            QMessageBox.Ok)

    @pyqtSlot()
    def reject(self):
        self.hide()
Пример #6
0
 def _getIClampCtrlBox(self):
     iClampPanel = QGroupBox(self)
     self._iClampCtrlBox = iClampPanel
     self._baseCurrentLabel = QLabel("Base Current Level (uA)", iClampPanel)
     self._baseCurrentEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.baseI']), iClampPanel)
     self._firstPulseLabel = QLabel("First Pulse Current (uA)", iClampPanel)
     self._firstPulseEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.firstI']), iClampPanel)
     self._firstDelayLabel = QLabel("First Onset Delay (ms)", iClampPanel)
     self._firstDelayEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.firstD']), iClampPanel)
     self._firstPulseWidthLabel = QLabel("First Pulse Width (ms)",
                                         iClampPanel)
     self._firstPulseWidthEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.firstT']), iClampPanel)
     self._secondPulseLabel = QLabel("Second Pulse Current (uA)",
                                     iClampPanel)
     self._secondPulseEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.secondI']), iClampPanel)
     self._secondDelayLabel = QLabel("Second Onset Delay (ms)", iClampPanel)
     self._secondDelayEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.secondD']), iClampPanel)
     self._secondPulseWidthLabel = QLabel("Second Pulse Width (ms)",
                                          iClampPanel)
     self._secondPulseWidthEdit = QLineEdit(
         '%g' % (SquidGui.defaults['iclamp.secondT']), iClampPanel)
     self._pulseMode = QComboBox(iClampPanel)
     self._pulseMode.addItem("Single Pulse")
     self._pulseMode.addItem("Pulse Train")
     for child in iClampPanel.children():
         if isinstance(child, QLineEdit):
             set_default_line_edit_size(child)
     layout = QGridLayout(iClampPanel)
     layout.addWidget(self._baseCurrentLabel, 0, 0)
     layout.addWidget(self._baseCurrentEdit, 0, 1)
     layout.addWidget(self._firstPulseLabel, 1, 0)
     layout.addWidget(self._firstPulseEdit, 1, 1)
     layout.addWidget(self._firstDelayLabel, 2, 0)
     layout.addWidget(self._firstDelayEdit, 2, 1)
     layout.addWidget(self._firstPulseWidthLabel, 3, 0)
     layout.addWidget(self._firstPulseWidthEdit, 3, 1)
     layout.addWidget(self._secondPulseLabel, 4, 0)
     layout.addWidget(self._secondPulseEdit, 4, 1)
     layout.addWidget(self._secondDelayLabel, 5, 0)
     layout.addWidget(self._secondDelayEdit, 5, 1)
     layout.addWidget(self._secondPulseWidthLabel, 6, 0)
     layout.addWidget(self._secondPulseWidthEdit, 6, 1)
     layout.addWidget(self._pulseMode, 7, 0, 1, 2)
     layout.setRowStretch(8, 1.0)
     # layout.setSizeConstraint(QLayout.SetFixedSize)
     iClampPanel.setLayout(layout)
     return self._iClampCtrlBox
Пример #7
0
    def init_eparlayout(self):
        ''' In commandLayout - Initialization of the experimental parameters section: Retarding potential, TOF length,
            wavelength, gas and first harmonic expected to see.'''

        gases = cts.GASLIST

        epar_box = QGroupBox(self)
        epar_box.setTitle("Experimental parameters")
        epar_box.setSizePolicy(0, 0)
        eparlayout = QGridLayout()
        eparlayout.setSpacing(10)

        self.retpot_le = QLineEdit(str(cts.cur_Vp), self)
        self.toflength_le = QLineEdit(str(cts.cur_L), self)
        self.wvlength_le = QLineEdit(str(cts.lambda_start), self)
        self.gas_combo = QComboBox(self)
        self.gas_combo.addItems(gases)
        self.firstharm_le = QLineEdit(str(cts.first_harm), self)

        self.retpot_le.returnPressed.connect(self.update_cts_fn)
        self.toflength_le.returnPressed.connect(self.update_cts_fn)
        self.wvlength_le.returnPressed.connect(self.update_cts_fn)
        self.firstharm_le.returnPressed.connect(self.update_cts_fn)
        self.gas_combo.currentIndexChanged.connect(self.gas_combo_lr)

        eparlayout.addWidget(QLabel("Ret. pot. (V)"), 0, 0)
        eparlayout.addWidget(self.retpot_le, 1, 0)
        eparlayout.addWidget(QLabel("TOF length (m)"), 0, 1)
        eparlayout.addWidget(self.toflength_le, 1, 1)
        eparlayout.addWidget(QLabel("lambda (nm)"), 0, 2)
        eparlayout.addWidget(self.wvlength_le, 1, 2)
        eparlayout.addWidget(QLabel("gas"), 0, 3)
        eparlayout.addWidget(self.gas_combo, 1, 3)
        eparlayout.addWidget(QLabel("1st harm."), 0, 4)
        eparlayout.addWidget(self.firstharm_le, 1, 4)

        epar_box.setLayout(eparlayout)

        for widget in epar_box.children():
            if isinstance(widget, QLineEdit) or isinstance(widget, QComboBox):
                widget.setFixedSize(50, 20)
                widget.setSizePolicy(0, 0)

        self.commandlayout.addWidget(epar_box)
Пример #8
0
 def _getIClampCtrlBox(self):
     iClampPanel = QGroupBox(self)
     self._iClampCtrlBox = iClampPanel
     self._baseCurrentLabel = QLabel("Base Current Level (uA)",iClampPanel)
     self._baseCurrentEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.baseI']),iClampPanel)
     self._firstPulseLabel = QLabel("First Pulse Current (uA)", iClampPanel)
     self._firstPulseEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstI']), iClampPanel)
     self._firstDelayLabel = QLabel("First Onset Delay (ms)", iClampPanel)
     self._firstDelayEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstD']),iClampPanel)
     self._firstPulseWidthLabel = QLabel("First Pulse Width (ms)", iClampPanel)
     self._firstPulseWidthEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstT']), iClampPanel)
     self._secondPulseLabel = QLabel("Second Pulse Current (uA)", iClampPanel)
     self._secondPulseEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondI']), iClampPanel)
     self._secondDelayLabel = QLabel("Second Onset Delay (ms)", iClampPanel)
     self._secondDelayEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondD']),iClampPanel)
     self._secondPulseWidthLabel = QLabel("Second Pulse Width (ms)", iClampPanel)
     self._secondPulseWidthEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondT']), iClampPanel)
     self._pulseMode = QComboBox(iClampPanel)
     self._pulseMode.addItem("Single Pulse")
     self._pulseMode.addItem("Pulse Train")
     for child in iClampPanel.children():
         if isinstance(child, QLineEdit):
             set_default_line_edit_size(child)
     layout = QGridLayout(iClampPanel)
     layout.addWidget(self._baseCurrentLabel, 0, 0)
     layout.addWidget(self._baseCurrentEdit, 0, 1)
     layout.addWidget(self._firstPulseLabel, 1, 0)
     layout.addWidget(self._firstPulseEdit, 1, 1)
     layout.addWidget(self._firstDelayLabel, 2, 0)
     layout.addWidget(self._firstDelayEdit, 2, 1)
     layout.addWidget(self._firstPulseWidthLabel, 3, 0)
     layout.addWidget(self._firstPulseWidthEdit, 3, 1)
     layout.addWidget(self._secondPulseLabel, 4, 0)
     layout.addWidget(self._secondPulseEdit, 4, 1)
     layout.addWidget(self._secondDelayLabel, 5, 0)
     layout.addWidget(self._secondDelayEdit, 5, 1)
     layout.addWidget(self._secondPulseWidthLabel, 6, 0)
     layout.addWidget(self._secondPulseWidthEdit, 6, 1)
     layout.addWidget(self._pulseMode, 7, 0, 1, 2)
     layout.setRowStretch(8, 1.0)        
     # layout.setSizeConstraint(QLayout.SetFixedSize)
     iClampPanel.setLayout(layout)
     return self._iClampCtrlBox
Пример #9
0
    def init_exportlayout(self):
        ''' In commandLayout - Initialization of the "Export" section'''
        exportlayout = QGridLayout()
        export_box = QGroupBox("Export", self)
        export_box.setFixedSize(300, 60)

        self.exportrab_btn = QPushButton("RABBIT", self)

        self.exportrab_btn.clicked.connect(self.exportrab_lr)

        exportlayout.addWidget(self.exportrab_btn)

        export_box.setLayout(exportlayout)

        for widget in export_box.children():
            if isinstance(widget, QPushButton):
                widget.setSizePolicy(0, 0)
                widget.setEnabled(False)
        self.commandLayout.addWidget(export_box)
Пример #10
0
 def _getVClampCtrlBox(self):
     vClampPanel = QGroupBox(self)
     self._vClampCtrlBox = vClampPanel
     self._holdingVLabel = QLabel("Holding Voltage (mV)", vClampPanel)
     self._holdingVEdit = QLineEdit(
         '%g' % (SquidGui.defaults['vclamp.holdingV']), vClampPanel)
     self._holdingTimeLabel = QLabel("Holding Time (ms)", vClampPanel)
     self._holdingTimeEdit = QLineEdit(
         '%g' % (SquidGui.defaults['vclamp.holdingT']), vClampPanel)
     self._prePulseVLabel = QLabel("Pre-pulse Voltage (mV)", vClampPanel)
     self._prePulseVEdit = QLineEdit(
         '%g' % (SquidGui.defaults['vclamp.prepulseV']), vClampPanel)
     self._prePulseTimeLabel = QLabel("Pre-pulse Time (ms)", vClampPanel)
     self._prePulseTimeEdit = QLineEdit(
         '%g' % (SquidGui.defaults['vclamp.prepulseT']), vClampPanel)
     self._clampVLabel = QLabel("Clamp Voltage (mV)", vClampPanel)
     self._clampVEdit = QLineEdit(
         '%g' % (SquidGui.defaults['vclamp.clampV']), vClampPanel)
     self._clampTimeLabel = QLabel("Clamp Time (ms)", vClampPanel)
     self._clampTimeEdit = QLineEdit(
         '%g' % (SquidGui.defaults['vclamp.clampT']), vClampPanel)
     for child in vClampPanel.children():
         if isinstance(child, QLineEdit):
             set_default_line_edit_size(child)
     layout = QGridLayout(vClampPanel)
     layout.addWidget(self._holdingVLabel, 0, 0)
     layout.addWidget(self._holdingVEdit, 0, 1)
     layout.addWidget(self._holdingTimeLabel, 1, 0)
     layout.addWidget(self._holdingTimeEdit, 1, 1)
     layout.addWidget(self._prePulseVLabel, 2, 0)
     layout.addWidget(self._prePulseVEdit, 2, 1)
     layout.addWidget(self._prePulseTimeLabel, 3, 0)
     layout.addWidget(self._prePulseTimeEdit, 3, 1)
     layout.addWidget(self._clampVLabel, 4, 0)
     layout.addWidget(self._clampVEdit, 4, 1)
     layout.addWidget(self._clampTimeLabel, 5, 0)
     layout.addWidget(self._clampTimeEdit, 5, 1)
     layout.setRowStretch(6, 1.0)
     vClampPanel.setLayout(layout)
     return self._vClampCtrlBox
Пример #11
0
    def init_fitparlayout(self):
        ''' In commandLayout - Initialization of the fit parameter section with a, t0 and c. First line: guess values calculated
            from the experimental parameters. Second line: fitted values.'''

        fitpar_box = QGroupBox()
        fitpar_box.setTitle("Calibration parameters")
        fitpar_box.setSizePolicy(0, 0)
        fitparlayout = QGridLayout()
        fitparlayout.setSpacing(10)

        self.aguess_lb = QLabel(self)
        self.afit_lb = QLabel(self)
        self.t0guess_lb = QLabel(self)
        self.t0fit_lb = QLabel(self)
        self.cguess_lb = QLabel(self)
        self.cfit_lb = QLabel(self)

        fitparlayout.addWidget(QLabel("a"), 0, 0)
        fitparlayout.addWidget(self.aguess_lb, 1, 0)
        fitparlayout.addWidget(self.afit_lb, 2, 0)
        fitparlayout.addWidget(QLabel("t0"), 0, 1)
        fitparlayout.addWidget(self.t0guess_lb, 1, 1)
        fitparlayout.addWidget(self.t0fit_lb, 2, 1)
        fitparlayout.addWidget(QLabel("c"), 0, 2)
        fitparlayout.addWidget(self.cguess_lb, 1, 2)
        fitparlayout.addWidget(self.cfit_lb, 2, 2)
        fitparlayout.addWidget(QLabel("guess"), 1, 3)
        fitparlayout.addWidget(QLabel("calc"), 2, 3)
        text = "q=a*1/(t-t0)²+c"
        fitparlayout.addWidget(QLabel(text), 1, 4)

        fitpar_box.setLayout(fitparlayout)

        for widget in fitpar_box.children():
            if isinstance(widget, QLabel) and widget.text() != text:
                widget.setSizePolicy(0, 0)
                widget.setFixedSize(55, 15)

        self.commandlayout.addWidget(fitpar_box)
Пример #12
0
    def init_plotbtnlayout(self):
        ''' In commandLayout - Initialization of the "Plot" section'''
        plotbtnlayout = QGridLayout()
        plotbtn_box = QGroupBox("Plot", self)
        plotbtn_box.setFixedSize(300, 60)

        self.plotSBvsdelay_btn = QPushButton("SB vs delay", self)
        self.plotPulseInTime_btn = QPushButton("Pulse in time", self)

        self.plotSBvsdelay_btn.clicked.connect(self.plotSBvsdelay_lr)
        self.plotPulseInTime_btn.clicked.connect(self.plotPulseInTime_lr)

        plotbtnlayout.addWidget(self.plotSBvsdelay_btn, 0, 0)
        plotbtnlayout.addWidget(self.plotPulseInTime_btn, 0, 1)

        plotbtn_box.setLayout(plotbtnlayout)

        for widget in plotbtn_box.children():
            if isinstance(widget, QPushButton):
                widget.setSizePolicy(0, 0)
                widget.setEnabled(False)

        self.commandLayout.addWidget(plotbtn_box)
Пример #13
0
    def init_sigtreatmentlayout(self):
        ''' In commandLayout - Initialization of the "Signal Treatment" section'''
        sigtreatment_box = QGroupBox("Signal Treatment", self)
        sigtreatmentlayout = QGridLayout()

        sigtreatment_box.setFixedSize(300, 100)

        self.smooth_btn = QPushButton("smooth", self)
        self.smooth_le = QLineEdit("2", self)
        self.normalize_btn = QPushButton("normalize", self)
        self.subXUV_btn = QPushButton("substract XUV", self)
        self.selectbands_btn = QPushButton("select bands")
        self.bandsnb_le = QLineEdit(str(cts.bandsnb), self)

        self.smooth_btn.clicked.connect(self.smoothrab_lr)
        self.normalize_btn.clicked.connect(self.normalizerab_lr)
        self.selectbands_btn.clicked.connect(self.selectbands_lr)
        self.bandsnb_le.returnPressed.connect(self.bandsnb_lr)
        self.subXUV_btn.clicked.connect(self.subXUV_lr)

        sigtreatmentlayout.addWidget(self.smooth_btn, 0, 0)
        sigtreatmentlayout.addWidget(self.smooth_le, 1, 0)
        sigtreatmentlayout.addWidget(self.normalize_btn, 0, 1)
        sigtreatmentlayout.addWidget(self.subXUV_btn, 1, 1)
        sigtreatmentlayout.addWidget(self.selectbands_btn, 0, 2)
        sigtreatmentlayout.addWidget(self.bandsnb_le, 1, 2)

        sigtreatment_box.setLayout(sigtreatmentlayout)

        for widget in sigtreatment_box.children():
            if isinstance(widget, QPushButton):
                widget.setSizePolicy(0, 0)
                widget.setEnabled(False)
            if isinstance(widget, QLineEdit):
                widget.setFixedSize(55, 20)

        self.commandLayout.addWidget(sigtreatment_box)
Пример #14
0
    def init_importlayout(self):
        ''' In commandLayout - Initialization of the "Import" section'''
        Importlayout = QGridLayout()
        Importlayout.setSpacing(10)

        Import_box = QGroupBox(self)
        Import_box.setTitle("Import")
        Import_box.setFixedSize(300, 100)

        self.importcalib_btn = QPushButton("calib", self)
        self.importdata_btn = QPushButton("data", self)
        self.importXUV_btn = QPushButton("XUV only", self)
        self.importrabparam_btn = QPushButton("RABBIT param", self)
        self.importrab_btn = QPushButton("RABBIT", self)

        self.importcalib_btn.clicked.connect(self.importcalib_lr)
        self.importdata_btn.clicked.connect(self.importdata_lr)
        self.importXUV_btn.clicked.connect(self.importXUV_lr)
        self.importrabparam_btn.clicked.connect(self.importrabparam_lr)
        self.importrab_btn.clicked.connect(self.importrab_lr)

        Importlayout.addWidget(self.importcalib_btn, 0, 0)
        Importlayout.addWidget(self.importdata_btn, 1, 0)
        Importlayout.addWidget(self.importXUV_btn, 0, 1)
        Importlayout.addWidget(self.importrabparam_btn, 0, 2)
        Importlayout.addWidget(self.importrab_btn, 1, 2)

        Import_box.setLayout(Importlayout)
        self.commandLayout.addWidget(Import_box)

        for widget in Import_box.children():
            if isinstance(widget, QPushButton):
                widget.setSizePolicy(0, 0)
                widget.setEnabled(False)
        self.importcalib_btn.setEnabled(True)
        self.importrabparam_btn.setEnabled(True)
Пример #15
0
class SquidGui( QMainWindow ):
    defaults = {}
    defaults.update(SquidAxon.defaults)
    defaults.update(ClampCircuit.defaults)
    defaults.update({'runtime': 50.0,
                  'simdt': 0.01,
                  'plotdt': 0.1,
                  'vclamp.holdingV': 0.0,
                  'vclamp.holdingT': 10.0,
                  'vclamp.prepulseV': 0.0,
                  'vclamp.prepulseT': 0.0,
                  'vclamp.clampV': 50.0,
                  'vclamp.clampT': 20.0,
                  'iclamp.baseI': 0.0,
                  'iclamp.firstI': 0.1,
                  'iclamp.firstT': 40.0,
                  'iclamp.firstD': 5.0,
                  'iclamp.secondI': 0.0,
                  'iclamp.secondT': 0.0,
                  'iclamp.secondD': 0.0
                  })
    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
        self.squid_setup = SquidSetup()
        self._plotdt = SquidGui.defaults['plotdt']
        self._plot_dict = defaultdict(list)
        self.setWindowTitle('Squid Axon simulation')        
        self.setDockNestingEnabled(True)
        self._createRunControl()
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._runControlDock) 
        self._runControlDock.setFeatures(QDockWidget.AllDockWidgetFeatures)	 
        self._createChannelControl()
        self._channelCtrlBox.setWindowTitle('Channel properties')
        self._channelControlDock.setFeatures(QDockWidget.AllDockWidgetFeatures)	 
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._channelControlDock) 
        self._createElectronicsControl()
        self._electronicsDock.setFeatures(QDockWidget.AllDockWidgetFeatures)	 
        self._electronicsDock.setWindowTitle('Electronics')
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._electronicsDock) 
        self._createPlotWidget()             
        self.setCentralWidget(self._plotWidget)
        self._createStatePlotWidget()
        self._createHelpMessage()
        self._helpWindow.setVisible(False)
        self._statePlotWidget.setWindowFlags(QtCore.Qt.Window)
        self._statePlotWidget.setWindowTitle('State plot')
        self._initActions()
        self._createRunToolBar()
        self._createPlotToolBar()

    def getFloatInput(self, widget, name):
        try:
            return float(str(widget.text()))
        except ValueError:
            QMessageBox.critical(self, 'Invalid input', 'Please enter a valid number for {}'.format(name))
            raise

        
    def _createPlotWidget(self):
        self._plotWidget = QWidget()
        self._plotFigure = Figure()
        self._plotCanvas = FigureCanvas(self._plotFigure)
        self._plotCanvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._plotCanvas.updateGeometry()
        self._plotCanvas.setParent(self._plotWidget)
        self._plotCanvas.mpl_connect('scroll_event', self._onScroll)
        self._plotFigure.set_canvas(self._plotCanvas)
        # Vm and command voltage go in the same subplot
        self._vm_axes = self._plotFigure.add_subplot(2,2,1, title='Membrane potential')
        self._vm_axes.set_ylim(-20.0, 120.0)
        # Channel conductances go to the same subplot
        self._g_axes = self._plotFigure.add_subplot(2,2,2, title='Channel conductance')
        self._g_axes.set_ylim(0.0, 0.5)
        # Injection current for Vclamp/Iclamp go to the same subplot
        self._im_axes = self._plotFigure.add_subplot(2,2,3, title='Injection current')
        self._im_axes.set_ylim(-0.5, 0.5)
        # Channel currents go to the same subplot
        self._i_axes = self._plotFigure.add_subplot(2,2,4, title='Channel current')
        self._i_axes.set_ylim(-10, 10)
        for axis in self._plotFigure.axes:
            axis.set_autoscale_on(False)
        layout = QVBoxLayout()
        layout.addWidget(self._plotCanvas)
        self._plotNavigator = NavigationToolbar(self._plotCanvas, self._plotWidget)
        layout.addWidget(self._plotNavigator)
        self._plotWidget.setLayout(layout)

    def _createStatePlotWidget(self):        
        self._statePlotWidget = QWidget()
        self._statePlotFigure = Figure()
        self._statePlotCanvas = FigureCanvas(self._statePlotFigure)
        self._statePlotCanvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._statePlotCanvas.updateGeometry()
        self._statePlotCanvas.setParent(self._statePlotWidget)
        self._statePlotFigure.set_canvas(self._statePlotCanvas)
        self._statePlotFigure.subplots_adjust(hspace=0.5)
        self._statePlotAxes = self._statePlotFigure.add_subplot(2,1,1, title='State plot')
        self._state_plot, = self._statePlotAxes.plot([], [], label='state')
        self._activationParamAxes = self._statePlotFigure.add_subplot(2,1,2, title='H-H activation parameters vs time')
        self._activationParamAxes.set_xlabel('Time (ms)')
        #for axis in self._plotFigure.axes:
        #    axis.autoscale(False)
        self._stateplot_xvar_label = QLabel('Variable on X-axis')
        self._stateplot_xvar_combo = QComboBox()
        self._stateplot_xvar_combo.addItems(['V', 'm', 'n', 'h'])
        self._stateplot_xvar_combo.setCurrentText('V')
        self._stateplot_xvar_combo.setEditable(False)
        self._stateplot_xvar_combo.currentIndexChanged[str].connect( self._statePlotXSlot )
        self._stateplot_yvar_label = QLabel('Variable on Y-axis')
        self._stateplot_yvar_combo = QComboBox()
        self._stateplot_yvar_combo.addItems(['V', 'm', 'n', 'h'])
        self._stateplot_yvar_combo.setCurrentIndex(2)
        self._stateplot_yvar_combo.setEditable(False)
        self._stateplot_yvar_combo.currentIndexChanged[str].connect(self._statePlotYSlot)
        self._statePlotNavigator = NavigationToolbar(self._statePlotCanvas, self._statePlotWidget)
        frame = QFrame()
        frame.setFrameStyle(QFrame.StyledPanel + QFrame.Raised)
        layout = QHBoxLayout()
        layout.addWidget(self._stateplot_xvar_label)
        layout.addWidget(self._stateplot_xvar_combo)
        layout.addWidget(self._stateplot_yvar_label)
        layout.addWidget(self._stateplot_yvar_combo)
        frame.setLayout(layout)
        self._closeStatePlotAction = QAction('Close', self)
        self._closeStatePlotAction.triggered.connect(self._statePlotWidget.close)
        self._closeStatePlotButton = QToolButton()
        self._closeStatePlotButton.setDefaultAction(self._closeStatePlotAction)
        layout = QVBoxLayout()
        layout.addWidget(frame)
        layout.addWidget(self._statePlotCanvas)
        layout.addWidget(self._statePlotNavigator)
        layout.addWidget(self._closeStatePlotButton)
        self._statePlotWidget.setLayout(layout)  
        # Setting the close event so that when the help window is
        # closed the ``State plot`` button becomes unchecked
        self._statePlotWidget.closeEvent = lambda event: self._showStatePlotAction.setChecked(False)

    def _createRunControl(self):
        self._runControlBox = QGroupBox(self)
        self._runControlBox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self._runTimeLabel = QLabel("Run time (ms)", self._runControlBox)
        self._simTimeStepLabel = QLabel("Simulation time step (ms)", self._runControlBox)
        self._runTimeEdit = QLineEdit('%g' % (SquidGui.defaults['runtime']), self._runControlBox)
        set_default_line_edit_size(self._runTimeEdit)
        self._simTimeStepEdit = QLineEdit('%g' % (SquidGui.defaults['simdt']), self._runControlBox)
        set_default_line_edit_size(self._simTimeStepEdit)
        layout = QGridLayout()
        layout.addWidget(self._runTimeLabel, 0, 0)
        layout.addWidget(self._runTimeEdit, 0, 1)
        layout.addWidget(self._simTimeStepLabel, 1, 0)
        layout.addWidget(self._simTimeStepEdit, 1, 1)
        layout.setColumnStretch(2, 1.0)
        layout.setRowStretch(2, 1.0)
        self._runControlBox.setLayout(layout)
        self._runControlDock = QDockWidget('Simulation', self)
        self._runControlDock.setWidget(self._runControlBox)

    def _createChannelControl(self):
        self._channelControlDock = QDockWidget('Channels', self)
        self._channelCtrlBox = QGroupBox(self)
        self._naConductanceToggle = QCheckBox('Block Na+ channel', self._channelCtrlBox)
        self._naConductanceToggle.setToolTip('<html>%s</html>' % (tooltip_NaChan))
        self._kConductanceToggle = QCheckBox('Block K+ channel', self._channelCtrlBox)
        self._kConductanceToggle.setToolTip('<html>%s</html>' % (tooltip_KChan))
        self._kOutLabel = QLabel('[K+]out (mM)', self._channelCtrlBox)
        self._kOutEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.K_out), 
                                         self._channelCtrlBox)
        self._kOutLabel.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        self._kOutEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        set_default_line_edit_size(self._kOutEdit)
        self._naOutLabel = QLabel('[Na+]out (mM)', self._channelCtrlBox)
        self._naOutEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.Na_out), 
                                         self._channelCtrlBox)
        self._naOutLabel.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        self._naOutEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        set_default_line_edit_size(self._naOutEdit)
        self._kInLabel = QLabel('[K+]in (mM)', self._channelCtrlBox)
        self._kInEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.K_in), 
                                         self._channelCtrlBox)
        self._kInEdit.setToolTip(tooltip_Nernst)
        self._naInLabel = QLabel('[Na+]in (mM)', self._channelCtrlBox)
        self._naInEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.Na_in), 
                                         self._channelCtrlBox)
        self._naInEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        self._temperatureLabel = QLabel('Temperature (C)', self._channelCtrlBox)
        self._temperatureEdit = QLineEdit('%g' % (self.defaults['temperature'] - CELSIUS_TO_KELVIN),
                                                self._channelCtrlBox)
        self._temperatureEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        set_default_line_edit_size(self._temperatureEdit)
        for child in self._channelCtrlBox.children():
            if isinstance(child, QLineEdit):
                set_default_line_edit_size(child)
        layout = QGridLayout(self._channelCtrlBox)
        layout.addWidget(self._naConductanceToggle, 0, 0)
        layout.addWidget(self._kConductanceToggle, 1, 0)
        layout.addWidget(self._naOutLabel, 2, 0)
        layout.addWidget(self._naOutEdit, 2, 1)
        layout.addWidget(self._naInLabel, 3, 0)
        layout.addWidget(self._naInEdit, 3, 1)
        layout.addWidget(self._kOutLabel, 4, 0)
        layout.addWidget(self._kOutEdit, 4, 1)
        layout.addWidget(self._kInLabel, 5, 0)
        layout.addWidget(self._kInEdit, 5, 1)
        layout.addWidget(self._temperatureLabel, 6, 0)
        layout.addWidget(self._temperatureEdit, 6, 1)
        layout.setRowStretch(7, 1.0)
        self._channelCtrlBox.setLayout(layout)
        self._channelControlDock.setWidget(self._channelCtrlBox)
        return self._channelCtrlBox        

    def __get_stateplot_data(self, name):
        data = []
        if name == 'V':
            data = self.squid_setup.vm_table.vector
        elif name == 'm':
            data = self.squid_setup.m_table.vector
        elif name == 'h':
            data = self.squid_setup.h_table.vector
        elif name == 'n':
            data = self.squid_setup.n_table.vector
        else:
            raise ValueError('Unrecognized selection: %s' % name )
        return numpy.asarray(data)
    
    def _statePlotYSlot(self, selectedItem):
        ydata = self.__get_stateplot_data(str(selectedItem))
        self._state_plot.set_ydata(ydata)
        self._statePlotAxes.set_ylabel(selectedItem)
        if str(selectedItem) == 'V':
            self._statePlotAxes.set_ylim(-20, 120)
        else:
            self._statePlotAxes.set_ylim(0, 1)
        self._statePlotCanvas.draw()
        
    def _statePlotXSlot(self, selectedItem):
        xdata = self.__get_stateplot_data(str(selectedItem))
        self._state_plot.set_xdata(xdata)
        self._statePlotAxes.set_xlabel(selectedItem)
        if str(selectedItem) == 'V':
            self._statePlotAxes.set_xlim(-20, 120)
        else:
            self._statePlotAxes.set_xlim(0, 1)
        self._statePlotCanvas.draw()

    def _createElectronicsControl(self):
        """Creates a tabbed widget of voltage clamp and current clamp controls"""
        self._electronicsTab = QTabWidget(self)
        self._electronicsTab.addTab(self._getIClampCtrlBox(), 'Current clamp')
        self._electronicsTab.addTab(self._getVClampCtrlBox(), 'Voltage clamp')
        self._electronicsDock = QDockWidget(self)
        self._electronicsDock.setWidget(self._electronicsTab)

    def _getVClampCtrlBox(self):
        vClampPanel = QGroupBox(self)
        self._vClampCtrlBox = vClampPanel
        self._holdingVLabel = QLabel("Holding Voltage (mV)", vClampPanel)
        self._holdingVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.holdingV']), vClampPanel)
        self._holdingTimeLabel = QLabel("Holding Time (ms)", vClampPanel)
        self._holdingTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.holdingT']), vClampPanel)
        self._prePulseVLabel = QLabel("Pre-pulse Voltage (mV)", vClampPanel)
        self._prePulseVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.prepulseV']), vClampPanel)
        self._prePulseTimeLabel = QLabel("Pre-pulse Time (ms)", vClampPanel)
        self._prePulseTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.prepulseT']), vClampPanel)
        self._clampVLabel = QLabel("Clamp Voltage (mV)", vClampPanel)
        self._clampVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.clampV']), vClampPanel)
        self._clampTimeLabel = QLabel("Clamp Time (ms)", vClampPanel)
        self._clampTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.clampT']), vClampPanel)
        for child in vClampPanel.children():
            if isinstance(child, QLineEdit):
                set_default_line_edit_size(child)
        layout = QGridLayout(vClampPanel)
        layout.addWidget(self._holdingVLabel, 0, 0)
        layout.addWidget(self._holdingVEdit, 0, 1)
        layout.addWidget(self._holdingTimeLabel, 1, 0)
        layout.addWidget(self._holdingTimeEdit, 1, 1)
        layout.addWidget(self._prePulseVLabel, 2, 0)
        layout.addWidget(self._prePulseVEdit, 2, 1)
        layout.addWidget(self._prePulseTimeLabel,3,0)
        layout.addWidget(self._prePulseTimeEdit, 3, 1)
        layout.addWidget(self._clampVLabel, 4, 0)
        layout.addWidget(self._clampVEdit, 4, 1)
        layout.addWidget(self._clampTimeLabel, 5, 0)
        layout.addWidget(self._clampTimeEdit, 5, 1)
        layout.setRowStretch(6, 1.0)
        vClampPanel.setLayout(layout)
        return self._vClampCtrlBox

    def _getIClampCtrlBox(self):
        iClampPanel = QGroupBox(self)
        self._iClampCtrlBox = iClampPanel
        self._baseCurrentLabel = QLabel("Base Current Level (uA)",iClampPanel)
        self._baseCurrentEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.baseI']),iClampPanel)
        self._firstPulseLabel = QLabel("First Pulse Current (uA)", iClampPanel)
        self._firstPulseEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstI']), iClampPanel)
        self._firstDelayLabel = QLabel("First Onset Delay (ms)", iClampPanel)
        self._firstDelayEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstD']),iClampPanel)
        self._firstPulseWidthLabel = QLabel("First Pulse Width (ms)", iClampPanel)
        self._firstPulseWidthEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstT']), iClampPanel)
        self._secondPulseLabel = QLabel("Second Pulse Current (uA)", iClampPanel)
        self._secondPulseEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondI']), iClampPanel)
        self._secondDelayLabel = QLabel("Second Onset Delay (ms)", iClampPanel)
        self._secondDelayEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondD']),iClampPanel)
        self._secondPulseWidthLabel = QLabel("Second Pulse Width (ms)", iClampPanel)
        self._secondPulseWidthEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondT']), iClampPanel)
        self._pulseMode = QComboBox(iClampPanel)
        self._pulseMode.addItem("Single Pulse")
        self._pulseMode.addItem("Pulse Train")
        for child in iClampPanel.children():
            if isinstance(child, QLineEdit):
                set_default_line_edit_size(child)
        layout = QGridLayout(iClampPanel)
        layout.addWidget(self._baseCurrentLabel, 0, 0)
        layout.addWidget(self._baseCurrentEdit, 0, 1)
        layout.addWidget(self._firstPulseLabel, 1, 0)
        layout.addWidget(self._firstPulseEdit, 1, 1)
        layout.addWidget(self._firstDelayLabel, 2, 0)
        layout.addWidget(self._firstDelayEdit, 2, 1)
        layout.addWidget(self._firstPulseWidthLabel, 3, 0)
        layout.addWidget(self._firstPulseWidthEdit, 3, 1)
        layout.addWidget(self._secondPulseLabel, 4, 0)
        layout.addWidget(self._secondPulseEdit, 4, 1)
        layout.addWidget(self._secondDelayLabel, 5, 0)
        layout.addWidget(self._secondDelayEdit, 5, 1)
        layout.addWidget(self._secondPulseWidthLabel, 6, 0)
        layout.addWidget(self._secondPulseWidthEdit, 6, 1)
        layout.addWidget(self._pulseMode, 7, 0, 1, 2)
        layout.setRowStretch(8, 1.0)        
        # layout.setSizeConstraint(QLayout.SetFixedSize)
        iClampPanel.setLayout(layout)
        return self._iClampCtrlBox

    def _overlayPlots(self, overlay):        
        if not overlay:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):
                title = axis.get_title()
                axis.clear()
                axis.set_title(title)
            suffix = ''
        else:
            suffix = '_%d' % (len(self._plot_dict['vm']))
        self._vm_axes.set_xlim(0.0, self._runtime)
        self._g_axes.set_xlim(0.0, self._runtime)
        self._im_axes.set_xlim(0.0, self._runtime)
        self._i_axes.set_xlim(0.0, self._runtime)
        self._vm_plot, = self._vm_axes.plot([], [], label='Vm%s'%(suffix))
        self._plot_dict['vm'].append(self._vm_plot)
        self._command_plot, = self._vm_axes.plot([], [], label='command%s'%(suffix))
        self._plot_dict['command'].append(self._command_plot)
        # Channel conductances go to the same subplot
        self._gna_plot, = self._g_axes.plot([], [], label='Na%s'%(suffix))
        self._plot_dict['gna'].append(self._gna_plot)
        self._gk_plot, = self._g_axes.plot([], [], label='K%s'%(suffix))
        self._plot_dict['gk'].append(self._gk_plot)
        # Injection current for Vclamp/Iclamp go to the same subplot
        self._iclamp_plot, = self._im_axes.plot([], [], label='Iclamp%s'%(suffix))
        self._vclamp_plot, = self._im_axes.plot([], [], label='Vclamp%s'%(suffix))
        self._plot_dict['iclamp'].append(self._iclamp_plot)
        self._plot_dict['vclamp'].append(self._vclamp_plot)
        # Channel currents go to the same subplot
        self._ina_plot, = self._i_axes.plot([], [], label='Na%s'%(suffix))
        self._plot_dict['ina'].append(self._ina_plot)
        self._ik_plot, = self._i_axes.plot([], [], label='K%s'%(suffix))
        self._plot_dict['ik'].append(self._ik_plot)
        # self._i_axes.legend()
        # State plots
        self._state_plot, = self._statePlotAxes.plot([], [], label='state%s'%(suffix))
        self._plot_dict['state'].append(self._state_plot)
        self._m_plot, = self._activationParamAxes.plot([],[], label='m%s'%(suffix))
        self._h_plot, = self._activationParamAxes.plot([], [], label='h%s'%(suffix))
        self._n_plot, = self._activationParamAxes.plot([], [], label='n%s'%(suffix))
        self._plot_dict['m'].append(self._m_plot)
        self._plot_dict['h'].append(self._h_plot)
        self._plot_dict['n'].append(self._n_plot)
        if self._showLegendAction.isChecked():
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):            
                axis.legend()

    def _updateAllPlots(self):
        self._updatePlots()
        self._updateStatePlot()

    def _updatePlots(self):
        if len(self.squid_setup.vm_table.vector) <= 0:
            return        
        vm = numpy.asarray(self.squid_setup.vm_table.vector)
        cmd = numpy.asarray(self.squid_setup.cmd_table.vector)
        ik = numpy.asarray(self.squid_setup.ik_table.vector)
        ina = numpy.asarray(self.squid_setup.ina_table.vector)
        iclamp = numpy.asarray(self.squid_setup.iclamp_table.vector)
        vclamp = numpy.asarray(self.squid_setup.vclamp_table.vector)
        gk = numpy.asarray(self.squid_setup.gk_table.vector)
        gna = numpy.asarray(self.squid_setup.gna_table.vector)
        time_series = numpy.linspace(0, self._plotdt * len(vm), len(vm))        
        self._vm_plot.set_data(time_series, vm)
        time_series = numpy.linspace(0, self._plotdt * len(cmd), len(cmd))        
        self._command_plot.set_data(time_series, cmd)
        time_series = numpy.linspace(0, self._plotdt * len(ik), len(ik))
        self._ik_plot.set_data(time_series, ik)
        time_series = numpy.linspace(0, self._plotdt * len(ina), len(ina))
        self._ina_plot.set_data(time_series, ina)
        time_series = numpy.linspace(0, self._plotdt * len(iclamp), len(iclamp))
        self._iclamp_plot.set_data(time_series, iclamp)
        time_series = numpy.linspace(0, self._plotdt * len(vclamp), len(vclamp))
        self._vclamp_plot.set_data(time_series, vclamp)
        time_series = numpy.linspace(0, self._plotdt * len(gk), len(gk))
        self._gk_plot.set_data(time_series, gk)
        time_series = numpy.linspace(0, self._plotdt * len(gna), len(gna))
        self._gna_plot.set_data(time_series, gna)
        # self._vm_axes.margins(y=0.1)
        # self._g_axes.margin(y=0.1)
        # self._im_axes.margins(y=0.1)
        # self._i_axes.margins(y=0.1)
        if self._autoscaleAction.isChecked():
            for axis in self._plotFigure.axes:
                axis.relim()
                axis.margins(0.1, 0.1)
                axis.autoscale_view(tight=True)
        else:
            self._vm_axes.set_ylim(-20.0, 120.0)
            self._g_axes.set_ylim(0.0, 0.5)
            self._im_axes.set_ylim(-0.5, 0.5)
            self._i_axes.set_ylim(-10, 10)
        self._vm_axes.set_xlim(0.0, time_series[-1])
        self._g_axes.set_xlim(0.0, time_series[-1])
        self._im_axes.set_xlim(0.0, time_series[-1])
        self._i_axes.set_xlim(0.0, time_series[-1])
        self._plotCanvas.draw()

    def _updateStatePlot(self):
        if len(self.squid_setup.vm_table.vector) <= 0:
            return
        sx = str(self._stateplot_xvar_combo.currentText())
        sy = str(self._stateplot_yvar_combo.currentText())
        xdata = self.__get_stateplot_data(sx)
        ydata = self.__get_stateplot_data(sy)
        minlen = min(len(xdata), len(ydata))
        self._state_plot.set_data(xdata[:minlen], ydata[:minlen])
        self._statePlotAxes.set_xlabel(sx)
        self._statePlotAxes.set_ylabel(sy)
        if sx == 'V':
            self._statePlotAxes.set_xlim(-20, 120)
        else:
            self._statePlotAxes.set_xlim(0, 1)
        if sy == 'V':
            self._statePlotAxes.set_ylim(-20, 120)
        else:
            self._statePlotAxes.set_ylim(0, 1)
        self._activationParamAxes.set_xlim(0, self._runtime)
        m = self.__get_stateplot_data('m')
        n = self.__get_stateplot_data('n')
        h = self.__get_stateplot_data('h')
        time_series = numpy.linspace(0, self._plotdt*len(m), len(m))
        self._m_plot.set_data(time_series, m)
        time_series = numpy.linspace(0, self._plotdt*len(h), len(h))
        self._h_plot.set_data(time_series, h)
        time_series = numpy.linspace(0, self._plotdt*len(n), len(n))
        self._n_plot.set_data(time_series, n)
        if self._autoscaleAction.isChecked():
            for axis in self._statePlotFigure.axes:
                axis.relim()
                axis.set_autoscale_on(True)
                axis.autoscale_view(True)
        self._statePlotCanvas.draw()

    def _runSlot(self):
        if moose.isRunning():
            print('Stopping simulation in progress ...')
            moose.stop()
        self._runtime = self.getFloatInput(self._runTimeEdit, self._runTimeLabel.text())
        self._overlayPlots(self._overlayAction.isChecked())
        self._simdt = self.getFloatInput(self._simTimeStepEdit, self._simTimeStepLabel.text())
        clampMode = None
        singlePulse = True
        if self._electronicsTab.currentWidget() == self._vClampCtrlBox:
            clampMode = 'vclamp'
            baseLevel = self.getFloatInput(self._holdingVEdit, self._holdingVLabel.text())
            firstDelay = self.getFloatInput(self._holdingTimeEdit, self._holdingTimeLabel.text())
            firstWidth = self.getFloatInput(self._prePulseTimeEdit, self._prePulseTimeLabel.text())
            firstLevel = self.getFloatInput(self._prePulseVEdit, self._prePulseVLabel.text())
            secondDelay = firstWidth
            secondWidth = self.getFloatInput(self._clampTimeEdit, self._clampTimeLabel.text())
            secondLevel = self.getFloatInput(self._clampVEdit, self._clampVLabel.text())
            if not self._autoscaleAction.isChecked():
                self._im_axes.set_ylim(-10.0, 10.0)
        else:
            clampMode = 'iclamp'
            baseLevel = self.getFloatInput(self._baseCurrentEdit, self._baseCurrentLabel.text())
            firstDelay = self.getFloatInput(self._firstDelayEdit, self._firstDelayLabel.text())
            firstWidth = self.getFloatInput(self._firstPulseWidthEdit, self._firstPulseWidthLabel.text())
            firstLevel = self.getFloatInput(self._firstPulseEdit, self._firstPulseLabel.text())
            secondDelay = self.getFloatInput(self._secondDelayEdit, self._secondDelayLabel.text())
            secondLevel = self.getFloatInput(self._secondPulseEdit, self._secondPulseLabel.text())
            secondWidth = self.getFloatInput(self._secondPulseWidthEdit, self._secondPulseWidthLabel.text())
            singlePulse = (self._pulseMode.currentIndex() == 0)
            if not self._autoscaleAction.isChecked():
                self._im_axes.set_ylim(-0.4, 0.4)
        self.squid_setup.clamp_ckt.configure_pulses(baseLevel=baseLevel,
                                                    firstDelay=firstDelay,
                                                    firstWidth=firstWidth,
                                                    firstLevel=firstLevel,
                                                    secondDelay=secondDelay,
                                                    secondWidth=secondWidth,
                                                    secondLevel=secondLevel,
                                                    singlePulse=singlePulse)
        if self._kConductanceToggle.isChecked():
            self.squid_setup.squid_axon.specific_gK = 0.0
        else:
            self.squid_setup.squid_axon.specific_gK = SquidAxon.defaults['specific_gK']
        if self._naConductanceToggle.isChecked():
            self.squid_setup.squid_axon.specific_gNa = 0.0
        else:
            self.squid_setup.squid_axon.specific_gNa = SquidAxon.defaults['specific_gNa']
        self.squid_setup.squid_axon.celsius = self.getFloatInput(self._temperatureEdit, self._temperatureLabel.text())
        self.squid_setup.squid_axon.K_out = self.getFloatInput(self._kOutEdit, self._kOutLabel.text())
        self.squid_setup.squid_axon.Na_out = self.getFloatInput(self._naOutEdit, self._naOutLabel.text())
        self.squid_setup.squid_axon.K_in = self.getFloatInput(self._kInEdit, self._kInLabel.text())
        self.squid_setup.squid_axon.Na_in = self.getFloatInput(self._naInEdit, self._naInLabel.text())
        self.squid_setup.squid_axon.updateEk()
        self.squid_setup.schedule(self._simdt, self._plotdt, clampMode)
        # The following line is for use with Qthread
        self.squid_setup.run(self._runtime)
        self._updateAllPlots()

    def _toggleDocking(self, on):
        self._channelControlDock.setFloating(on)
        self._electronicsDock.setFloating(on)
        self._runControlDock.setFloating(on)
        
    def _restoreDocks(self):
        self._channelControlDock.setVisible(True)
        self._electronicsDock.setVisible(True)
        self._runControlDock.setVisible(True)

    def _initActions(self):
        self._runAction = QAction(self.tr('Run'), self)
        self._runAction.setShortcut(self.tr('F5'))
        self._runAction.setToolTip('Run simulation (F5)')
        self._runAction.triggered.connect( self._runSlot)
        self._resetToDefaultsAction = QAction(self.tr('Restore defaults'), self)
        self._resetToDefaultsAction.setToolTip('Reset all settings to their default values')
        self._resetToDefaultsAction.triggered.connect( self._useDefaults)
        self._showLegendAction = QAction(self.tr('Display legend'), self)
        self._showLegendAction.setCheckable(True)
        self._showLegendAction.toggled.connect(self._showLegend)
        self._showStatePlotAction = QAction(self.tr('State plot'), self)
        self._showStatePlotAction.setCheckable(True)
        self._showStatePlotAction.setChecked(False)
        self._showStatePlotAction.toggled.connect(self._statePlotWidget.setVisible)
        self._autoscaleAction  = QAction(self.tr('Auto-scale plots'), self)
        self._autoscaleAction.setCheckable(True)
        self._autoscaleAction.setChecked(False)
        self._autoscaleAction.toggled.connect(self._autoscale)
        self._overlayAction = QAction('Overlay plots', self)
        self._overlayAction.setCheckable(True)
        self._overlayAction.setChecked(False) 
        self._dockAction = QAction('Undock all', self)
        self._dockAction.setCheckable(True)
        self._dockAction.setChecked(False)
        #  self._dockAction.toggle.connect( self._toggleDocking)
        self._restoreDocksAction = QAction('Show all', self)
        self._restoreDocksAction.triggered.connect( self._restoreDocks)
        self._quitAction = QAction(self.tr('&Quit'), self)
        self._quitAction.setShortcut(self.tr('Ctrl+Q'))
        self._quitAction.triggered.connect(qApp.closeAllWindows)

        

    def _createRunToolBar(self):
        self._simToolBar = self.addToolBar(self.tr('Simulation control'))
        self._simToolBar.addAction(self._quitAction)
        self._simToolBar.addAction(self._runAction)
        self._simToolBar.addAction(self._resetToDefaultsAction)
        self._simToolBar.addAction(self._dockAction)
        self._simToolBar.addAction(self._restoreDocksAction)

    def _createPlotToolBar(self):
        self._plotToolBar = self.addToolBar(self.tr('Plotting control'))
        self._plotToolBar.addAction(self._showLegendAction)
        self._plotToolBar.addAction(self._autoscaleAction)
        self._plotToolBar.addAction(self._overlayAction)
        self._plotToolBar.addAction(self._showStatePlotAction)
        self._plotToolBar.addAction(self._helpAction)
        self._plotToolBar.addAction(self._helpBiophysicsAction)

    def _showLegend(self, on):
        if on:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):            
                axis.legend().set_visible(True)
        else:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):            
                axis.legend().set_visible(False)
        self._plotCanvas.draw()
        self._statePlotCanvas.draw()

    def _autoscale(self, on):
        if on:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):            
                axis.relim()
                axis.set_autoscale_on(True)
                axis.autoscale_view(True)
        else:
            for axis in self._plotFigure.axes:
                axis.set_autoscale_on(False)            
            self._vm_axes.set_ylim(-20.0, 120.0)
            self._g_axes.set_ylim(0.0, 0.5)
            self._im_axes.set_ylim(-0.5, 0.5)
            self._i_axes.set_ylim(-10, 10)
        self._plotCanvas.draw()
        self._statePlotCanvas.draw()
        
    def _useDefaults(self):
        self._runTimeEdit.setText('%g' % (self.defaults['runtime']))
        self._simTimeStepEdit.setText('%g' % (self.defaults['simdt']))
        self._overlayAction.setChecked(False)
        self._naConductanceToggle.setChecked(False)
        self._kConductanceToggle.setChecked(False)
        self._kOutEdit.setText('%g' % (SquidGui.defaults['K_out']))
        self._naOutEdit.setText('%g' % (SquidGui.defaults['Na_out']))
        self._kInEdit.setText('%g' % (SquidGui.defaults['K_in']))
        self._naInEdit.setText('%g' % (SquidGui.defaults['Na_in']))
        self._temperatureEdit.setText('%g' % (SquidGui.defaults['temperature'] - CELSIUS_TO_KELVIN))
        self._holdingVEdit.setText('%g' % (SquidGui.defaults['vclamp.holdingV']))
        self._holdingTimeEdit.setText('%g' % (SquidGui.defaults['vclamp.holdingT']))
        self._prePulseVEdit.setText('%g' % (SquidGui.defaults['vclamp.prepulseV']))
        self._prePulseTimeEdit.setText('%g' % (SquidGui.defaults['vclamp.prepulseT']))
        self._clampVEdit.setText('%g' % (SquidGui.defaults['vclamp.clampV']))
        self._clampTimeEdit.setText('%g' % (SquidGui.defaults['vclamp.clampT']))
        self._baseCurrentEdit.setText('%g' % (SquidGui.defaults['iclamp.baseI']))
        self._firstPulseEdit.setText('%g' % (SquidGui.defaults['iclamp.firstI']))
        self._firstDelayEdit.setText('%g' % (SquidGui.defaults['iclamp.firstD']))
        self._firstPulseWidthEdit.setText('%g' % (SquidGui.defaults['iclamp.firstT']))
        self._secondPulseEdit.setText('%g' % (SquidGui.defaults['iclamp.secondI']))
        self._secondDelayEdit.setText('%g' % (SquidGui.defaults['iclamp.secondD']))
        self._secondPulseWidthEdit.setText('%g' % (SquidGui.defaults['iclamp.secondT']))
        self._pulseMode.setCurrentIndex(0)

    def _onScroll(self, event):
        if event.inaxes is None:
            return  
        axes = event.inaxes
        zoom = 0.0
        if event.button == 'up':
            zoom = -1.0
        elif event.button == 'down':
            zoom = 1.0
        if zoom != 0.0:
            self._plotNavigator.push_current()
            axes.get_xaxis().zoom(zoom)
            axes.get_yaxis().zoom(zoom)        
        self._plotCanvas.draw()

    def closeEvent(self, event):
        qApp.closeAllWindows()

    def _showBioPhysicsHelp(self):
        self._createHelpMessage()
        self._helpMessageText.setText('<html><p>%s</p><p>%s</p><p>%s</p><p>%s</p><p>%s</p></html>' % 
                                      (tooltip_Nernst, 
                                       tooltip_Erest,
                                       tooltip_KChan,
                                       tooltip_NaChan,
                                       tooltip_Im))
        self._helpWindow.setVisible(True)

    def _showRunningHelp(self):
        self._createHelpMessage()
        self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
        self._helpWindow.setVisible(True)

    def _createHelpMessage(self):
        if hasattr(self, '_helpWindow'):
            return
        self._helpWindow = QWidget()
        self._helpWindow.setWindowFlags(QtCore.Qt.Window)
        layout = QVBoxLayout()
        self._helpWindow.setLayout(layout)
        self._helpMessageArea = QScrollArea()
        self._helpMessageText = QTextBrowser()
        self._helpMessageText.setOpenExternalLinks(True)
        self._helpMessageArea.setWidget(self._helpMessageText)
        layout.addWidget(self._helpMessageText)
        self._squidGuiPath = os.path.dirname(os.path.abspath(__file__))
        self._helpBaseURL = os.path.join(self._squidGuiPath,'help.html')
        self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
        self._helpMessageText.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._helpMessageArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._helpMessageText.setMinimumSize(800, 600)
        self._closeHelpAction = QAction('Close', self)
        self._closeHelpAction.triggered.connect(self._helpWindow.close)        
        # Setting the close event so that the ``Help`` button is
        # unchecked when the help window is closed
        self._helpWindow.closeEvent = lambda event: self._helpAction.setChecked(False)
        self._helpTOCAction = QAction('Help running demo', self)
        self._helpTOCAction.triggered.connect( self._jumpToHelpTOC)                
        # This panel is for putting two buttons using horizontal
        # layout
        panel = QFrame()
        panel.setFrameStyle(QFrame.StyledPanel + QFrame.Raised)
        layout.addWidget(panel)
        layout = QHBoxLayout()
        panel.setLayout(layout)
        self._helpAction = QAction('Help running', self)
        self._helpAction.triggered.connect(self._showRunningHelp)
        self._helpBiophysicsAction = QAction('Help biophysics', self)
        self._helpBiophysicsAction.triggered.connect(self._showBioPhysicsHelp)
        self._helpTOCButton = QToolButton()
        self._helpTOCButton.setDefaultAction(self._helpTOCAction)
        self._helpBiophysicsButton = QToolButton()
        self._helpBiophysicsButton.setDefaultAction(self._helpBiophysicsAction)
        layout.addWidget(self._helpTOCButton)
        layout.addWidget(self._helpBiophysicsButton)
        self._closeHelpButton = QToolButton()
        self._closeHelpButton.setDefaultAction(self._closeHelpAction)
        layout.addWidget(self._closeHelpButton)
        
    def _jumpToHelpTOC(self):
        self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
Пример #16
0
class CalibWin(QWidget, _calf.calib_functions_mixin, _ie.Imp_Exp_Mixin):
    """ Energy calibration window

    For the names of the children widgets, I tried to put suffixes that indicate clearly their types:
    *_btn -> QPushButton,
    *_le -> QLineEdit,
    *_lb -> QLabel,
    *layout -> QHBoxLayout, QVBoxLayout or QGridLayout,
    *_box -> QGroupBox,
    *_cb -> QCheckBox,
    *_rb -> QRadioButton

    The functions that are connected to a widget's event have the suffix _lr (for 'listener'). For example, a button named
    test_btn will be connected to a function test_lr.
    Some functions may be connected to widgets but without the suffix _lr in their names. It means that they are not only
    called when interacting with the widget.
    """

    ##################################################################################
    ############################ Widget Initialization ###############################

    def __init__(self, parent=None):
        """Initialization of the window

        the main layout is called mainLayout. It is divided in two:
            - graphLayout: the left part, contains all the figures
            - commandLayout: the right part, contains all the buttons, fields, checkboxes...
        Both graphLayout and commandLayout are divided into sub-layouts.

        This function calls several functions to initialize each part of the window. The name of these functions contains
        'init_*layout'.
        """
        super(CalibWin, self).__init__(parent=parent)

        self.setWindowTitle("Energy Calibration")
        self.mainlayout = QHBoxLayout()
        self.graphlayout = QVBoxLayout()
        self.commandlayout = QVBoxLayout()
        self.commandlayout.setSpacing(10)

        # initialization of all the widgets/layouts
        self.init_btnlayout()
        self.init_tof2evlayout()
        self.init_eparlayout()
        self.init_fitparlayout()
        self.init_envectlayout()
        self.init_tofgraphlayout()
        self.init_graphauxlayout()

        # making the buttons not resizable
        for widget in self.children():
            if isinstance(widget, QPushButton):
                widget.setSizePolicy(0, 0)

        self.mainlayout.addLayout(self.graphlayout)
        self.mainlayout.addLayout(self.commandlayout)
        self.setLayout(self.mainlayout)

        self.init_var()

        self.show()

    def init_var(self):
        ''' Initialization of instance attributes'''

        self.withsb_bool = False
        self.calibloaded = False
        self.dataloaded = False
        self.bgndremoved = False
        self.threshyBool = False
        self.threshxminBool = False
        self.threshxmaxBool = False
        self.showexppeaksBool = False
        self.calibBool = False
        self.peaksfound = False

        self.thxmin = 0
        self.thy = 0
        self.thxmax = 0

        self.counts = []

        self.gas_combo.setCurrentIndex(2)  # Argon

    def init_btnlayout(self):
        ''' In commandLayout - Initialization of the top right part of the layout, with 6 buttons (see just below)'''

        btnlayout = QGridLayout()
        btnlayout.setSpacing(10)

        self.load_btn = QPushButton("Load data", self)
        self.rmbgnd_btn = QPushButton("Remove bgnd", self)
        self.findpeaks_btn = QPushButton("Find peaks", self)
        self.rmpeaks_btn = QPushButton("Remove peaks", self)
        self.exportcalib_btn = QPushButton("Export calib", self)
        self.importcalib_btn = QPushButton("Import calib", self)
        self.exportXUV_btn = QPushButton("Export XUV", self)

        self.rmbgnd_btn.setEnabled(False)
        self.findpeaks_btn.setEnabled(False)
        self.rmpeaks_btn.setEnabled(False)
        self.exportcalib_btn.setEnabled(False)
        self.importcalib_btn.setEnabled(False)
        self.exportXUV_btn.setEnabled(False)

        self.load_btn.clicked.connect(self.loadfile_lr)
        self.rmbgnd_btn.clicked.connect(self.rmbgnd_lr)
        self.findpeaks_btn.clicked.connect(self.findpeaks_lr)
        self.importcalib_btn.clicked.connect(self.importcalib_lr)
        self.rmpeaks_btn.clicked.connect(self.removepeaks_lr)
        self.exportXUV_btn.clicked.connect(self.exportXUV_lr)
        self.exportcalib_btn.clicked.connect(self.exportcalib_lr)

        btnlayout.addWidget(self.load_btn, 0, 0)
        btnlayout.addWidget(self.rmbgnd_btn, 0, 1)
        btnlayout.addWidget(self.findpeaks_btn, 1, 0)
        btnlayout.addWidget(self.rmpeaks_btn, 1, 1)
        btnlayout.addWidget(self.exportcalib_btn, 1, 3)
        btnlayout.addWidget(self.importcalib_btn, 1, 2)
        btnlayout.addWidget(self.exportXUV_btn, 0, 3)
        self.commandlayout.addLayout(btnlayout)

    def init_tof2evlayout(self):
        ''' In commandLayout - Initialization of the tof to eV section: parameters of the af.find_local_maxima function,
            'TOF to energy' button and 'with sidebands checkbox' '''

        tof2evlayout = QHBoxLayout()
        flmlayout = QGridLayout()
        flmlayout.setSpacing(10)
        self.flm_box = QGroupBox(self)
        self.flm_box.setTitle("Find local maxima parameters")

        self.sm1_le = QLineEdit("5", self)
        self.sm2_le = QLineEdit("100", self)
        self.mindt_le = QLineEdit("10", self)

        flmlayout.addWidget(QLabel("smooth1"), 0, 0)
        flmlayout.addWidget(self.sm1_le, 1, 0)
        flmlayout.addWidget(QLabel("smooth2"), 0, 1)
        flmlayout.addWidget(self.sm2_le, 1, 1)
        flmlayout.addWidget(QLabel("min dt"), 0, 2)
        flmlayout.addWidget(self.mindt_le, 1, 2)
        self.flm_box.setLayout(flmlayout)

        for widget in self.flm_box.children():
            if isinstance(widget, QLineEdit):
                widget.setSizePolicy(0, 0)
                widget.setFixedSize(50, 20)

        self.tof2en_btn = QPushButton("TOF to energy", self)
        self.tof2en_btn.clicked.connect(self.tof2en_lr)
        self.tof2en_btn.setEnabled(False)

        self.withsb_cb = QCheckBox("With sidebands", self)
        self.withsb_cb.stateChanged.connect(self.withsb_fn)

        tof2evlayout.addWidget(self.flm_box)
        tof2evlayout.addWidget(self.withsb_cb)
        tof2evlayout.addWidget(self.tof2en_btn)
        self.commandlayout.addLayout(tof2evlayout)

    def init_eparlayout(self):
        ''' In commandLayout - Initialization of the experimental parameters section: Retarding potential, TOF length,
            wavelength, gas and first harmonic expected to see.'''

        gases = cts.GASLIST

        epar_box = QGroupBox(self)
        epar_box.setTitle("Experimental parameters")
        epar_box.setSizePolicy(0, 0)
        eparlayout = QGridLayout()
        eparlayout.setSpacing(10)

        self.retpot_le = QLineEdit(str(cts.cur_Vp), self)
        self.toflength_le = QLineEdit(str(cts.cur_L), self)
        self.wvlength_le = QLineEdit(str(cts.lambda_start), self)
        self.gas_combo = QComboBox(self)
        self.gas_combo.addItems(gases)
        self.firstharm_le = QLineEdit(str(cts.first_harm), self)

        self.retpot_le.returnPressed.connect(self.update_cts_fn)
        self.toflength_le.returnPressed.connect(self.update_cts_fn)
        self.wvlength_le.returnPressed.connect(self.update_cts_fn)
        self.firstharm_le.returnPressed.connect(self.update_cts_fn)
        self.gas_combo.currentIndexChanged.connect(self.gas_combo_lr)

        eparlayout.addWidget(QLabel("Ret. pot. (V)"), 0, 0)
        eparlayout.addWidget(self.retpot_le, 1, 0)
        eparlayout.addWidget(QLabel("TOF length (m)"), 0, 1)
        eparlayout.addWidget(self.toflength_le, 1, 1)
        eparlayout.addWidget(QLabel("lambda (nm)"), 0, 2)
        eparlayout.addWidget(self.wvlength_le, 1, 2)
        eparlayout.addWidget(QLabel("gas"), 0, 3)
        eparlayout.addWidget(self.gas_combo, 1, 3)
        eparlayout.addWidget(QLabel("1st harm."), 0, 4)
        eparlayout.addWidget(self.firstharm_le, 1, 4)

        epar_box.setLayout(eparlayout)

        for widget in epar_box.children():
            if isinstance(widget, QLineEdit) or isinstance(widget, QComboBox):
                widget.setFixedSize(50, 20)
                widget.setSizePolicy(0, 0)

        self.commandlayout.addWidget(epar_box)

    def init_fitparlayout(self):
        ''' In commandLayout - Initialization of the fit parameter section with a, t0 and c. First line: guess values calculated
            from the experimental parameters. Second line: fitted values.'''

        fitpar_box = QGroupBox()
        fitpar_box.setTitle("Calibration parameters")
        fitpar_box.setSizePolicy(0, 0)
        fitparlayout = QGridLayout()
        fitparlayout.setSpacing(10)

        self.aguess_lb = QLabel(self)
        self.afit_lb = QLabel(self)
        self.t0guess_lb = QLabel(self)
        self.t0fit_lb = QLabel(self)
        self.cguess_lb = QLabel(self)
        self.cfit_lb = QLabel(self)

        fitparlayout.addWidget(QLabel("a"), 0, 0)
        fitparlayout.addWidget(self.aguess_lb, 1, 0)
        fitparlayout.addWidget(self.afit_lb, 2, 0)
        fitparlayout.addWidget(QLabel("t0"), 0, 1)
        fitparlayout.addWidget(self.t0guess_lb, 1, 1)
        fitparlayout.addWidget(self.t0fit_lb, 2, 1)
        fitparlayout.addWidget(QLabel("c"), 0, 2)
        fitparlayout.addWidget(self.cguess_lb, 1, 2)
        fitparlayout.addWidget(self.cfit_lb, 2, 2)
        fitparlayout.addWidget(QLabel("guess"), 1, 3)
        fitparlayout.addWidget(QLabel("calc"), 2, 3)
        text = "q=a*1/(t-t0)²+c"
        fitparlayout.addWidget(QLabel(text), 1, 4)

        fitpar_box.setLayout(fitparlayout)

        for widget in fitpar_box.children():
            if isinstance(widget, QLabel) and widget.text() != text:
                widget.setSizePolicy(0, 0)
                widget.setFixedSize(55, 15)

        self.commandlayout.addWidget(fitpar_box)

    def init_envectlayout(self):
        ''' In commandLayout - Initialization of the resulting energy vector section, with elow, ehigh and dE'''

        envect_box = QGroupBox()
        envect_box.setTitle("Energy vector parameters")
        envect_box.setSizePolicy(0, 0)
        envectlayout = QGridLayout()
        envectlayout.setSpacing(10)

        self.elow_le = QLineEdit("{:.2f}".format(cts.elow), self)
        self.ehigh_le = QLineEdit("{:.2f}".format(cts.ehigh), self)
        self.dE_le = QLineEdit(str(cts.dE), self)

        self.elow_le.returnPressed.connect(self.update_envect_fn)
        self.ehigh_le.returnPressed.connect(self.update_envect_fn)
        self.dE_le.returnPressed.connect(self.update_envect_fn)

        envectlayout.addWidget(QLabel("E low (eV)"), 0, 0)
        envectlayout.addWidget(self.elow_le, 1, 0)
        envectlayout.addWidget(QLabel("E high (eV)"), 0, 1)
        envectlayout.addWidget(self.ehigh_le, 1, 1)
        envectlayout.addWidget(QLabel("dE (eV)"), 0, 2)
        envectlayout.addWidget(self.dE_le, 1, 2)

        envect_box.setLayout(envectlayout)

        for widget in envect_box.children():
            if isinstance(widget, QLabel) or isinstance(widget, QLineEdit):
                widget.setSizePolicy(0, 0)
                widget.setFixedSize(55, 20)

        self.commandlayout.addWidget(envect_box)
        self.update_envect_fn()

    def init_tofgraphlayout(self):
        ''' In graphLayout - Initialization of the top figure on the window, where the time of flight is plotted'''

        tof_fig = Figure(figsize=(4, 3), dpi=100)
        self.tof_fc = FigureCanvas(tof_fig)
        self.tof_fc.mpl_connect('button_press_event', self.onclick)
        self.tof_ax = self.tof_fc.figure.add_subplot(111)
        self.tof_fc.draw()
        tof_nav = NavigationToolbar2QT(self.tof_fc, self)
        tof_nav.setStyleSheet("QToolBar { border: 0px }")

        tgparalayout = QGridLayout()
        self.threshtype_bgroup = QButtonGroup()
        rblayout = QGridLayout()
        self.setth_cb = QCheckBox("Set threshold", self)
        self.setth_cb.setEnabled(False)
        self.setth_cb.stateChanged.connect(self.setth_lr)
        self.addpeak_cb = QCheckBox("Add peak", self)
        self.addpeak_cb.setEnabled(False)
        self.addpeak_cb.stateChanged.connect(self.addpeak_lr)
        self.showexppeaks_cb = QCheckBox("Show expected peaks", self)
        self.showexppeaks_cb.stateChanged.connect(self.showexppeaks_lr)
        self.showexppeaks_cb.setEnabled(False)

        self.clear_btn = QPushButton("Clear", self)
        self.clear_btn.clicked.connect(self.clear_lr)
        self.clear_btn.setEnabled(False)

        self.Y_rb = QRadioButton("Y", self)
        self.Y_rb.value = "Y"
        self.Y_rb.toggled.connect(self.threshtype_lr)
        self.Y_rb.toggle()
        self.Y_rb.setEnabled(False)

        self.xmin_rb = QRadioButton("X min", self)
        self.xmin_rb.value = "Xm"
        self.xmin_rb.toggled.connect(self.threshtype_lr)
        self.xmin_rb.setEnabled(False)

        self.xmax_rb = QRadioButton("X max", self)
        self.xmax_rb.value = "XM"
        self.xmax_rb.toggled.connect(self.threshtype_lr)
        self.xmax_rb.setEnabled(False)

        self.minus_sign_cb = QCheckBox("*(-1)", self)
        self.minus_sign_cb.setEnabled(False)
        self.minus_sign_cb.stateChanged.connect(self.minus_sign_lr)

        self.threshtype_bgroup.addButton(self.Y_rb)
        self.threshtype_bgroup.addButton(self.xmin_rb)
        self.threshtype_bgroup.addButton(self.xmax_rb)

        rblayout.addWidget(self.Y_rb, 0, 0)
        rblayout.addWidget(self.xmin_rb, 0, 1)
        rblayout.addWidget(self.xmax_rb, 0, 2)
        tgparalayout.addWidget(self.setth_cb, 0, 0)
        tgparalayout.addWidget(self.addpeak_cb, 0, 1)
        tgparalayout.addWidget(self.showexppeaks_cb, 0, 2)
        tgparalayout.addWidget(self.clear_btn, 0, 3)
        tgparalayout.addLayout(rblayout, 1, 0, 1, 3)
        tgparalayout.addWidget(self.minus_sign_cb, 1, 3)

        self.graphlayout.addWidget(self.tof_fc)
        self.graphlayout.addWidget(tof_nav)
        self.graphlayout.addLayout(tgparalayout)

    def init_graphauxlayout(self):
        ''' In graphLayout - Initialization the two bottom figures on the window'''

        graphauxlayout = QHBoxLayout()
        ga1layout = QVBoxLayout()
        ga2layout = QVBoxLayout()

        fit_fig = Figure(figsize=(2, 2), dpi=100)
        self.fit_fc = FigureCanvas(fit_fig)
        self.fit_fc.setSizePolicy(1, 0)
        self.fit_ax = self.fit_fc.figure.add_subplot(111)
        self.fit_ax.tick_params(labelsize=8)
        ga1layout.addWidget(self.fit_fc)
        self.fit_fc.draw()

        en_fig = Figure(figsize=(2, 2), dpi=100)
        self.en_fc = FigureCanvas(en_fig)
        #self.en_fc.setSizePolicy(1, 0)
        self.en_ax = self.en_fc.figure.add_subplot(111)
        self.en_ax.tick_params(labelsize=8)
        self.en_fc.draw()
        en_nav = NavigationToolbar2QT(self.en_fc, self)
        en_nav.setStyleSheet("QToolBar { border: 0px }")
        ga2layout.addWidget(self.en_fc)
        ga2layout.addWidget(en_nav)

        graphauxlayout.addLayout(ga1layout)
        graphauxlayout.addLayout(ga2layout)
        self.graphlayout.addLayout(graphauxlayout)

    #################################################################################
    ############################ Other methods ######################################

    def update_fitpar_fn(self):
        ''' Updating the fit parameters on the window'''

        if (self.calibBool):
            self.afit_lb.setText("{:.3e}".format(cts.afit))
            self.t0fit_lb.setText("{:.3e}".format(cts.t0fit))
            self.cfit_lb.setText("{:.3f}".format(cts.cfit))

    def update_envect_fn(self):
        ''' Updating th energy vector parameters with the values written in the associated QLineEdit objects'''

        cts.elow = float(self.elow_le.text())
        cts.ehigh = float(self.ehigh_le.text())
        cts.dE = float(self.dE_le.text())
        self.elow_le.setText("{:.2f}".format(cts.elow))
        self.ehigh_le.setText("{:.2f}".format(cts.ehigh))
        self.window().updateglobvar_fn()

    def gas_combo_lr(self, i):
        ''' Gas QCombobox listener'''
        cts.cur_Ip = cts.IPLIST[i]
        cts.first_harm = cts.FIRST_HARMLIST[i]
        self.firstharm_le.setText(str(cts.first_harm))
        cts.elow = (cts.first_harm - 1) * cts.HEV * cts.cur_nu
        self.elow_le.setText("{:.2f}".format(cts.elow))
        self.update_cts_fn()

    def threshtype_lr(self):
        ''' Listener of the threshold radiobuttons: Y, Xmin or Xmax'''
        rb = self.sender()
        self.threshtype = rb.value

    def withsb_fn(self, state):
        ''' "with sidebands" checkbox listener '''
        if state == Qt.Checked:
            self.withsb_bool = True
        else:
            self.withsb_bool = False

    def showexppeaks_lr(self, state):
        ''' "show expected peaks" checkbox listener '''
        if state == Qt.Checked:
            self.showexppeaksBool = True
        else:
            self.showexppeaksBool = False
        self.refreshplot_fn()

    def setth_lr(self):
        ''' "set threshold" checkbox listener '''
        if self.setth_cb.isChecked():
            self.addpeak_cb.setCheckState(Qt.Unchecked)

    def addpeak_lr(self):
        ''' "add peak" checkbox listener '''
        if self.addpeak_cb.isChecked():
            self.setth_cb.setCheckState(Qt.Unchecked)

    def removepeaks_lr(self):
        ''' "remove peaks" button listener '''
        rmp = rmPeaksDialog(self)  # new class defined below

    def refreshplot_fn(self):
        ''' Updating the top left (TOF) graph'''
        xmin, xmax = self.tof_ax.get_xlim()
        ymin, ymax = self.tof_ax.get_ylim()
        self.tof_ax.cla()

        self.tof_ax.xaxis.set_major_formatter(FormatStrFormatter('%2.e'))
        self.tof_ax.yaxis.set_major_formatter(FormatStrFormatter('%1.e'))
        self.tof_ax.set_ylabel("counts (arb. units)")
        self.tof_ax.set_xlabel("TOF (s)")

        if self.dataloaded:
            self.tof_ax.plot(self.counts[:, 0], self.counts[:, 1])
        if self.threshyBool:
            self.tof_ax.plot(self.threshyline[:, 0], self.threshyline[:, 1],
                             'k')
        if self.threshxminBool:
            self.tof_ax.plot(self.threshxminline[:, 0],
                             self.threshxminline[:, 1], 'k')
        if self.threshxmaxBool:
            self.tof_ax.plot(self.threshxmaxline[:, 0],
                             self.threshxmaxline[:, 1], 'k')
        if self.peaksfound:
            self.tof_ax.plot(self.maximaIndices, self.maximaIntensity, 'ro')
            self.tof_ax.plot(self.counts[:, 0], self.convolvedsignal)

        if self.showexppeaksBool:
            qq2 = np.arange(cts.first_harm, 35, 1)

            y = np.linspace(ymax - (ymax - ymin) * 0.2, ymax, 100)
            for i in range((len(qq2))):
                if qq2[i] % 2 == 0:
                    c = 'r'
                else:
                    c = 'k'
                try:
                    xval = float(
                        np.math.sqrt(0.5 * cts.ME * cts.cur_L**2 / cts.QE /
                                     (qq2[i] * cts.HEV * cts.cur_nu -
                                      cts.cur_Ip)) + 6e-8)
                    # NB: cts.QE is used to convert the energy from eV to Joules. It's not the electron's charge
                    x = np.full((100, 1), xval)
                except Exception:
                    print(traceback.format_exception(*sys.exc_info()))
                self.tof_ax.plot(x, y, color=c, linewidth=1.0)

        if self.bgndremoved:
            self.bgndremoved = False  #this means that when we remove bgnd, we don't keep the same scale
        else:
            self.tof_ax.set_ylim(ymin, ymax)

        self.tof_ax.set_xlim(xmin, xmax)
        self.tof_fc.draw()

    def onclick(self, event):
        ''' called when double-clicking on the TOF graph'''
        if self.dataloaded and self.addpeak_cb.isChecked(
        ):  #add a peak on clicking on the figure
            i = 0
            ifound = False
            while (i < len(self.maximaIndices) and ifound == False):
                if (self.maximaIndices[i] < event.xdata):
                    i += 1
                else:
                    ifound = True
            self.maximaIndices.insert(i, event.xdata)
            self.maximaIntensity.insert(i, event.ydata)
            self.refreshplot_fn()

        if self.dataloaded and self.setth_cb.isChecked():
            if self.Y_rb.isChecked():
                self.thy = event.ydata
                self.threshyline = np.full((len(self.counts), 2), self.thy)
                self.threshyline[:, 0] = self.counts[:, 0]
                self.threshyBool = True
            elif self.xmin_rb.isChecked():
                self.thxmin = event.xdata
                self.threshxminline = np.full((len(self.counts), 2),
                                              self.thxmin)
                self.threshxminline[:, 1] = self.counts[:, 1]
                self.threshxminBool = True
            elif self.xmax_rb.isChecked():
                self.thxmax = event.xdata
                self.threshxmaxline = np.full((len(self.counts), 2),
                                              self.thxmax)
                self.threshxmaxline[:, 1] = self.counts[:, 1]
                self.threshxmaxBool = True
            self.refreshplot_fn()

    def exportXUV_lr(self):
        ''' "Export XUV" button listener. Saving the energy vector and the energy-converted TOF signal'''
        filename = QFileDialog.getSaveFileName(self, 'Save XUV')
        fname = filename[0]
        if fname:
            XUV_array = np.vstack((self.Eevlin, self.signal)).T
            np.savetxt(fname, XUV_array, delimiter='\t')

    def clear_lr(self):
        ''' "Clear" button listener. Resets all the objects, but not the global variables'''
        self.tof_ax.cla()
        self.fit_ax.cla()
        self.en_ax.cla()

        self.dataloaded = False
        self.threshyBool = False
        self.threshxminBool = False
        self.threshxmaxBool = False
        self.calibloaded = False
        self.calibBool = False

        self.Y_rb.setEnabled(False)
        self.xmin_rb.setEnabled(False)
        self.xmax_rb.setEnabled(False)
        self.minus_sign_cb.setEnabled(False)

        for w in self.children():
            if isinstance(w, QPushButton) or isinstance(w, QCheckBox):
                w.setEnabled(False)
        self.load_btn.setEnabled(True)
        self.importcalib_btn.setEnabled(False)

        self.minus_sign_cb.setEnabled(False)

        self.tof_fc.draw()
        self.fit_fc.draw()
        self.en_fc.draw()

        cts.clear_varlist()
        self.window().updateglobvar_fn()
Пример #17
0
class SquidGui(QMainWindow):
    defaults = {}
    defaults.update(SquidAxon.defaults)
    defaults.update(ClampCircuit.defaults)
    defaults.update({
        'runtime': 50.0,
        'simdt': 0.01,
        'plotdt': 0.1,
        'vclamp.holdingV': 0.0,
        'vclamp.holdingT': 10.0,
        'vclamp.prepulseV': 0.0,
        'vclamp.prepulseT': 0.0,
        'vclamp.clampV': 50.0,
        'vclamp.clampT': 20.0,
        'iclamp.baseI': 0.0,
        'iclamp.firstI': 0.1,
        'iclamp.firstT': 40.0,
        'iclamp.firstD': 5.0,
        'iclamp.secondI': 0.0,
        'iclamp.secondT': 0.0,
        'iclamp.secondD': 0.0
    })

    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
        self.squid_setup = SquidSetup()
        self._plotdt = SquidGui.defaults['plotdt']
        self._plot_dict = defaultdict(list)
        self.setWindowTitle('Squid Axon simulation')
        self.setDockNestingEnabled(True)
        self._createRunControl()
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._runControlDock)
        self._runControlDock.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self._createChannelControl()
        self._channelCtrlBox.setWindowTitle('Channel properties')
        self._channelControlDock.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                           self._channelControlDock)
        self._createElectronicsControl()
        self._electronicsDock.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self._electronicsDock.setWindowTitle('Electronics')
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._electronicsDock)
        self._createPlotWidget()
        self.setCentralWidget(self._plotWidget)
        self._createStatePlotWidget()
        self._createHelpMessage()
        self._helpWindow.setVisible(False)
        self._statePlotWidget.setWindowFlags(QtCore.Qt.Window)
        self._statePlotWidget.setWindowTitle('State plot')
        self._initActions()
        self._createRunToolBar()
        self._createPlotToolBar()

    def getFloatInput(self, widget, name):
        try:
            return float(str(widget.text()))
        except ValueError:
            QMessageBox.critical(
                self, 'Invalid input',
                'Please enter a valid number for {}'.format(name))
            raise

    def _createPlotWidget(self):
        self._plotWidget = QWidget()
        self._plotFigure = Figure()
        self._plotCanvas = FigureCanvas(self._plotFigure)
        self._plotCanvas.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self._plotCanvas.updateGeometry()
        self._plotCanvas.setParent(self._plotWidget)
        self._plotCanvas.mpl_connect('scroll_event', self._onScroll)
        self._plotFigure.set_canvas(self._plotCanvas)
        # Vm and command voltage go in the same subplot
        self._vm_axes = self._plotFigure.add_subplot(
            2, 2, 1, title='Membrane potential')
        self._vm_axes.set_ylim(-20.0, 120.0)
        # Channel conductances go to the same subplot
        self._g_axes = self._plotFigure.add_subplot(
            2, 2, 2, title='Channel conductance')
        self._g_axes.set_ylim(0.0, 0.5)
        # Injection current for Vclamp/Iclamp go to the same subplot
        self._im_axes = self._plotFigure.add_subplot(2,
                                                     2,
                                                     3,
                                                     title='Injection current')
        self._im_axes.set_ylim(-0.5, 0.5)
        # Channel currents go to the same subplot
        self._i_axes = self._plotFigure.add_subplot(2,
                                                    2,
                                                    4,
                                                    title='Channel current')
        self._i_axes.set_ylim(-10, 10)
        for axis in self._plotFigure.axes:
            axis.set_autoscale_on(False)
        layout = QVBoxLayout()
        layout.addWidget(self._plotCanvas)
        self._plotNavigator = NavigationToolbar(self._plotCanvas,
                                                self._plotWidget)
        layout.addWidget(self._plotNavigator)
        self._plotWidget.setLayout(layout)

    def _createStatePlotWidget(self):
        self._statePlotWidget = QWidget()
        self._statePlotFigure = Figure()
        self._statePlotCanvas = FigureCanvas(self._statePlotFigure)
        self._statePlotCanvas.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self._statePlotCanvas.updateGeometry()
        self._statePlotCanvas.setParent(self._statePlotWidget)
        self._statePlotFigure.set_canvas(self._statePlotCanvas)
        self._statePlotFigure.subplots_adjust(hspace=0.5)
        self._statePlotAxes = self._statePlotFigure.add_subplot(
            2, 1, 1, title='State plot')
        self._state_plot, = self._statePlotAxes.plot([], [], label='state')
        self._activationParamAxes = self._statePlotFigure.add_subplot(
            2, 1, 2, title='H-H activation parameters vs time')
        self._activationParamAxes.set_xlabel('Time (ms)')
        #for axis in self._plotFigure.axes:
        #    axis.autoscale(False)
        self._stateplot_xvar_label = QLabel('Variable on X-axis')
        self._stateplot_xvar_combo = QComboBox()
        self._stateplot_xvar_combo.addItems(['V', 'm', 'n', 'h'])
        self._stateplot_xvar_combo.setCurrentText('V')
        self._stateplot_xvar_combo.setEditable(False)
        self._stateplot_xvar_combo.currentIndexChanged[str].connect(
            self._statePlotXSlot)
        self._stateplot_yvar_label = QLabel('Variable on Y-axis')
        self._stateplot_yvar_combo = QComboBox()
        self._stateplot_yvar_combo.addItems(['V', 'm', 'n', 'h'])
        self._stateplot_yvar_combo.setCurrentIndex(2)
        self._stateplot_yvar_combo.setEditable(False)
        self._stateplot_yvar_combo.currentIndexChanged[str].connect(
            self._statePlotYSlot)
        self._statePlotNavigator = NavigationToolbar(self._statePlotCanvas,
                                                     self._statePlotWidget)
        frame = QFrame()
        frame.setFrameStyle(QFrame.StyledPanel + QFrame.Raised)
        layout = QHBoxLayout()
        layout.addWidget(self._stateplot_xvar_label)
        layout.addWidget(self._stateplot_xvar_combo)
        layout.addWidget(self._stateplot_yvar_label)
        layout.addWidget(self._stateplot_yvar_combo)
        frame.setLayout(layout)
        self._closeStatePlotAction = QAction('Close', self)
        self._closeStatePlotAction.triggered.connect(
            self._statePlotWidget.close)
        self._closeStatePlotButton = QToolButton()
        self._closeStatePlotButton.setDefaultAction(self._closeStatePlotAction)
        layout = QVBoxLayout()
        layout.addWidget(frame)
        layout.addWidget(self._statePlotCanvas)
        layout.addWidget(self._statePlotNavigator)
        layout.addWidget(self._closeStatePlotButton)
        self._statePlotWidget.setLayout(layout)
        # Setting the close event so that when the help window is
        # closed the ``State plot`` button becomes unchecked
        self._statePlotWidget.closeEvent = lambda event: self._showStatePlotAction.setChecked(
            False)

    def _createRunControl(self):
        self._runControlBox = QGroupBox(self)
        self._runControlBox.setSizePolicy(QSizePolicy.Preferred,
                                          QSizePolicy.Preferred)
        self._runTimeLabel = QLabel("Run time (ms)", self._runControlBox)
        self._simTimeStepLabel = QLabel("Simulation time step (ms)",
                                        self._runControlBox)
        self._runTimeEdit = QLineEdit('%g' % (SquidGui.defaults['runtime']),
                                      self._runControlBox)
        set_default_line_edit_size(self._runTimeEdit)
        self._simTimeStepEdit = QLineEdit('%g' % (SquidGui.defaults['simdt']),
                                          self._runControlBox)
        set_default_line_edit_size(self._simTimeStepEdit)
        layout = QGridLayout()
        layout.addWidget(self._runTimeLabel, 0, 0)
        layout.addWidget(self._runTimeEdit, 0, 1)
        layout.addWidget(self._simTimeStepLabel, 1, 0)
        layout.addWidget(self._simTimeStepEdit, 1, 1)
        layout.setColumnStretch(2, 1.0)
        layout.setRowStretch(2, 1.0)
        self._runControlBox.setLayout(layout)
        self._runControlDock = QDockWidget('Simulation', self)
        self._runControlDock.setWidget(self._runControlBox)

    def _createChannelControl(self):
        self._channelControlDock = QDockWidget('Channels', self)
        self._channelCtrlBox = QGroupBox(self)
        self._naConductanceToggle = QCheckBox('Block Na+ channel',
                                              self._channelCtrlBox)
        self._naConductanceToggle.setToolTip('<html>%s</html>' %
                                             (tooltip_NaChan))
        self._kConductanceToggle = QCheckBox('Block K+ channel',
                                             self._channelCtrlBox)
        self._kConductanceToggle.setToolTip('<html>%s</html>' %
                                            (tooltip_KChan))
        self._kOutLabel = QLabel('[K+]out (mM)', self._channelCtrlBox)
        self._kOutEdit = QLineEdit('%g' % (self.squid_setup.axon.K_out),
                                   self._channelCtrlBox)
        self._kOutLabel.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        self._kOutEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        set_default_line_edit_size(self._kOutEdit)
        self._naOutLabel = QLabel('[Na+]out (mM)', self._channelCtrlBox)
        self._naOutEdit = QLineEdit('%g' % (self.squid_setup.axon.Na_out),
                                    self._channelCtrlBox)
        self._naOutLabel.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        self._naOutEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        set_default_line_edit_size(self._naOutEdit)
        self._kInLabel = QLabel('[K+]in (mM)', self._channelCtrlBox)
        self._kInEdit = QLineEdit('%g' % (self.squid_setup.axon.K_in),
                                  self._channelCtrlBox)
        self._kInEdit.setToolTip(tooltip_Nernst)
        self._naInLabel = QLabel('[Na+]in (mM)', self._channelCtrlBox)
        self._naInEdit = QLineEdit('%g' % (self.squid_setup.axon.Na_in),
                                   self._channelCtrlBox)
        self._naInEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        self._temperatureLabel = QLabel('Temperature (C)',
                                        self._channelCtrlBox)
        self._temperatureEdit = QLineEdit(
            '%g' % (self.defaults['temperature'] - CELSIUS_TO_KELVIN),
            self._channelCtrlBox)
        self._temperatureEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst))
        set_default_line_edit_size(self._temperatureEdit)
        for child in self._channelCtrlBox.children():
            if isinstance(child, QLineEdit):
                set_default_line_edit_size(child)
        layout = QGridLayout(self._channelCtrlBox)
        layout.addWidget(self._naConductanceToggle, 0, 0)
        layout.addWidget(self._kConductanceToggle, 1, 0)
        layout.addWidget(self._naOutLabel, 2, 0)
        layout.addWidget(self._naOutEdit, 2, 1)
        layout.addWidget(self._naInLabel, 3, 0)
        layout.addWidget(self._naInEdit, 3, 1)
        layout.addWidget(self._kOutLabel, 4, 0)
        layout.addWidget(self._kOutEdit, 4, 1)
        layout.addWidget(self._kInLabel, 5, 0)
        layout.addWidget(self._kInEdit, 5, 1)
        layout.addWidget(self._temperatureLabel, 6, 0)
        layout.addWidget(self._temperatureEdit, 6, 1)
        layout.setRowStretch(7, 1.0)
        self._channelCtrlBox.setLayout(layout)
        self._channelControlDock.setWidget(self._channelCtrlBox)
        return self._channelCtrlBox

    def __get_stateplot_data(self, name):
        data = []
        if name == 'V':
            data = self.squid_setup.vm_table.vector
        elif name == 'm':
            data = self.squid_setup.m_table.vector
        elif name == 'h':
            data = self.squid_setup.h_table.vector
        elif name == 'n':
            data = self.squid_setup.n_table.vector
        else:
            raise ValueError('Unrecognized selection: %s' % name)
        return numpy.asarray(data)

    def _statePlotYSlot(self, selectedItem):
        ydata = self.__get_stateplot_data(str(selectedItem))
        self._state_plot.set_ydata(ydata)
        self._statePlotAxes.set_ylabel(selectedItem)
        if str(selectedItem) == 'V':
            self._statePlotAxes.set_ylim(-20, 120)
        else:
            self._statePlotAxes.set_ylim(0, 1)
        self._statePlotCanvas.draw()

    def _statePlotXSlot(self, selectedItem):
        xdata = self.__get_stateplot_data(str(selectedItem))
        self._state_plot.set_xdata(xdata)
        self._statePlotAxes.set_xlabel(selectedItem)
        if str(selectedItem) == 'V':
            self._statePlotAxes.set_xlim(-20, 120)
        else:
            self._statePlotAxes.set_xlim(0, 1)
        self._statePlotCanvas.draw()

    def _createElectronicsControl(self):
        """Creates a tabbed widget of voltage clamp and current clamp controls"""
        self._electronicsTab = QTabWidget(self)
        self._electronicsTab.addTab(self._getIClampCtrlBox(), 'Current clamp')
        self._electronicsTab.addTab(self._getVClampCtrlBox(), 'Voltage clamp')
        self._electronicsDock = QDockWidget(self)
        self._electronicsDock.setWidget(self._electronicsTab)

    def _getVClampCtrlBox(self):
        vClampPanel = QGroupBox(self)
        self._vClampCtrlBox = vClampPanel
        self._holdingVLabel = QLabel("Holding Voltage (mV)", vClampPanel)
        self._holdingVEdit = QLineEdit(
            '%g' % (SquidGui.defaults['vclamp.holdingV']), vClampPanel)
        self._holdingTimeLabel = QLabel("Holding Time (ms)", vClampPanel)
        self._holdingTimeEdit = QLineEdit(
            '%g' % (SquidGui.defaults['vclamp.holdingT']), vClampPanel)
        self._prePulseVLabel = QLabel("Pre-pulse Voltage (mV)", vClampPanel)
        self._prePulseVEdit = QLineEdit(
            '%g' % (SquidGui.defaults['vclamp.prepulseV']), vClampPanel)
        self._prePulseTimeLabel = QLabel("Pre-pulse Time (ms)", vClampPanel)
        self._prePulseTimeEdit = QLineEdit(
            '%g' % (SquidGui.defaults['vclamp.prepulseT']), vClampPanel)
        self._clampVLabel = QLabel("Clamp Voltage (mV)", vClampPanel)
        self._clampVEdit = QLineEdit(
            '%g' % (SquidGui.defaults['vclamp.clampV']), vClampPanel)
        self._clampTimeLabel = QLabel("Clamp Time (ms)", vClampPanel)
        self._clampTimeEdit = QLineEdit(
            '%g' % (SquidGui.defaults['vclamp.clampT']), vClampPanel)
        for child in vClampPanel.children():
            if isinstance(child, QLineEdit):
                set_default_line_edit_size(child)
        layout = QGridLayout(vClampPanel)
        layout.addWidget(self._holdingVLabel, 0, 0)
        layout.addWidget(self._holdingVEdit, 0, 1)
        layout.addWidget(self._holdingTimeLabel, 1, 0)
        layout.addWidget(self._holdingTimeEdit, 1, 1)
        layout.addWidget(self._prePulseVLabel, 2, 0)
        layout.addWidget(self._prePulseVEdit, 2, 1)
        layout.addWidget(self._prePulseTimeLabel, 3, 0)
        layout.addWidget(self._prePulseTimeEdit, 3, 1)
        layout.addWidget(self._clampVLabel, 4, 0)
        layout.addWidget(self._clampVEdit, 4, 1)
        layout.addWidget(self._clampTimeLabel, 5, 0)
        layout.addWidget(self._clampTimeEdit, 5, 1)
        layout.setRowStretch(6, 1.0)
        vClampPanel.setLayout(layout)
        return self._vClampCtrlBox

    def _getIClampCtrlBox(self):
        iClampPanel = QGroupBox(self)
        self._iClampCtrlBox = iClampPanel
        self._baseCurrentLabel = QLabel("Base Current Level (uA)", iClampPanel)
        self._baseCurrentEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.baseI']), iClampPanel)
        self._firstPulseLabel = QLabel("First Pulse Current (uA)", iClampPanel)
        self._firstPulseEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.firstI']), iClampPanel)
        self._firstDelayLabel = QLabel("First Onset Delay (ms)", iClampPanel)
        self._firstDelayEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.firstD']), iClampPanel)
        self._firstPulseWidthLabel = QLabel("First Pulse Width (ms)",
                                            iClampPanel)
        self._firstPulseWidthEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.firstT']), iClampPanel)
        self._secondPulseLabel = QLabel("Second Pulse Current (uA)",
                                        iClampPanel)
        self._secondPulseEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.secondI']), iClampPanel)
        self._secondDelayLabel = QLabel("Second Onset Delay (ms)", iClampPanel)
        self._secondDelayEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.secondD']), iClampPanel)
        self._secondPulseWidthLabel = QLabel("Second Pulse Width (ms)",
                                             iClampPanel)
        self._secondPulseWidthEdit = QLineEdit(
            '%g' % (SquidGui.defaults['iclamp.secondT']), iClampPanel)
        self._pulseMode = QComboBox(iClampPanel)
        self._pulseMode.addItem("Single Pulse")
        self._pulseMode.addItem("Pulse Train")
        for child in iClampPanel.children():
            if isinstance(child, QLineEdit):
                set_default_line_edit_size(child)
        layout = QGridLayout(iClampPanel)
        layout.addWidget(self._baseCurrentLabel, 0, 0)
        layout.addWidget(self._baseCurrentEdit, 0, 1)
        layout.addWidget(self._firstPulseLabel, 1, 0)
        layout.addWidget(self._firstPulseEdit, 1, 1)
        layout.addWidget(self._firstDelayLabel, 2, 0)
        layout.addWidget(self._firstDelayEdit, 2, 1)
        layout.addWidget(self._firstPulseWidthLabel, 3, 0)
        layout.addWidget(self._firstPulseWidthEdit, 3, 1)
        layout.addWidget(self._secondPulseLabel, 4, 0)
        layout.addWidget(self._secondPulseEdit, 4, 1)
        layout.addWidget(self._secondDelayLabel, 5, 0)
        layout.addWidget(self._secondDelayEdit, 5, 1)
        layout.addWidget(self._secondPulseWidthLabel, 6, 0)
        layout.addWidget(self._secondPulseWidthEdit, 6, 1)
        layout.addWidget(self._pulseMode, 7, 0, 1, 2)
        layout.setRowStretch(8, 1.0)
        # layout.setSizeConstraint(QLayout.SetFixedSize)
        iClampPanel.setLayout(layout)
        return self._iClampCtrlBox

    def _overlayPlots(self, overlay):
        if not overlay:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):
                title = axis.get_title()
                axis.clear()
                axis.set_title(title)
            suffix = ''
        else:
            suffix = '_%d' % (len(self._plot_dict['vm']))
        self._vm_axes.set_xlim(0.0, self._runtime)
        self._g_axes.set_xlim(0.0, self._runtime)
        self._im_axes.set_xlim(0.0, self._runtime)
        self._i_axes.set_xlim(0.0, self._runtime)
        self._vm_plot, = self._vm_axes.plot([], [], label='Vm%s' % (suffix))
        self._plot_dict['vm'].append(self._vm_plot)
        self._command_plot, = self._vm_axes.plot([], [],
                                                 label='command%s' % (suffix))
        self._plot_dict['command'].append(self._command_plot)
        # Channel conductances go to the same subplot
        self._gna_plot, = self._g_axes.plot([], [], label='Na%s' % (suffix))
        self._plot_dict['gna'].append(self._gna_plot)
        self._gk_plot, = self._g_axes.plot([], [], label='K%s' % (suffix))
        self._plot_dict['gk'].append(self._gk_plot)
        # Injection current for Vclamp/Iclamp go to the same subplot
        self._iclamp_plot, = self._im_axes.plot([], [],
                                                label='Iclamp%s' % (suffix))
        self._vclamp_plot, = self._im_axes.plot([], [],
                                                label='Vclamp%s' % (suffix))
        self._plot_dict['iclamp'].append(self._iclamp_plot)
        self._plot_dict['vclamp'].append(self._vclamp_plot)
        # Channel currents go to the same subplot
        self._ina_plot, = self._i_axes.plot([], [], label='Na%s' % (suffix))
        self._plot_dict['ina'].append(self._ina_plot)
        self._ik_plot, = self._i_axes.plot([], [], label='K%s' % (suffix))
        self._plot_dict['ik'].append(self._ik_plot)
        # self._i_axes.legend()
        # State plots
        self._state_plot, = self._statePlotAxes.plot([], [],
                                                     label='state%s' %
                                                     (suffix))
        self._plot_dict['state'].append(self._state_plot)
        self._m_plot, = self._activationParamAxes.plot([], [],
                                                       label='m%s' % (suffix))
        self._h_plot, = self._activationParamAxes.plot([], [],
                                                       label='h%s' % (suffix))
        self._n_plot, = self._activationParamAxes.plot([], [],
                                                       label='n%s' % (suffix))
        self._plot_dict['m'].append(self._m_plot)
        self._plot_dict['h'].append(self._h_plot)
        self._plot_dict['n'].append(self._n_plot)
        if self._showLegendAction.isChecked():
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):
                axis.legend()

    def _updateAllPlots(self):
        self._updatePlots()
        self._updateStatePlot()

    def _updatePlots(self):
        if len(self.squid_setup.vm_table.vector) <= 0:
            return
        vm = numpy.asarray(self.squid_setup.vm_table.vector)
        cmd = numpy.asarray(self.squid_setup.cmd_table.vector)
        ik = numpy.asarray(self.squid_setup.ik_table.vector)

        #  tab = self.squid_setup.ina_table
        #  print(moose.showmsg(tab))

        ina = numpy.asarray(self.squid_setup.ina_table.vector)

        iclamp = numpy.asarray(self.squid_setup.iclamp_table.vector)
        vclamp = numpy.asarray(self.squid_setup.vclamp_table.vector)
        gk = numpy.asarray(self.squid_setup.gk_table.vector)
        gna = numpy.asarray(self.squid_setup.gna_table.vector)
        time_series = numpy.linspace(0, self._plotdt * len(vm), len(vm))
        self._vm_plot.set_data(time_series, vm)
        time_series = numpy.linspace(0, self._plotdt * len(cmd), len(cmd))
        self._command_plot.set_data(time_series, cmd)
        time_series = numpy.linspace(0, self._plotdt * len(ik), len(ik))
        self._ik_plot.set_data(time_series, ik)
        time_series = numpy.linspace(0, self._plotdt * len(ina), len(ina))
        self._ina_plot.set_data(time_series, ina)
        time_series = numpy.linspace(0, self._plotdt * len(iclamp),
                                     len(iclamp))
        self._iclamp_plot.set_data(time_series, iclamp)
        time_series = numpy.linspace(0, self._plotdt * len(vclamp),
                                     len(vclamp))
        self._vclamp_plot.set_data(time_series, vclamp)
        time_series = numpy.linspace(0, self._plotdt * len(gk), len(gk))
        self._gk_plot.set_data(time_series, gk)
        time_series = numpy.linspace(0, self._plotdt * len(gna), len(gna))
        self._gna_plot.set_data(time_series, gna)
        # self._vm_axes.margins(y=0.1)
        # self._g_axes.margin(y=0.1)
        # self._im_axes.margins(y=0.1)
        # self._i_axes.margins(y=0.1)
        if self._autoscaleAction.isChecked():
            for axis in self._plotFigure.axes:
                axis.relim()
                axis.margins(0.1, 0.1)
                axis.autoscale_view(tight=True)
        else:
            self._vm_axes.set_ylim(-20.0, 120.0)
            self._g_axes.set_ylim(0.0, 0.5)
            self._im_axes.set_ylim(-0.5, 0.5)
            self._i_axes.set_ylim(-10, 10)
        self._vm_axes.set_xlim(0.0, time_series[-1])
        self._g_axes.set_xlim(0.0, time_series[-1])
        self._im_axes.set_xlim(0.0, time_series[-1])
        self._i_axes.set_xlim(0.0, time_series[-1])
        self._plotCanvas.draw()

    def _updateStatePlot(self):
        if len(self.squid_setup.vm_table.vector) <= 0:
            return
        sx = str(self._stateplot_xvar_combo.currentText())
        sy = str(self._stateplot_yvar_combo.currentText())
        xdata = self.__get_stateplot_data(sx)
        ydata = self.__get_stateplot_data(sy)
        minlen = min(len(xdata), len(ydata))
        self._state_plot.set_data(xdata[:minlen], ydata[:minlen])
        self._statePlotAxes.set_xlabel(sx)
        self._statePlotAxes.set_ylabel(sy)
        if sx == 'V':
            self._statePlotAxes.set_xlim(-20, 120)
        else:
            self._statePlotAxes.set_xlim(0, 1)
        if sy == 'V':
            self._statePlotAxes.set_ylim(-20, 120)
        else:
            self._statePlotAxes.set_ylim(0, 1)
        self._activationParamAxes.set_xlim(0, self._runtime)
        m = self.__get_stateplot_data('m')
        n = self.__get_stateplot_data('n')
        h = self.__get_stateplot_data('h')
        time_series = numpy.linspace(0, self._plotdt * len(m), len(m))
        self._m_plot.set_data(time_series, m)
        time_series = numpy.linspace(0, self._plotdt * len(h), len(h))
        self._h_plot.set_data(time_series, h)
        time_series = numpy.linspace(0, self._plotdt * len(n), len(n))
        self._n_plot.set_data(time_series, n)
        if self._autoscaleAction.isChecked():
            for axis in self._statePlotFigure.axes:
                axis.relim()
                axis.set_autoscale_on(True)
                axis.autoscale_view(True)
        self._statePlotCanvas.draw()

    def _runSlot(self):
        if moose.isRunning():
            print('Stopping simulation in progress ...')
            moose.stop()
        self._runtime = self.getFloatInput(self._runTimeEdit,
                                           self._runTimeLabel.text())
        self._overlayPlots(self._overlayAction.isChecked())
        self._simdt = self.getFloatInput(self._simTimeStepEdit,
                                         self._simTimeStepLabel.text())
        clampMode = None
        singlePulse = True
        if self._electronicsTab.currentWidget() == self._vClampCtrlBox:
            clampMode = 'vclamp'
            baseLevel = self.getFloatInput(self._holdingVEdit,
                                           self._holdingVLabel.text())
            firstDelay = self.getFloatInput(self._holdingTimeEdit,
                                            self._holdingTimeLabel.text())
            firstWidth = self.getFloatInput(self._prePulseTimeEdit,
                                            self._prePulseTimeLabel.text())
            firstLevel = self.getFloatInput(self._prePulseVEdit,
                                            self._prePulseVLabel.text())
            secondDelay = firstWidth
            secondWidth = self.getFloatInput(self._clampTimeEdit,
                                             self._clampTimeLabel.text())
            secondLevel = self.getFloatInput(self._clampVEdit,
                                             self._clampVLabel.text())
            if not self._autoscaleAction.isChecked():
                self._im_axes.set_ylim(-10.0, 10.0)
        else:
            clampMode = 'iclamp'
            baseLevel = self.getFloatInput(self._baseCurrentEdit,
                                           self._baseCurrentLabel.text())
            firstDelay = self.getFloatInput(self._firstDelayEdit,
                                            self._firstDelayLabel.text())
            firstWidth = self.getFloatInput(self._firstPulseWidthEdit,
                                            self._firstPulseWidthLabel.text())
            firstLevel = self.getFloatInput(self._firstPulseEdit,
                                            self._firstPulseLabel.text())
            secondDelay = self.getFloatInput(self._secondDelayEdit,
                                             self._secondDelayLabel.text())
            secondLevel = self.getFloatInput(self._secondPulseEdit,
                                             self._secondPulseLabel.text())
            secondWidth = self.getFloatInput(
                self._secondPulseWidthEdit, self._secondPulseWidthLabel.text())
            singlePulse = (self._pulseMode.currentIndex() == 0)
            if not self._autoscaleAction.isChecked():
                self._im_axes.set_ylim(-0.4, 0.4)
        self.squid_setup.clamp_ckt.configure_pulses(baseLevel=baseLevel,
                                                    firstDelay=firstDelay,
                                                    firstWidth=firstWidth,
                                                    firstLevel=firstLevel,
                                                    secondDelay=secondDelay,
                                                    secondWidth=secondWidth,
                                                    secondLevel=secondLevel,
                                                    singlePulse=singlePulse)
        if self._kConductanceToggle.isChecked():
            self.squid_setup.axon.specific_gK = 0.0
        else:
            self.squid_setup.axon.specific_gK = SquidAxon.defaults[
                'specific_gK']
        if self._naConductanceToggle.isChecked():
            self.squid_setup.axon.specific_gNa = 0.0
        else:
            self.squid_setup.axon.specific_gNa = SquidAxon.defaults[
                'specific_gNa']
        self.squid_setup.axon.celsius = self.getFloatInput(
            self._temperatureEdit, self._temperatureLabel.text())
        self.squid_setup.axon.K_out = self.getFloatInput(
            self._kOutEdit, self._kOutLabel.text())
        self.squid_setup.axon.Na_out = self.getFloatInput(
            self._naOutEdit, self._naOutLabel.text())
        self.squid_setup.axon.K_in = self.getFloatInput(
            self._kInEdit, self._kInLabel.text())
        self.squid_setup.axon.Na_in = self.getFloatInput(
            self._naInEdit, self._naInLabel.text())
        self.squid_setup.axon.updateEk()
        self.squid_setup.schedule(self._simdt, self._plotdt, clampMode)
        # The following line is for use with Qthread
        self.squid_setup.run(self._runtime)
        self._updateAllPlots()

    def _toggleDocking(self, on):
        self._channelControlDock.setFloating(on)
        self._electronicsDock.setFloating(on)
        self._runControlDock.setFloating(on)

    def _restoreDocks(self):
        self._channelControlDock.setVisible(True)
        self._electronicsDock.setVisible(True)
        self._runControlDock.setVisible(True)

    def _initActions(self):
        self._runAction = QAction(self.tr('Run'), self)
        self._runAction.setShortcut(self.tr('F5'))
        self._runAction.setToolTip('Run simulation (F5)')
        self._runAction.triggered.connect(self._runSlot)
        self._resetToDefaultsAction = QAction(self.tr('Restore defaults'),
                                              self)
        self._resetToDefaultsAction.setToolTip(
            'Reset all settings to their default values')
        self._resetToDefaultsAction.triggered.connect(self._useDefaults)
        self._showLegendAction = QAction(self.tr('Display legend'), self)
        self._showLegendAction.setCheckable(True)
        self._showLegendAction.toggled.connect(self._showLegend)
        self._showStatePlotAction = QAction(self.tr('State plot'), self)
        self._showStatePlotAction.setCheckable(True)
        self._showStatePlotAction.setChecked(False)
        self._showStatePlotAction.toggled.connect(
            self._statePlotWidget.setVisible)
        self._autoscaleAction = QAction(self.tr('Auto-scale plots'), self)
        self._autoscaleAction.setCheckable(True)
        self._autoscaleAction.setChecked(False)
        self._autoscaleAction.toggled.connect(self._autoscale)
        self._overlayAction = QAction('Overlay plots', self)
        self._overlayAction.setCheckable(True)
        self._overlayAction.setChecked(False)
        self._dockAction = QAction('Undock all', self)
        self._dockAction.setCheckable(True)
        self._dockAction.setChecked(False)
        #  self._dockAction.toggle.connect( self._toggleDocking)
        self._restoreDocksAction = QAction('Show all', self)
        self._restoreDocksAction.triggered.connect(self._restoreDocks)
        self._quitAction = QAction(self.tr('&Quit'), self)
        self._quitAction.setShortcut(self.tr('Ctrl+Q'))
        self._quitAction.triggered.connect(qApp.closeAllWindows)

    def _createRunToolBar(self):
        self._simToolBar = self.addToolBar(self.tr('Simulation control'))
        self._simToolBar.addAction(self._quitAction)
        self._simToolBar.addAction(self._runAction)
        self._simToolBar.addAction(self._resetToDefaultsAction)
        self._simToolBar.addAction(self._dockAction)
        self._simToolBar.addAction(self._restoreDocksAction)

    def _createPlotToolBar(self):
        self._plotToolBar = self.addToolBar(self.tr('Plotting control'))
        self._plotToolBar.addAction(self._showLegendAction)
        self._plotToolBar.addAction(self._autoscaleAction)
        self._plotToolBar.addAction(self._overlayAction)
        self._plotToolBar.addAction(self._showStatePlotAction)
        self._plotToolBar.addAction(self._helpAction)
        self._plotToolBar.addAction(self._helpBiophysicsAction)

    def _showLegend(self, on):
        if on:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):
                axis.legend().set_visible(True)
        else:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):
                axis.legend().set_visible(False)
        self._plotCanvas.draw()
        self._statePlotCanvas.draw()

    def _autoscale(self, on):
        if on:
            for axis in (self._plotFigure.axes + self._statePlotFigure.axes):
                axis.relim()
                axis.set_autoscale_on(True)
                axis.autoscale_view(True)
        else:
            for axis in self._plotFigure.axes:
                axis.set_autoscale_on(False)
            self._vm_axes.set_ylim(-20.0, 120.0)
            self._g_axes.set_ylim(0.0, 0.5)
            self._im_axes.set_ylim(-0.5, 0.5)
            self._i_axes.set_ylim(-10, 10)
        self._plotCanvas.draw()
        self._statePlotCanvas.draw()

    def _useDefaults(self):
        self._runTimeEdit.setText('%g' % (self.defaults['runtime']))
        self._simTimeStepEdit.setText('%g' % (self.defaults['simdt']))
        self._overlayAction.setChecked(False)
        self._naConductanceToggle.setChecked(False)
        self._kConductanceToggle.setChecked(False)
        self._kOutEdit.setText('%g' % (SquidGui.defaults['K_out']))
        self._naOutEdit.setText('%g' % (SquidGui.defaults['Na_out']))
        self._kInEdit.setText('%g' % (SquidGui.defaults['K_in']))
        self._naInEdit.setText('%g' % (SquidGui.defaults['Na_in']))
        self._temperatureEdit.setText(
            '%g' % (SquidGui.defaults['temperature'] - CELSIUS_TO_KELVIN))
        self._holdingVEdit.setText('%g' %
                                   (SquidGui.defaults['vclamp.holdingV']))
        self._holdingTimeEdit.setText('%g' %
                                      (SquidGui.defaults['vclamp.holdingT']))
        self._prePulseVEdit.setText('%g' %
                                    (SquidGui.defaults['vclamp.prepulseV']))
        self._prePulseTimeEdit.setText('%g' %
                                       (SquidGui.defaults['vclamp.prepulseT']))
        self._clampVEdit.setText('%g' % (SquidGui.defaults['vclamp.clampV']))
        self._clampTimeEdit.setText('%g' %
                                    (SquidGui.defaults['vclamp.clampT']))
        self._baseCurrentEdit.setText('%g' %
                                      (SquidGui.defaults['iclamp.baseI']))
        self._firstPulseEdit.setText('%g' %
                                     (SquidGui.defaults['iclamp.firstI']))
        self._firstDelayEdit.setText('%g' %
                                     (SquidGui.defaults['iclamp.firstD']))
        self._firstPulseWidthEdit.setText('%g' %
                                          (SquidGui.defaults['iclamp.firstT']))
        self._secondPulseEdit.setText('%g' %
                                      (SquidGui.defaults['iclamp.secondI']))
        self._secondDelayEdit.setText('%g' %
                                      (SquidGui.defaults['iclamp.secondD']))
        self._secondPulseWidthEdit.setText(
            '%g' % (SquidGui.defaults['iclamp.secondT']))
        self._pulseMode.setCurrentIndex(0)

    def _onScroll(self, event):
        if event.inaxes is None:
            return
        axes = event.inaxes
        zoom = 0.0
        if event.button == 'up':
            zoom = -1.0
        elif event.button == 'down':
            zoom = 1.0
        if zoom != 0.0:
            self._plotNavigator.push_current()
            axes.get_xaxis().zoom(zoom)
            axes.get_yaxis().zoom(zoom)
        self._plotCanvas.draw()

    def closeEvent(self, event):
        qApp.closeAllWindows()

    def _showBioPhysicsHelp(self):
        self._createHelpMessage()
        self._helpMessageText.setText(
            '<html><p>%s</p><p>%s</p><p>%s</p><p>%s</p><p>%s</p></html>' %
            (tooltip_Nernst, tooltip_Erest, tooltip_KChan, tooltip_NaChan,
             tooltip_Im))
        self._helpWindow.setVisible(True)

    def _showRunningHelp(self):
        self._createHelpMessage()
        self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
        self._helpWindow.setVisible(True)

    def _createHelpMessage(self):
        if hasattr(self, '_helpWindow'):
            return
        self._helpWindow = QWidget()
        self._helpWindow.setWindowFlags(QtCore.Qt.Window)
        layout = QVBoxLayout()
        self._helpWindow.setLayout(layout)
        self._helpMessageArea = QScrollArea()
        self._helpMessageText = QTextBrowser()
        self._helpMessageText.setOpenExternalLinks(True)
        self._helpMessageArea.setWidget(self._helpMessageText)
        layout.addWidget(self._helpMessageText)
        self._squidGuiPath = os.path.dirname(os.path.abspath(__file__))
        self._helpBaseURL = os.path.join(self._squidGuiPath, 'help.html')
        self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
        self._helpMessageText.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self._helpMessageArea.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self._helpMessageText.setMinimumSize(800, 600)
        self._closeHelpAction = QAction('Close', self)
        self._closeHelpAction.triggered.connect(self._helpWindow.close)
        # Setting the close event so that the ``Help`` button is
        # unchecked when the help window is closed
        self._helpWindow.closeEvent = lambda event: self._helpAction.setChecked(
            False)
        self._helpTOCAction = QAction('Help running demo', self)
        self._helpTOCAction.triggered.connect(self._jumpToHelpTOC)
        # This panel is for putting two buttons using horizontal
        # layout
        panel = QFrame()
        panel.setFrameStyle(QFrame.StyledPanel + QFrame.Raised)
        layout.addWidget(panel)
        layout = QHBoxLayout()
        panel.setLayout(layout)
        self._helpAction = QAction('Help running', self)
        self._helpAction.triggered.connect(self._showRunningHelp)
        self._helpBiophysicsAction = QAction('Help biophysics', self)
        self._helpBiophysicsAction.triggered.connect(self._showBioPhysicsHelp)
        self._helpTOCButton = QToolButton()
        self._helpTOCButton.setDefaultAction(self._helpTOCAction)
        self._helpBiophysicsButton = QToolButton()
        self._helpBiophysicsButton.setDefaultAction(self._helpBiophysicsAction)
        layout.addWidget(self._helpTOCButton)
        layout.addWidget(self._helpBiophysicsButton)
        self._closeHelpButton = QToolButton()
        self._closeHelpButton.setDefaultAction(self._closeHelpAction)
        layout.addWidget(self._closeHelpButton)

    def _jumpToHelpTOC(self):
        self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
Пример #18
0
def GetTextFromGroup(group: QtWidgets.QGroupBox) -> QtWidgets.QPlainTextEdit:
    for child in group.children():
        if hasattr(child, "toPlainText"):
            return child
Пример #19
0
class App(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'Personality Grapher'
        self.left = 100
        self.right = 100
        self.top = 10
        self.width = 500
        self.height = 500
        self.init_ui()

    def init_ui(self):
        # set window title, size and position
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.right, self.width, self.height)

        # create the main layout
        self.main_layout = QVBoxLayout()
        self.error_message = QErrorMessage()

        # add a form with spin boxes
        self.create_formbox()
        self.main_layout.addWidget(self.form_groupbox)

        # add an options box for the graph
        self.create_optionsbox()
        self.main_layout.addWidget(self.options_groupbox)

        # add render button
        render_button = QPushButton('Render Graph', self)
        render_button.setToolTip('Render the personality graph and display it')
        render_button.clicked.connect(self.render_click)
        self.main_layout.addWidget(render_button)

        # finally, display the window
        self.setLayout(self.main_layout)
        self.show()

    def create_formbox(self):
        self.form_groupbox = QGroupBox('Personality Traits')
        self.form_layout = QFormLayout()

        addrow_button = QPushButton('Add Trait', self)
        addrow_button.setToolTip('Add a new section to the graph')
        addrow_button.clicked.connect(self.addrow_click)

        self.form_layout.addRow(QLabel('Trait'), QLabel('Value'))
        self.form_layout.addRow(QLineEdit(),
                                QDoubleSpinBox(decimals=5, maximum=10))
        self.form_layout.addRow(addrow_button)

        self.form_groupbox.setLayout(self.form_layout)

    def create_optionsbox(self):
        self.options_groupbox = QGroupBox('Graph Options')
        self.options_layout = QFormLayout()

        self.ceiling_text = QDoubleSpinBox(decimals=5, value=10.00)
        self.ceiling_text.valueChanged.connect(self.ceiling_changed)

        self.options_layout.addRow(QLabel('Graph Name'), QLineEdit())
        self.options_layout.addRow(QLabel('Max Value'), self.ceiling_text)
        self.options_layout.addRow(QLabel('Height/Width'),
                                   QSpinBox(value=6, minimum=1))
        self.options_layout.addRow(QLabel('Padding'), QSpinBox(value=4))
        self.options_layout.addRow(QLabel('Font Size'),
                                   QSpinBox(value=12, minimum=1))

        self.options_groupbox.setLayout(self.options_layout)

    # calls the render_graph function to render and then display the graph
    @pyqtSlot()
    def render_click(self):
        input_values = []
        input_names = []
        name = self.options_groupbox.children()[2].text().strip()
        padding = self.options_groupbox.children()[8].value()
        size = self.options_groupbox.children()[6].value()
        font = self.options_groupbox.children()[10].value()
        max = self.options_groupbox.children()[4].value()

        if len(self.form_groupbox.children()) == 3:
            # if the user has not added any sections, warn them
            self.error_message.showMessage('Cannot graph with no sections!')
        elif size < 1:
            self.error_message.showMessage(
                'Height/Width must be greater than 0!')
        else:
            # get values from input boxes and pass them into graphing function
            children = self.form_groupbox.findChildren(QLineEdit)
            count = 0
            while count < len(children):
                input_names.append(children[count].text())
                count += 1
                input_values.append(float(children[count].text()))
                count += 1

            result = polar_bar.render_graph(name=name,
                                            section_names=input_names,
                                            value_list=input_values,
                                            padding=padding,
                                            max=max,
                                            size=size,
                                            font=font)
            if result is False:
                self.error_message.showMessage(
                    'Padding too big for Height/Width!')

    @pyqtSlot()
    def addrow_click(self):
        self.form_layout.insertRow(
            self.form_layout.rowCount() - 1, QLineEdit(),
            QDoubleSpinBox(decimals=5,
                           maximum=float(self.ceiling_text.value())))

    @pyqtSlot()
    def ceiling_changed(self):
        for i in self.form_groupbox.findChildren(QDoubleSpinBox):
            i.setMaximum(float(self.ceiling_text.value()))
Пример #20
0
class SongList(QWidget):
    def __init__(self, parent=None):
        super(SongList, self).__init__(parent)

        os.chdir(os.path.dirname(os.path.abspath(__file__)))
        resourcesPath = os.getcwd()
        resourcesPath = os.path.join(resourcesPath, "resources")

        self.PLAY_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "play.png")))
        self.PAUSE_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "pause.png")))
        self.STOP_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "stop.png")))
        self.DELETE_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "delete.png")))

        self.setupMediaPlayer()
        self.setupUi()

    def setupMediaPlayer(self):
        self.mediaPlayer = QMediaPlayer()

        self.mediaPlayer.setNotifyInterval(1)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)

    def setupUi(self):
        self.setWindowTitle("List of songs")
        mainLayout = QHBoxLayout(self)

        verticalListLayout = QVBoxLayout()
        self.songsListWidget = QListWidget()
        self.songsListWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.songsListWidget.customContextMenuRequested.connect(self.listWidgetRightClick)
        verticalListLayout.addWidget(self.songsListWidget)

        miniHorizontalLayout = QHBoxLayout()
        locatorLine = QLineEdit()
        locatorLine.setPlaceholderText("Locator")
        locatorBox = QComboBox()
        items = ["Title", "Status", "Description", "Style", "All"]
        locatorBox.addItems(items)
        locatorBox.setCurrentIndex(len(items)-1)

        miniHorizontalLayout.addWidget(locatorLine)
        miniHorizontalLayout.addWidget(locatorBox)

        locatorLine.textChanged.connect(lambda:self.populateList(locatorLine.text(), locatorBox.currentText()))

        verticalListLayout.addLayout(miniHorizontalLayout)

        self.mainForm = QGroupBox()
        self.mainForm.setTitle("Details")

        mainLayout.addLayout(verticalListLayout)
        mainLayout.addWidget(self.mainForm)

        self.populateList()
        self.mainFormSetupUi()
        #self.show()

        self.songsListWidget.currentRowChanged.connect(self.changePage)
    
    def mainFormSetupUi(self):

        """title, status style, duration, descriptin, location, project,
        variation_another_song, timestamp"""

        mainLayout = QVBoxLayout(self.mainForm)

        #Horizontal Layout 1
        horizontalLayout1 = QHBoxLayout()

        titleLabel = QLabel("Song name:")
        self.titleEdit = QLineEdit()

        self.titleEdit.editingFinished.connect(self.checkSong)
        self.titleEdit.textChanged.connect(self.validateSong)

        horizontalLayout1.addWidget(titleLabel)
        horizontalLayout1.addWidget(self.titleEdit)


        #Horizontal Layout 2
        horizontalLayout2 = QHBoxLayout()
        statusLabel = QLabel("Status:")
        self.statusBox = QComboBox()

        dateLabel = QLabel("Date:")
        self.dateEdit = QDateTimeEdit()
        self.dateEdit.setCalendarPopup(True)

        horizontalLayout2.addWidget(statusLabel)
        horizontalLayout2.addWidget(self.statusBox)
        horizontalLayout2.addStretch(1)
        horizontalLayout2.addWidget(dateLabel)
        horizontalLayout2.addWidget(self.dateEdit)


        #Style Groupbox, widgets added automatically
        self.styleGroupBox = QGroupBox()
        self.styleGroupBox.setTitle("Style:")
        self.styleLayout = QGridLayout(self.styleGroupBox)

        horizontalLayout3 = QHBoxLayout()
        durationLabel = QLabel("Duration:")
        self.durationLine = QTimeEdit()
        self.durationLine.setDisplayFormat("mm:ss")

        projectLabel = QLabel("Project")

        self.projectComboBox = QComboBox()
        self.projectComboBox.setEditable(True)

        horizontalLayout3.addWidget(durationLabel)
        horizontalLayout3.addWidget(self.durationLine)
        horizontalLayout3.addWidget(projectLabel)
        horizontalLayout3.addWidget(self.projectComboBox)

        horizontalLayout4 = QHBoxLayout()
        descriptionLabel = QLabel("Description:")
        variationLabel = QLabel("Variation from another song: ")
        self.variationLine = QLineEdit()

        horizontalLayout4.addWidget(descriptionLabel)
        horizontalLayout4.addStretch(1)
        horizontalLayout4.addWidget(variationLabel)
        horizontalLayout4.addWidget(self.variationLine)

        self.descriptionTextEdit = QTextEdit()

        horizontalLayout5 = QHBoxLayout()
        locationLabel = QLabel("Location:")
        self.locationLine = QLineEdit()
        self.locationButton = QPushButton("...")
        self.locationButton.clicked.connect(self.locateFile)


        horizontalLayout5.addWidget(locationLabel)
        horizontalLayout5.addWidget(self.locationLine)
        horizontalLayout5.addWidget(self.locationButton)

        horizontalLayout6 = QHBoxLayout()
        self.slider = QSlider(Qt.Horizontal)
        self.slider.sliderReleased.connect(self.playSlider)
        self.slider.setStyleSheet("QSlider::handle:horizontal { border: 1px solid #777; background:#b55858;}")
        horizontalLayout6.addWidget(self.slider)

        horizontalLayout7 = QHBoxLayout()
        self.playButton = QPushButton()
        self.stopButton = QPushButton()

        self.playButton.setIcon(self.PLAY_ICON)
        self.stopButton.setIcon(self.STOP_ICON)

        self.playButton.clicked.connect(self.playSong)
        self.stopButton.clicked.connect(self.stopSong)

        horizontalLayout7.addStretch(1)
        horizontalLayout7.addWidget(self.playButton)
        horizontalLayout7.addWidget(self.stopButton)
        horizontalLayout7.addStretch(1)


        horizontalLayout8 = QHBoxLayout()
        self.saveButton = QPushButton()
        self.saveButton.setText("Save")
        self.saveButton.clicked.connect(self.saveSong)

        horizontalLayout8.addStretch(1)
        horizontalLayout8.addWidget(self.saveButton)

        mainLayout.addLayout(horizontalLayout1)
        mainLayout.addLayout(horizontalLayout2)
        mainLayout.addWidget(self.styleGroupBox)
        mainLayout.addLayout(horizontalLayout3)
        mainLayout.addLayout(horizontalLayout4)
        mainLayout.addWidget(self.descriptionTextEdit)
        mainLayout.addLayout(horizontalLayout5)
        mainLayout.addLayout(horizontalLayout6)
        mainLayout.addLayout(horizontalLayout7)
        mainLayout.addLayout(horizontalLayout8)

    def clearForm(self):
        self.titleEdit.clear()
        self.statusBox.clear()
        for widget in self.styleGroupBox.children():
            if not isinstance(widget, QGridLayout):
                widget.deleteLater()

        self.durationLine.clear()
        self.projectComboBox.clear()
        self.variationLine.clear()
        self.descriptionTextEdit.clear()
        self.locationLine.clear()

    def changePage(self, index):
        title = self.songsListWidget.item(index).data(Qt.UserRole)
        self.clearForm()
        self.populateForm(title)
        self.slider.setValue(0)

    def populateForm(self, title): #title is the primary key
        listArray = queries("""SELECT title, status, style, duration, description,
        location, project, variation_another_song, timestamp from songs WHERE title = ?""", (title,))
        print(listArray)
        if len(listArray) != 0:
            title = listArray[0][0]
            status = listArray[0][1]

            styles = []
            styleArray = listArray[0][2]
            if styleArray != None:
                if "," in styleArray:
                    styles = styleArray.split(",")
                else:
                    styles.append(styleArray)
            duration = listArray[0][3]
            description = listArray[0][4]
            location = listArray[0][5]
            project = listArray[0][6]
            variation_another_song = listArray[0][7]
            timestamp = listArray[0][8]
        else:
            title = None
            status = None
            styles = None
            duration = None
            description = None
            location = None
            project = None
            variation_another_song = None
            timestamp = None

        if title != None: self.titleEdit.setText(title)

        self.statusBox.addItems(["Select...", "Demo", "WIP", "Idea", "Unfinished song", "EQ", "Master", "Finished"])
        if status != None: self.statusBox.setCurrentText(status)
        if timestamp != None: self.dateEdit.setDateTime(datetime.strptime(timestamp, '%d/%m/%Y %H:%M'))
        else: self.dateEdit.setDateTime(datetime.now())#default

        styleArray = queries("select style from songs where style is not null")

        """
        print(styleArray)
        if styleArray != None:
            styleArray = styleArray[0][0]
            if "," in styleArray:
                styles = styleArray.split(",")
            else:
                styles.append(styleArray)"""

        stylesArray = []

        query = queries("select style from songs where style is not null")
        if len(query) != 0:
            for style in query:
                stylesMiniArray = style[0].split(",")
                stylesMiniArray = list(filter(None, stylesMiniArray))
                for item in stylesMiniArray:
                    if item not in stylesArray:
                        if item != '':
                            stylesArray.append(item)

        self.x = 0
        self.y = 0

        if len(stylesArray) != 0:
            for style in stylesArray:
                    print("style", style)
                    checkBox = QCheckBox(style)
                    self.styleLayout.addWidget(checkBox, self.x, self.y)
                    self.checkBoxPositionAsignment()
        self.addStyle()

        if styles!= None:
            if len(styles) != 0:
                for style in styles:
                    for checkbox in self.styleGroupBox.children():
                        if isinstance(checkbox, QCheckBox):
                            if checkbox.text() == style:
                                checkbox.setChecked(True)

        if duration != None:
                time = QTime(0,0,0)
                self.durationLine.setTime(time.addSecs(duration))

        projectsArray = ["Select..."]
        projectsArrayQuery = queries("SELECT project from songs")
        if len(projectsArrayQuery) != 0:
            for project in projectsArrayQuery[0]:
                if project not in projectsArray:
                    projectsArray.append(project)
        if project != None: self.projectComboBox.setCurrentText(project)

        if variation_another_song != None: self.variationLine.setText(variation_another_song)
        if description != None: self.descriptionTextEdit.setText(description)

        available = False
        if location != None:
            self.locationLine.setText(location)
        if len(self.locationLine.text()) != 0:
            try:
                self.playlist = QMediaPlaylist()
                self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(location)))
                self.mediaPlayer.setPlaylist(self.playlist)
            except:
                pass
            available = True#I know this is stupid but just in case

        self.slider.setVisible(available)
        self.playButton.setVisible(available)
        self.stopButton.setVisible(available)

    def populateList(self, locatorItem=None, locatorColumn=None):
        print(locatorItem, locatorColumn)
        self.songsListWidget.blockSignals(True)
        self.songsListWidget.clear()
        if locatorItem == None or locatorItem == "":
            listArray = queries("""SELECT title, status, timestamp from songs """)
            print(listArray)
        else:
            if locatorColumn != "All": #No strings concatenation, no security holes
                if locatorColumn == "Title":
                    sql = """SELECT title, status, timestamp from songs where title LIKE ?"""
                elif locatorColumn == "Status":
                    sql = """SELECT title, status, timestamp from songs where status LIKE ?"""
                elif locatorColumn == "Description":
                    sql = """SELECT title, status, timestamp from songs where description LIKE ?"""
                elif locatorColumn == "Style":
                    sql = """SELECT title, status, timestamp from songs where style LIKE ?"""

                locatorItem = "%" + locatorItem + "%"
                listArray = queries(sql, (locatorItem,))
            else:
                locatorItem = "%" + locatorItem + "%"
                variables = [locatorItem, locatorItem, locatorItem, locatorItem, locatorItem]
                listArray = queries("""SELECT title, status, timestamp from songs
                where title LIKE ? OR type LIKE ? OR original_song LIKE ? OR link LIKE ?
                OR description LIKE ?""", variables)
        for item in listArray:
            title = item[0]
            status = item[1]
            timestamp = item[2]
            try:
                timestamp = datetime.strptime(timestamp, "%d/%m/%Y %H:%M")
                timestamp = timestamp.strftime("%d/%m/%Y")
            except:
                timestamp = ""

            text = "%s %s %s" % (title, status, timestamp)
            qItem = QListWidgetItem(text)
            qItem.setData(Qt.UserRole, title)
            self.songsListWidget.addItem(qItem)
        #new idea
        qItem = QListWidgetItem("New song...")
        qItem.setData(Qt.UserRole, "New song...") #otherwise that would be an error
        self.songsListWidget.addItem(qItem)
        self.songsListWidget.blockSignals(False)

    def listWidgetRightClick(self, position):
        widgetItem = self.songsListWidget.itemAt(position)
        if widgetItem != None: #quick lazy text fix
            if widgetItem.text() != "New song...":
                print(widgetItem.text())
                menu = QMenu()
                deleteAction = QAction(self.DELETE_ICON, "Delete song")
                menu.addAction(deleteAction)
                action = menu.exec(self.mapToGlobal(position)) 

                if action == deleteAction:
                    msg = QMessageBox.question(None, "Delete?", "Are you sure you want to delete this entry?")
                    if msg == QMessageBox.Yes:
                        title = widgetItem.data(Qt.UserRole)
                        queries("DELETE from songs where title = ?", (title,))
                        self.populateList()
                        self.songsListWidget.setCurrentRow(0)

    def songVariations(self):
        sql = "SELECT title from songs"
        songArray = []
        for song in queries(sql)[0]:
            songArray.append(song)
        return songArray
    def checkBoxPositionAsignment(self):
            self.y += 1
            if self.y == 4:
                self.y = 0
                self.x += 1
    def addStyle(self, text=""):
        "text = "" if comes from outside"

        self.styleEdit = QLineEdit()
        self.styleEdit.setPlaceholderText("Style")
        self.styleEdit.textChanged.connect(self.validateStyle)
        self.styleEdit.returnPressed.connect(lambda: self.addStyle(self.styleEdit.text()))

        if text != "":
            self.styleLayout.takeAt(self.styleLayout.count()-1).widget().deleteLater()

            styleCheckBox = QCheckBox()
            styleCheckBox.setText(text)
            print(text)
            self.styleLayout.addWidget(styleCheckBox, self.x, self.y)
            self.checkBoxPositionAsignment()
            print(self.durationLine.text())
        self.styleLayout.addWidget(self.styleEdit)


    def checkSong(self):
        text = self.titleEdit.text()
        sql = "SELECT title from songs where title = ?"
        if len(queries(sql, (text,))) != 0:
            self.titleEdit.setText("")
    def validateSong(self):
        pass
        #VALIDATE REG EXP

    def validateStyle(self, text):
        if "," in text:
            self.styleEdit.undo()

    def playSong(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.PAUSE_ICON)
        else:
            self.playButton.setIcon(self.PLAY_ICON)
    def positionChanged(self, position):
        if position != self.mediaPlayer.duration():
            self.slider.setValue(position)
    def durationChanged(self, duration):
        if duration != self.mediaPlayer.position():
            print("duration chagned")
            self.slider.setRange(0, duration)
    def playSlider(self):
        self.mediaPlayer.setPosition(self.slider.value())

    def stopSong(self):
        self.mediaPlayer.stop()

    def locateFile(self):
        self.fileSystem = QFileDialog(filter="Sound files (*.wav *.mp3 *.flac)")
        self.fileSystem.show()
        self.fileSystem.fileSelected.connect(self.fileLoaded)

    def fileLoaded(self, path):
        self.locationLine.setText(path)
        try:
            self.playlist = QMediaPlaylist()
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(path)))
            self.mediaPlayer.setPlaylist(self.playlist)
        except:
            print("fail")
        self.slider.setVisible(True)
        self.playButton.setVisible(True)
        self.stopButton.setVisible(True)

    def saveSong(self):
        title = self.titleEdit.text()
        status = self.statusBox.currentText()
        date = self.dateEdit.text()
        style = ""

        print(status, style)
        x = 0
        for checkBox in self.styleGroupBox.children():
            if isinstance(checkBox, QCheckBox):
                if checkBox.isChecked():
                    style += (checkBox.text()) + ","
                    x+=1
        if x != 0: style = style.rstrip(",")
        else: style = None

        duration = self.durationLine.time()
        duration = QTime(0, 0).secsTo(duration)

        project = self.projectComboBox.currentText()
        variation = self.variationLine.text()
        description = self.descriptionTextEdit.toPlainText()
        location = self.locationLine.text()

        variables = [title, status, description, location, project,\
        variation, date, style, duration]

        print("---------", variables)

        sql = """INSERT OR REPLACE into songs
        (title, status, description, location, project,
        variation_another_song, timestamp, style, duration)

        values
        (?,      ?,       ?,          ?,     ?,
         ?,                     ?,         ?,      ?)"""

        queries(sql, variables)
        self.populateList()
Пример #21
0
class Multidialog(QDialog):
    def __init__(self, screen, title, form_set, buttons=None, button_pressed=lambda:None):
        if screen in window.screens:
            self.screen = screen
            super(Multidialog, self).__init__(window.screens[screen])
        else:
            self.screen = None

        self.form_set = form_set
        self.elements = {}
        self.title = title
        self.setWindowTitle(self.title)
        self.main_layout = QVBoxLayout()
        self.group_box = QGroupBox()
        self.first_launch = True
        layout = QFormLayout()
        for f in self.form_set:
            if not 'name' in f: continue
            else:
                self.elements[f['name']] = {k:f[k] for k in f}
                e, l = self.get_element(etype=f['type'],
                                        settings=f['settings'] if 'settings' in f else None,
                                        data=f['data'] if 'data' in f else None,
                                        label=f['label'] if 'label' in f else None)
                self.elements[f['name']]['object'], self.elements[f['name']]['label'] = e, l
                self.elements[f['name']]['callback'] = False
                if 'settings' in f: self.elements[f['name']]['settings'] = f['settings']

            layout.addRow(self.elements[f['name']]['label'], self.elements[f['name']]['object'])
        self.initialize_settings()
        if not buttons:
            self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
            self.button_box.accepted.connect(self.accept)
            self.button_box.rejected.connect(self.reject)
        else:
            self.button_box = QDialogButtonBox(QDialogButtonBox.Reset | QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
            #this needs some work
            
        self.group_box.setLayout(layout)
        self.main_layout.addWidget(self.group_box)
        self.main_layout.addWidget(self.button_box)
        self.setLayout(self.main_layout)
        self.setFixedSize(self.main_layout.sizeHint())

    def get_element(self, etype, settings, data, label):
        widget = None
        label = QLabel(label)
        if etype.lower() == "input":
            le = QLineEdit()
            if data and isinstance(data, str): le.setText(data)
            if settings and 'mode' in settings:
                if settings["mode"] == "password": le.setEchoMode(QLineEdit.Password)
            widget = le
        elif etype.lower() == "dropdown":
            cb = QComboBox()
            cb.setFocusPolicy(Qt.StrongFocus)
            # bugged on enter activate; to-do
            # # QShortcut(QKeySequence(Qt.Key_Return), cb)
            # cb.enterPressed.activated.connect(lambda: cb.showPopup)
            if data:
                if isinstance(data, list): cb.addItems(data)
                elif isinstance(data, str): cb.addItem(data)
            widget = cb
        elif etype.lower() == "color":
            cb = ColorButton()
            if settings and 'pref' in settings:
                cb.pref = settings['pref']
                cb.color = prefs.get_pref(cb.pref)
            elif 'color' in settings:
                cb.color = settings['color']
            cb.updateColor(cb.color)
            widget = cb
        return widget, label

    def initialize_settings(self):
        for el in self.elements:
            e = self.elements[el]
            if 'settings' in e:
                settings = e['settings']
                if 'conditional_show' in settings:
                    if 'element' in settings['conditional_show']:
                        if settings['conditional_show']['element'] in self.elements:
                            ref_e = settings['conditional_show']['element']
                            if 'callback' in self.elements[ref_e] and not self.elements[ref_e]['callback']:
                                if 'object' in self.elements[ref_e] and isinstance(self.elements[ref_e]['object'], QComboBox):
                                    self.elements[ref_e]['object'].currentIndexChanged.connect(self.initialize_settings)
                                    self.elements[ref_e]['callback'] = True
                            if 'object' in self.elements[ref_e]:
                                if 'not_state' in settings['conditional_show']:
                                    sv = not (self.elements[ref_e]['object'].currentText() in settings['conditional_show']['not_state'])
                                    e['object'].setVisible(sv)
                                    e['label'].setVisible(sv)
                                elif 'state' in settings['conditional_show']:
                                    sv = (self.elements[ref_e]['object'].currentText() in settings['conditional_show']['state'])
                                    e['object'].setVisible(sv)
                                    e['label'].setVisible(sv)

    def refresh(self):
        for w in self.group_box.children():
            if isinstance(w, QLineEdit): w.setText("")
            elif isinstance(w, QComboBox):
                if w.count() > 0: w.setCurrentIndex(0)