class MyForm(QMainWindow):
    
    def __init__(self, parent = None):
        
        # standard GUI code
        QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.canvas = FigureCanvas(self.ui.mplwidgetPulseSeq.figure)
        self.canvas.setParent(self.ui.widgetMPLPlot)
        
        # MPL toolbar
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.ui.widgetMPLPlot)
        self.mpl_toolbar.setParent(self.ui.widgetMPLToolbar)

        vboxPlot = QVBoxLayout()
        vboxPlot.addWidget(self.canvas)  # the matplotlib canvas
        vboxToolbar = QVBoxLayout()
        vboxToolbar.addWidget(self.mpl_toolbar) # the matplotlib toolbar
        
        self.ui.widgetMPLPlot.setLayout(vboxPlot)
        self.ui.widgetMPLToolbar.setLayout(vboxToolbar)
        
        self.ui.mplwidgetPulseSeq = self.canvas
        
        self.error_message = QErrorMessage(parent=self)
        self.pulse_sequence = PulseSequence()
        
        # Connect the buttons
        self.connect(self.ui.comboBoxChannel, SIGNAL("currentIndexChanged(int)"), self.changeChannel)
        self.connect(self.ui.comboBoxPulseTrainIndex, SIGNAL("currentIndexChanged(int)"), self.changePulseTrainIndex)
        self.connect(self.ui.lineEditTimeOn, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.lineEditPulseWidth, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.lineEditPulseSeparation, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.lineEditPulsesInTrain, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.pushButtonAddPulse, SIGNAL("clicked()"), self.addPulseTrain)
        self.connect(self.ui.pushButtonDeletePulse, SIGNAL("clicked()"), self.deletePulseTrain)
        self.connect(self.ui.pushButtonChooseSaveFile, SIGNAL("clicked()"), self.choose_save_file)
        self.connect(self.ui.pushButtonSavePS, SIGNAL("clicked()"), self.save_ps)
        self.connect(self.ui.pushButtonLoadPS, SIGNAL("clicked()"), self.load_ps)
        self.connect(self.ui.pushButtonChooseLoadFile, SIGNAL("clicked()"), self.choose_load_file)
        self.connect(self.ui.comboBoxWaitEvents, SIGNAL("currentIndexChanged(int)"), self.changeWaitEventIndex)
        self.connect(self.ui.pushButtonAddWait, SIGNAL("clicked()"), self.addWaitEvent)
        self.connect(self.ui.pushButtonDeleteWait, SIGNAL("clicked()"), self.deleteWaitEvent)
        self.connect(self.ui.lineEditWaitTime, SIGNAL("returnPressed()"), self.editWaitEvent)
        
        
        self.connect(self.ui.pushButtonInitializePB, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Initialize'))
        self.connect(self.ui.pushButtonClosePB, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Close'))
        self.connect(self.ui.pushButtonSendSequence, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Send sequence'))
        self.connect(self.ui.pushButtonStartSequence, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Start sequence'))
        self.connect(self.ui.pushButtonStopSequence, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Stop sequence'))
        self.connect(self.ui.pushButtonGetStatus, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Get status'))
        
        self.connect(self.ui.pushButtonClearMessages, SIGNAL("clicked()"), self.ui.textEditMessages.clear)
        
        # Set validators for pulse train attributes
        vTimeOn = QDoubleValidator(self.ui.lineEditTimeOn)
        vTimeOn.setRange(12.5e-09, 10000.0, 9)
        vDouble = QDoubleValidator(self.ui.lineEditPulseWidth)
        vDouble.setRange(2.5e-09, 10000.0, 9)
        vDouble.setNotation(1)
        self.ui.lineEditTimeOn.setValidator(vTimeOn)
        self.ui.lineEditPulseWidth.setValidator(vDouble)
        self.ui.lineEditPulseSeparation.setValidator(vDouble)  
        self.ui.lineEditPBClockFrequency.setValidator(vDouble)
        self.ui.lineEditWaitTime.setValidator(vDouble)
        vInt = QIntValidator(1, 1000, self.ui.lineEditPulsesInTrain)
        self.ui.lineEditPulsesInTrain.setValidator(vInt)
        
        # Create threads
        self.save_ps_thread = Save_pulse_sequence()
        self.load_ps_thread = Load_pulse_sequence()
        self.plot_ps_thread = Plot_pulse_sequence()
        self.communicate_with_pb_thread = Communicate_with_PB()
        
        # Connect the threads
        self.connect(self.save_ps_thread, SIGNAL("Save attempted."), self.update_save_status)
        self.connect(self.load_ps_thread, SIGNAL("Load attempted."), self.update_load_status)
        self.connect(self.load_ps_thread, SIGNAL("Initiate loaded pulse sequence."), self.initiate_loaded_ps)
        self.connect(self.communicate_with_pb_thread, SIGNAL("New message."), self.update_messages)
        self.connect(self.communicate_with_pb_thread, SIGNAL("New command."), self.update_command)
        self.connect(self.communicate_with_pb_thread, SIGNAL("New status."), self.update_status)
        
        # Populate pulse sequence with channels:
        for i in xrange(21):
            self.pulse_sequence.addChannel()
            self.currentChannel = self.pulse_sequence.channels[i]
            self.ui.comboBoxChannel.addItem(str(self.currentChannel.pulse_channel_index))
        self.ui.comboBoxChannel.setCurrentIndex(0)
        self.changeChannel()

    def changeChannel(self):
        self.currentChannel = self.pulse_sequence.channels[self.ui.comboBoxChannel.currentIndex()]
        self.ui.comboBoxPulseTrainIndex.clear()
        if self.currentChannel.num_of_pulse_trains > 0:
            self.ui.comboBoxPulseTrainIndex.addItems(map(str, range(self.currentChannel.num_of_pulse_trains)))
            self.ui.comboBoxPulseTrainIndex.setCurrentIndex(0)
            self.changePulseTrainIndex()
        else:
            self.ui.lineEditTimeOn.setText('1e-06')
            self.ui.lineEditPulseWidth.setText('1e-07')
            self.ui.lineEditPulseSeparation.setText('0.0')
            self.ui.lineEditPulsesInTrain.setText('1')
            self.ui.lineEditTimeOn.selectAll()
            self.ui.lineEditPulseWidth.selectAll()
            self.ui.lineEditPulseSeparation.selectAll()
            self.ui.lineEditPulsesInTrain.selectAll()
            
    def changeWaitEventIndex(self):
        if self.pulse_sequence.num_of_wait_events > 0:
            self.ui.lineEditWaitTime.setText(str(self.pulse_sequence.wait_events[int(self.ui.comboBoxWaitEvents.currentIndex())]))

    def editWaitEvent(self):
        clock_cycle = 1e03/(float(self.ui.lineEditPBClockFrequency.text()))
        self.pulse_sequence.wait_events[self.ui.comboBoxWaitEvents.currentIndex()] = round((float(self.ui.lineEditWaitTime.text())*1e09)/clock_cycle)*clock_cycle*1e-09
        self.ui.lineEditWaitTime.setText(str(round((float(self.ui.lineEditWaitTime.text())*1e09)/clock_cycle)*clock_cycle*1e-09))
        instructions, seq, run_time, found_bad_instruction = self.pulse_sequence.convertSequenceToInstructions(self.ui.checkBoxInfiniteLoop.isChecked(), 
                                                                self.ui.spinBoxNumberOfLoops.value())
        if found_bad_instruction:
            self.error_message.showMessage('Sequence includes a bad instruction! The time between the beginning of any two pulses on any two channels must be at least 5 PulseBlaster clock cycles. Recommend undoing last action.')
        self.plot_sequence()

        
    def addWaitEvent(self):
        clock_cycle = 1e03/(float(self.ui.lineEditPBClockFrequency.text()))
        self.pulse_sequence.addWaitEvent(round((float(self.ui.lineEditWaitTime.text())*1e09)/clock_cycle)*clock_cycle*1e-09)
        self.ui.lineEditWaitTime.setText(str(round((float(self.ui.lineEditWaitTime.text())*1e09)/clock_cycle)*clock_cycle*1e-09))
        self.ui.comboBoxWaitEvents.addItem(str(self.pulse_sequence.num_of_wait_events-1))
        self.ui.comboBoxWaitEvents.setCurrentIndex(self.pulse_sequence.num_of_wait_events-1)
        instructions, seq, run_time, found_bad_instruction = self.pulse_sequence.convertSequenceToInstructions(self.ui.checkBoxInfiniteLoop.isChecked(), 
                                                                self.ui.spinBoxNumberOfLoops.value())
        if found_bad_instruction:
            self.error_message.showMessage('Sequence includes a bad instruction! The time between the beginning of any two pulses on any two channels must be at least 5 PulseBlaster clock cycles. Recommend undoing last action.')
        self.plot_sequence()
        
    def deleteWaitEvent(self):
        if self.pulse_sequence.num_of_wait_events > 0:
            self.pulse_sequence.deleteWaitEvent(self.ui.comboBoxWaitEvents.currentIndex())
            self.ui.comboBoxWaitEvents.removeItem(self.pulse_sequence.num_of_wait_events)
            if self.pulse_sequence.num_of_wait_events > 0:
                self.ui.lineEditWaitTime.setText(str(self.pulse_sequence.wait_events[int(self.ui.comboBoxWaitEvents.currentIndex())]))
            else:
                self.ui.lineEditWaitTime.clear()
            self.plot_sequence()
        
    def changePulseTrainIndex(self):
        if self.currentChannel.num_of_pulse_trains > 0:
            new_index = self.ui.comboBoxPulseTrainIndex.currentIndex()
            
            self.currentPulseTrain = self.currentChannel.pulse_trains[new_index]
           
            self.ui.lineEditTimeOn.setText(str(self.currentChannel.pulse_trains[new_index].time_on))
            self.ui.lineEditPulseWidth.setText(str(self.currentChannel.pulse_trains[new_index].width))
            self.ui.lineEditPulseSeparation.setText(str(self.currentChannel.pulse_trains[new_index].separation))
            self.ui.lineEditPulsesInTrain.setText(str(self.currentChannel.pulse_trains[new_index].pulses_in_train))
    
    # When editing or adding pulse trains to the sequence, time_on, width, and separation values are rounded to the
    # nearest clock cycle, the resolution of the PB
    def EditPulseTrain(self):
        clock_cycle = 1e03/(float(self.ui.lineEditPBClockFrequency.text()))
        if self.currentChannel.num_of_pulse_trains > 0:
            pulse_train_index = self.ui.comboBoxPulseTrainIndex.currentIndex()
            old_pulse_train = self.currentChannel.pulse_trains[pulse_train_index]
            self.currentChannel.pulse_trains[pulse_train_index] = PulseTrain(time_on = round((float(self.ui.lineEditTimeOn.text())*1e09)/clock_cycle)*clock_cycle*1e-09, width = round((float(self.ui.lineEditPulseWidth.text())*1e09)/clock_cycle)*clock_cycle*1e-09,
                                                    separation = round((float(self.ui.lineEditPulseSeparation.text())*1e09)/clock_cycle)*clock_cycle*1e-09, pulses_in_train = int(self.ui.lineEditPulsesInTrain.text())) 
            if not self.currentChannel.has_coincident_events():
                self.currentPulseTrain = self.currentChannel.pulse_trains[pulse_train_index]
                self.currentChannel.setLatestChannelEvent()
                self.pulse_sequence.setLatestSequenceEvent()
                self.currentChannel.setFirstChannelEvent()
                self.pulse_sequence.setFirstSequenceEvent()
                
                # check to see if added pulse will give a bad instruction to PulseBlaster
                instructions, seq, run_time, found_bad_instruction = self.pulse_sequence.convertSequenceToInstructions(self.ui.checkBoxInfiniteLoop.isChecked(), 
                                                                self.ui.spinBoxNumberOfLoops.value())
                if found_bad_instruction:
                    #self.currentChannel.pulse_trains[pulse_train_index] = old_pulse_train
                    #self.currentPulseTrain = self.currentChannel.pulse_trains[pulse_train_index]  
                    #self.currentChannel.setLatestChannelEvent()
                    #self.pulse_sequence.setLatestSequenceEvent()
                    #self.currentChannel.setFirstChannelEvent()
                    #self.pulse_sequence.setFirstSequenceEvent()
                    #self.changePulseTrainIndex()
                    
                    self.error_message.showMessage('This will create a bad instruction! The time between the beginning of any two pulses on any two channels must be at least 5 PulseBlaster clock cycles. Recommend undoing last action.')
                self.plot_sequence()
                self.changePulseTrainIndex()
            else:
                self.currentChannel.pulse_trains[pulse_train_index] = old_pulse_train
                self.changePulseTrainIndex()
                sle.plot_sequence()
                self.error_message.showMessage('Pulses overlap!. Changes have been discarded.')
            
    def addPulseTrain(self):
        clock_cycle = 1e03/(float(self.ui.lineEditPBClockFrequency.text()))
        if self.ui.lineEditTimeOn.hasAcceptableInput() and self.ui.lineEditPulseWidth.hasAcceptableInput() and self.ui.lineEditPulseSeparation and self.ui.lineEditPulsesInTrain.hasAcceptableInput:
            self.currentChannel.addPulseTrain(round((float(self.ui.lineEditTimeOn.text())*1e09)/clock_cycle)*clock_cycle*1e-09,
                                    round((float(self.ui.lineEditPulseWidth.text())*1e09)/clock_cycle)*clock_cycle*1e-09,
                                    round((float(self.ui.lineEditPulseSeparation.text())*1e09)/clock_cycle)*clock_cycle*1e-09,
                                    int(self.ui.lineEditPulsesInTrain.text()))
                                    
            if not self.currentChannel.has_coincident_events():

                self.currentChannel.setLatestChannelEvent()
                self.pulse_sequence.setLatestSequenceEvent()
                self.currentChannel.setFirstChannelEvent()
                self.pulse_sequence.setFirstSequenceEvent()
                self.ui.comboBoxPulseTrainIndex.addItem(str(self.currentChannel.num_of_pulse_trains-1))
                self.ui.comboBoxPulseTrainIndex.setCurrentIndex(self.currentChannel.num_of_pulse_trains-1)
                self.currentPulseTrain = self.currentChannel.pulse_trains[self.currentChannel.num_of_pulse_trains-1]
                # check to see if added pulse will give a bad instruction to PulseBlaster
                instructions, seq, run_time, found_bad_instruction = self.pulse_sequence.convertSequenceToInstructions(self.ui.checkBoxInfiniteLoop.isChecked(), 
                                                                self.ui.spinBoxNumberOfLoops.value())
                self.plot_sequence()
                if found_bad_instruction:
                    self.error_message.showMessage('This will create a bad instruction! The time between the beginning of any two pulses on any two channels must be at least 5 PulseBlaster clock cycles. Recommend undoing last action.')
                    #self.deletePulseTrain()
            else:
                self.deletePulseTrain()
                self.error_message.showMessage('Pulses overlap! Pulse train has not been added.')
            
    
    def deletePulseTrain(self):
        if self.pulse_sequence.num_of_channels > 0 and self.currentChannel.num_of_pulse_trains > 0:
            index = self.ui.comboBoxPulseTrainIndex.currentIndex()
            if (self.currentChannel.deletePulseTrain(index)):
                self.ui.comboBoxPulseTrainIndex.removeItem(self.currentChannel.num_of_pulse_trains)
                if index == 0:
                    self.ui.comboBoxPulseTrainIndex.setCurrentIndex(0)
                else:
                    self.ui.comboBoxPulseTrainIndex.setCurrentIndex(index-1)
                self.changePulseTrainIndex()
                self.currentChannel.setLatestChannelEvent()
                self.pulse_sequence.setLatestSequenceEvent()
                self.currentChannel.setFirstChannelEvent()
                self.pulse_sequence.setFirstSequenceEvent()
                self.plot_sequence()
                    
    def choose_load_file(self):
        self.ui.textEditLoadFile.setText(QFileDialog.getOpenFileName(filter='pickle Files (*.pkl)'))
    def load_ps(self):
        file_name = self.ui.textEditLoadFile.toPlainText()
        self.load_ps_thread.input(file_name)
    def update_load_status(self, status):
        self.ui.textEditLoadStatus.setText(status)
    
    def initiate_loaded_ps(self, pulse_sequence):
        self.pulse_sequence = pulse_sequence
        channels = map(str, range(self.pulse_sequence.num_of_channels))
        self.ui.comboBoxChannel.clear()
        self.ui.comboBoxChannel.addItems(map(str, self.pulse_sequence.pulse_channel_indices))
        if self.pulse_sequence.num_of_wait_events > 0:
            self.ui.comboBoxWaitEvents.addItems(map(str, range(self.pulse_sequence.num_of_wait_events)))
            self.ui.lineEditWaitTime.setText(str(self.pulse_sequence.wait_events[0]))
        self.plot_ps_thread.input(self.pulse_sequence, self.ui.mplwidgetPulseSeq, float(self.ui.lineEditPBClockFrequency.text()))
        
    def choose_save_file(self):
        self.ui.textEditSaveFile.setText(QFileDialog.getSaveFileName(filter='pickle Files (*.pkl)'))
    def save_ps(self):
        file_name = self.ui.textEditSaveFile.toPlainText()
        self.save_ps_thread.input(self.pulse_sequence, file_name)
    def update_save_status(self, status):
        self.ui.textEditSaveStatus.setText(status)

    def plot_sequence(self):
        self.plot_ps_thread.input(self.pulse_sequence, self.ui.mplwidgetPulseSeq, float(self.ui.lineEditPBClockFrequency.text()))

    def communicate_with_pb(self, command):
        self.command = command
        if self.command == 'Initialize':
            self.communicate_with_pb_thread.initialize(self.ui.lineEditPBClockFrequency.text())
        elif self.command == 'Close':
            self.communicate_with_pb_thread.close()
        elif self.command == 'Send sequence':
            self.communicate_with_pb_thread.send_sequence(self.pulse_sequence, str(self.ui.lineEditPBClockFrequency.text()), self.ui.checkBoxInfiniteLoop.isChecked(), 
                                                            self.ui.doubleSpinBoxRunTime.value(), self.ui.spinBoxNumberOfLoops.value())
        elif self.command == 'Start sequence':
            self.communicate_with_pb_thread.start_sequence()
        elif self.command == 'Stop sequence':
            self.communicate_with_pb_thread.stop_sequence()
        elif self.command == 'Get status':
            self.communicate_with_pb_thread.get_status()
        
            
    def update_messages(self, message):
        self.ui.textEditMessages.append(message)
    def update_command(self, command):
        self.ui.lineEditCommand.setText(command)
    def update_status(self, status):
        self.ui.lineEditStatus.setText(status)
class MyForm(QMainWindow):
    
    def __init__(self, parent = None):
        
        # standard GUI code
        QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.canvas = FigureCanvas(self.ui.mplwidgetPulseSeq.figure)
        self.canvas.setParent(self.ui.widgetMPLPlot)
        #self.canvas.setFocusPolicy(Qt.StrongFocus)
        #self.canvas.setFocus()
        
        # MPL toolbar
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.ui.widgetMPLPlot)
        self.mpl_toolbar.setParent(self.ui.widgetMPLToolbar)
        
        #self.canvas.mpl_connect('key_press_event', self.on_key_press)

        vboxPlot = QVBoxLayout()
        vboxPlot.addWidget(self.canvas)  # the matplotlib canvas
        vboxToolbar = QVBoxLayout()
        vboxToolbar.addWidget(self.mpl_toolbar) # the matplotlib toolbar
        
        self.ui.widgetMPLPlot.setLayout(vboxPlot)
        self.ui.widgetMPLToolbar.setLayout(vboxToolbar)
        
        self.ui.mplwidgetPulseSeq = self.canvas

        self.pulse_sequence = PulseSequence()
        
        # Connect the buttons
        self.connect(self.ui.comboBoxChannel, SIGNAL("currentIndexChanged(int)"), self.changeChannel)
        self.connect(self.ui.comboBoxPulseTrainIndex, SIGNAL("currentIndexChanged(int)"), self.changePulseTrainIndex)
        self.connect(self.ui.lineEditTimeOn, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.lineEditPulseWidth, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.lineEditPulseSeparation, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.lineEditPulsesInTrain, SIGNAL("returnPressed()"), self.EditPulseTrain)
        self.connect(self.ui.pushButtonAddPulse, SIGNAL("clicked()"), self.addPulseTrain)
        self.connect(self.ui.pushButtonDeletePulse, SIGNAL("clicked()"), self.deletePulseTrain)
        self.connect(self.ui.pushButtonChooseSaveFile, SIGNAL("clicked()"), self.choose_save_file)
        self.connect(self.ui.pushButtonSavePS, SIGNAL("clicked()"), self.save_ps)
        self.connect(self.ui.pushButtonLoadPS, SIGNAL("clicked()"), self.load_ps)
        self.connect(self.ui.pushButtonChooseLoadFile, SIGNAL("clicked()"), self.choose_load_file)
        self.connect(self.ui.comboBoxWaitEvents, SIGNAL("currentIndexChanged(int)"), self.changeWaitEventIndex)
        self.connect(self.ui.pushButtonAddWait, SIGNAL("clicked()"), self.addWaitEvent)
        self.connect(self.ui.pushButtonDeleteWait, SIGNAL("clicked()"), self.deleteWaitEvent)
        self.connect(self.ui.lineEditWaitTime, SIGNAL("returnPressed()"), self.editWaitEvent)
        
        
        self.connect(self.ui.pushButtonInitializePB, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Initialize'))
        self.connect(self.ui.pushButtonStartSequence, SIGNAL("clicked()"), lambda: self.communicate_with_pb('Start sequence'))
        self.connect(self.ui.pushButtonClearMessages, SIGNAL("clicked()"), self.ui.textEditMessages.clear)
        
        # Set validators for pulse train attributes
        vTimeOn = QDoubleValidator(self.ui.lineEditTimeOn)
        vTimeOn.setRange(12.5e-09, 10000.0, 7)
        vDouble = QDoubleValidator(self.ui.lineEditPulseWidth)
        vDouble.setRange(2.5e-09, 10000.0, 7)
        vDouble.setNotation(1)
        self.ui.lineEditTimeOn.setValidator(vTimeOn)
        self.ui.lineEditPulseWidth.setValidator(vDouble)
        self.ui.lineEditPulseSeparation.setValidator(vDouble)  
        self.ui.lineEditPBClockFrequency.setValidator(vDouble)
        self.ui.lineEditWaitTime.setValidator(vDouble)
        vInt = QIntValidator(1, 1000, self.ui.lineEditPulsesInTrain)
        self.ui.lineEditPulsesInTrain.setValidator(vInt)
        
        # Create threads
        self.save_ps_thread = Save_pulse_sequence()
        self.load_ps_thread = Load_pulse_sequence()
        self.plot_ps_thread = Plot_pulse_sequence()
        self.communicate_with_pb_thread = Communicate_with_PB()
        
        # Connect the threads
        self.connect(self.save_ps_thread, SIGNAL("Save attempted."), self.update_save_status)
        self.connect(self.load_ps_thread, SIGNAL("Load attempted."), self.update_load_status)
        self.connect(self.load_ps_thread, SIGNAL("Initiate loaded pulse sequence."), self.initiate_loaded_ps)
        self.connect(self.communicate_with_pb_thread, SIGNAL("New message."), self.update_messages)
        
        # Populate pulse sequence with channels:
        for i in xrange(21):
            self.pulse_sequence.addChannel()
            self.currentChannel = self.pulse_sequence.channels[i]
            self.ui.comboBoxChannel.addItem(str(self.currentChannel.pulse_channel_index))
        self.ui.comboBoxChannel.setCurrentIndex(0)
        self.changeChannel()

    def changeChannel(self):
        self.currentChannel = self.pulse_sequence.channels[self.ui.comboBoxChannel.currentIndex()]
        self.ui.comboBoxPulseTrainIndex.clear()
        if self.currentChannel.num_of_pulse_trains > 0:
            self.ui.comboBoxPulseTrainIndex.addItems(map(str, range(self.currentChannel.num_of_pulse_trains)))
            self.ui.comboBoxPulseTrainIndex.setCurrentIndex(0)
            self.changePulseTrainIndex()
        else:
            self.ui.lineEditTimeOn.setText('1e-06')
            self.ui.lineEditPulseWidth.setText('1e-07')
            self.ui.lineEditPulseSeparation.setText('0.0')
            self.ui.lineEditPulsesInTrain.setText('1')
            self.ui.lineEditTimeOn.selectAll()
            self.ui.lineEditPulseWidth.selectAll()
            self.ui.lineEditPulseSeparation.selectAll()
            self.ui.lineEditPulsesInTrain.selectAll()
            
    def changeWaitEventIndex(self):
        if self.pulse_sequence.num_of_wait_events > 0:
            self.ui.lineEditWaitTime.setText(str(self.pulse_sequence.wait_events[int(self.ui.comboBoxWaitEvents.currentIndex())]))

    def editWaitEvent(self):
        self.pulse_sequence.wait_events[self.ui.comboBoxWaitEvents.currentIndex()] = float(self.ui.lineEditWaitTime.text())
        self.plot_sequence()
        
    def addWaitEvent(self):
        self.pulse_sequence.addWaitEvent(str(self.ui.lineEditWaitTime.text()))
        self.ui.comboBoxWaitEvents.addItem(str(self.pulse_sequence.num_of_wait_events-1))
        self.ui.comboBoxWaitEvents.setCurrentIndex(self.pulse_sequence.num_of_wait_events-1)
        self.plot_sequence()
    
    def deleteWaitEvent(self):
        if self.pulse_sequence.num_of_wait_events > 0:
            self.pulse_sequence.deleteWaitEvent(self.ui.comboBoxWaitEvents.currentIndex())
            self.ui.comboBoxWaitEvents.removeItem(self.pulse_sequence.num_of_wait_events)
            if self.pulse_sequence.num_of_wait_events > 0:
                self.ui.lineEditWaitTime.setText(str(self.pulse_sequence.wait_events[int(self.ui.comboBoxWaitEvents.currentIndex())]))
            else:
                self.ui.lineEditWaitTime.clear()
            self.plot_sequence()
            
    #def addChannel(self):  
    #    if self.pulse_sequence.num_of_channels < self.pulse_sequence._CHANNELS:
    #        self.pulse_sequence.addChannel()
    #        self.currentChannel = self.pulse_sequence.channels[-1]
    #        self.ui.comboBoxChannel.addItem(str(self.currentChannel.pulse_channel_index))
    #        self.ui.comboBoxChannel.setCurrentIndex(self.pulse_sequence.num_of_channels-1)
    #        self.plot_ps_thread.input(self.pulse_sequence, self.ui.mplwidgetPulseSeq)
        
    
    #def deleteChannel(self):
    #    if self.pulse_sequence.num_of_channels > 0:
    #        index = self.ui.comboBoxChannel.currentIndex()
    #        if (self.pulse_sequence.deleteChannel(index)):
    #            if self.pulse_sequence.num_of_channels == 0:
    #                self.ui.comboBoxChannel.clear()
    #                self.ui.comboBoxPulseTrainIndex.clear()
    #            else:
    #                if index == 0:
    #                    self.currentChannel = self.pulse_sequence.channels[index]
    #                    self.ui.comboBoxChannel.removeItem(index)
    #                    self.ui.comboBoxChannel.setCurrentIndex(index)
    #                else:
    #                    self.currentChannel = self.pulse_sequence.channels[index-1]
    #                    self.ui.comboBoxChannel.removeItem(index)
    #                    self.ui.comboBoxChannel.setCurrentIndex(index-1)
    #            self.plot_ps_thread.input(self.pulse_sequence, self.ui.mplwidgetPulseSeq)
        
    def changePulseTrainIndex(self):
        if self.currentChannel.num_of_pulse_trains > 0:
            new_index = self.ui.comboBoxPulseTrainIndex.currentIndex()
            
            self.currentPulseTrain = self.currentChannel.pulse_trains[new_index]
           
            self.ui.lineEditTimeOn.setText(str(self.currentChannel.pulse_trains[new_index].time_on))
            self.ui.lineEditPulseWidth.setText(str(self.currentChannel.pulse_trains[new_index].width))
            self.ui.lineEditPulseSeparation.setText(str(self.currentChannel.pulse_trains[new_index].separation))
            self.ui.lineEditPulsesInTrain.setText(str(self.currentChannel.pulse_trains[new_index].pulses_in_train))
        
    def EditPulseTrain(self):
        if self.currentChannel.num_of_pulse_trains > 0:
            pulse_train_index = self.ui.comboBoxPulseTrainIndex.currentIndex()
            self.currentChannel.pulse_trains[pulse_train_index] = PulseTrain(time_on = float(self.ui.lineEditTimeOn.text()), width = float(self.ui.lineEditPulseWidth.text()),
                                                separation = float(self.ui.lineEditPulseSeparation.text()), pulses_in_train = int(self.ui.lineEditPulsesInTrain.text())) 
                                                #pulse_train_index = self.currentPulseTrain.pulse_train_index)
            self.currentPulseTrain = self.currentChannel.pulse_trains[pulse_train_index]
            self.currentChannel.setLatestChannelEvent()
            self.pulse_sequence.setLatestSequenceEvent()
            self.currentChannel.setFirstChannelEvent()
            self.pulse_sequence.setFirstSequenceEvent()
            self.plot_sequence()
            
    def addPulseTrain(self):
        if self.ui.lineEditTimeOn.hasAcceptableInput() and self.ui.lineEditPulseWidth.hasAcceptableInput() and self.ui.lineEditPulseSeparation and self.ui.lineEditPulsesInTrain.hasAcceptableInput:
            self.currentChannel.addPulseTrain(float(self.ui.lineEditTimeOn.text()),
                                        float(self.ui.lineEditPulseWidth.text()),
                                        float(self.ui.lineEditPulseSeparation.text()),
                                        int(self.ui.lineEditPulsesInTrain.text()))
            self.currentPulseTrain = self.currentChannel.pulse_trains[self.currentChannel.num_of_pulse_trains-1]
            self.ui.comboBoxPulseTrainIndex.addItem(str(self.currentChannel.num_of_pulse_trains-1))
            self.ui.comboBoxPulseTrainIndex.setCurrentIndex(self.currentChannel.num_of_pulse_trains-1)
            self.currentChannel.setLatestChannelEvent()
            self.pulse_sequence.setLatestSequenceEvent()
            self.currentChannel.setFirstChannelEvent()
            self.pulse_sequence.setFirstSequenceEvent()
            self.plot_sequence()
            
    
    def deletePulseTrain(self):
        if self.pulse_sequence.num_of_channels > 0 and self.currentChannel.num_of_pulse_trains > 0:
            index = self.ui.comboBoxPulseTrainIndex.currentIndex()
            if (self.currentChannel.deletePulseTrain(index)):
                self.ui.comboBoxPulseTrainIndex.removeItem(self.currentChannel.num_of_pulse_trains)
                if index == 0:
                    self.ui.comboBoxPulseTrainIndex.setCurrentIndex(0)
                else:
                    self.ui.comboBoxPulseTrainIndex.setCurrentIndex(index-1)
                self.changePulseTrainIndex()
                self.currentChannel.setLatestChannelEvent()
                self.pulse_sequence.setLatestSequenceEvent()
                self.currentChannel.setFirstChannelEvent()
                self.pulse_sequence.setFirstSequenceEvent()
                self.plot_sequence()
                    
    

 
    def choose_load_file(self):
        self.ui.textEditLoadFile.setText(QFileDialog.getOpenFileName())
    def load_ps(self):
        file_name = self.ui.textEditLoadFile.toPlainText()
        self.load_ps_thread.input(file_name)
    def update_load_status(self, status):
        self.ui.textEditLoadStatus.setText(status)
    
    def initiate_loaded_ps(self, pulse_sequence):
        self.pulse_sequence = pulse_sequence
        channels = map(str, range(self.pulse_sequence.num_of_channels))
        self.ui.comboBoxChannel.clear()
        self.ui.comboBoxChannel.addItems(map(str, self.pulse_sequence.pulse_channel_indices))
        if self.pulse_sequence.num_of_wait_events > 0:
            self.ui.comboBoxWaitEvents.addItems(map(str, range(self.pulse_sequence.num_of_wait_events)))
            self.ui.lineEditWaitTime.setText(str(self.pulse_sequence.wait_events[0]))
        self.plot_ps_thread.input(self.pulse_sequence, self.ui.mplwidgetPulseSeq, float(self.ui.lineEditPBClockFrequency.text()))
        
    def choose_save_file(self):
        self.ui.textEditSaveFile.setText(QFileDialog.getSaveFileName()) 
    def save_ps(self):
        file_name = self.ui.textEditSaveFile.toPlainText()
        self.save_ps_thread.input(self.pulse_sequence, file_name)
    def update_save_status(self, status):
        self.ui.textEditSaveStatus.setText(status)

    def plot_sequence(self):
        self.plot_ps_thread.input(self.pulse_sequence, self.ui.mplwidgetPulseSeq, float(self.ui.lineEditPBClockFrequency.text()))

    def communicate_with_pb(self, command):
        self.communicate_with_pb_thread.input(self.pulse_sequence, command, 
                                                str(self.ui.lineEditPBClockFrequency.text()), self.ui.checkBoxInfiniteLoop.isChecked(),
                                                self.ui.doubleSpinBoxRunTime.value(), self.ui.spinBoxNumberOfLoops.value())
    def update_messages(self, message):
        self.ui.textEditMessages.append(message)