Exemple #1
0
 def __init__(self, sid, title, header, body, footer, formarts, columns,  parent=None):
     super(TableProfile, self).__init__(parent)
     #page setup
     self.setGeometry(100, 100, 700, 700)
     self.textStyle = "background-color: white; color:black; border: 3px ridge #ccc"
     self.minW = 670
     self.maxW = 700
     self.sid = sid
     self.header = header
     self.body = body
     self.footer = footer
     self.formarts = formarts
     self.title = title
     self.columns = [x + 1 for x in columns]
     self.hold = self.columns
     cn = Db()
     self.myterms = cn.getTermClass(self.sid)
     menu = self.menuUi()
     
     self.h1_box = QVBoxLayout()
     
     self.bioText = QTextEdit(self)
     self.bioText.setMinimumWidth(self.minW)
     self.bioText.setMinimumHeight(self.maxW)
     self.bioText.setMaximumHeight(self.maxW)
     btext = self.buildBio()
     self.bioText.insertHtml(btext)
     self.bioText.setStyleSheet(self.textStyle)
     self.h1_box.addWidget(self.bioText)
     self.h1_box.setSizeConstraint(QLayout.SetFixedSize)
     self.doc1 = self.bioText
     
     scrollArea = QScrollArea(self)
     scrollArea.setWidgetResizable(True)
     scrollArea.setFixedHeight(700)
     scrollArea.setFixedWidth(700)
     
     bioProfileWidget = QWidget()
     bioProfileWidget.setLayout(self.h1_box)
     #Main layout
     Hbox = QVBoxLayout()
     Hbox.addWidget(menu)
     Hbox.addStretch()
     Hbox.addWidget(bioProfileWidget)
     Hbox.setContentsMargins(0, 0, 0, 0)
    
     #Create central widget, add layout and set
     central_widget = QWidget(scrollArea)
     scrollArea.setWidget(central_widget)
     central_widget.setContentsMargins(0, 0, 0, 0)
     central_widget.setGeometry(0, 0, 650, 700)
     central_widget.setStyleSheet("background-color: #ccc; color:#000")
     central_widget.setLayout(Hbox)
    
     self.setWindowTitle(title)
     self.show()    
Exemple #2
0
    def _set_expander(self):
        """Set the expander widget."""
        self.ssl_text = QTextEdit()
        self.ssl_text.setText(self.details)
        scroll_area = QScrollArea()
        scroll_area.setViewport(self.ssl_text)
        scroll_area.setFixedHeight(50)

        self.expander = QExpander(SSL_CERT_DETAILS)
        self.expander.addWidget(scroll_area)
        self.ui.expander_layout.insertWidget(2, self.expander)
Exemple #3
0
def selectFile():
    global path
    path = QFileDialog.getOpenFileName()
    ui.fileUploadText.setText(path + ' uploaded.')

    file = open(path)

    counts = defaultdict(int)
    for line in file:

        list = line.split(',')
        counts[list[0]] += 1

    counts = OrderedDict(sorted(counts.items()))

    #Create the plot
    plot.bar(range(len(counts)), counts.values(), align='center')
    plot.xticks(range(len(counts)), counts.keys())

    fig = plot.gcf()
    fig.set_size_inches(24, 8)

    fig.suptitle('Age distribution', fontsize=18)
    plot.xlabel('Age', fontsize=18)
    plot.ylabel('Number of records', fontsize=18)

    fig.savefig(str(path) + 'plot.png', dpi=60)
    outputGraph = str(path) + 'plot.png'

    pixMap = QtGui.QPixmap(outputGraph)
    ui.inputDataLabel.setPixmap(pixMap)

    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.inputDataLabel)
    scrollArea.setFixedHeight(500)
    scrollArea.horizontalScrollBar().setValue(
        scrollArea.horizontalScrollBar().value() + 100)
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.uploadTab.setLayout(hLayout)
def selectFile():
    global path
    path = QFileDialog.getOpenFileName()
    ui.fileUploadText.setText(path + ' uploaded.')

    file = open(path)

    counts = defaultdict(int)
    for line in file:

        list = line.split(',')
        counts[list[0]] += 1

    counts = OrderedDict(sorted(counts.items()))

    #Create the plot
    plot.bar(range(len(counts)), counts.values(), align='center')
    plot.xticks(range(len(counts)), counts.keys())

    fig = plot.gcf()
    fig.set_size_inches(24, 8)

    fig.suptitle('Age distribution', fontsize=18)
    plot.xlabel('Age', fontsize=18)
    plot.ylabel('Number of records', fontsize=18)

    fig.savefig(str(path) + 'plot.png', dpi=60)
    outputGraph = str(path) + 'plot.png'

    pixMap = QtGui.QPixmap(outputGraph)
    ui.inputDataLabel.setPixmap(pixMap)
    
    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.inputDataLabel)
    scrollArea.setFixedHeight(500)
    scrollArea.horizontalScrollBar().setValue(scrollArea.horizontalScrollBar().value() + 100); 
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.uploadTab.setLayout(hLayout)
Exemple #5
0
def runDecisionTree():

    #Todo: try not to use global variables
    global path
    global alteredPath

    fileName = ''

    if (alteredPath):
        fileName = alteredPath
    elif (path):
        fileName = path
    else:
        print('Must upload file first')
        return

    x = []
    y = []

    file = open(fileName)
    for line in file:
        line = line.rstrip()
        features = []
        classification = []

        list = line.split(',')
        features = list[0:-1]
        if (features and features[0].strip()):
            x.append(features)

        classification = [list[-1]]
        if (classification and classification[0].strip()):
            y.append(classification)

    ui.progressBar.setValue(25)

    samples = [dict(enumerate(sample)) for sample in x]

    # turn list of dicts into a numpy array
    vect = DictVectorizer(sparse=False)
    x = vect.fit_transform(samples)
    ui.progressBar.setValue(50)

    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(x, y)

    with open(fileName + '.dot', 'w') as f:
        f = tree.export_graphviz(clf, out_file=f)
    graph = pydot.graph_from_dot_file(fileName + '.dot')
    graph.write_png(fileName + '.png')
    global outputGraph
    outputGraph = fileName + '.png'

    ui.progressBar.setValue(75)

    pixMap = QtGui.QPixmap(outputGraph)
    #ui.outputLabel.setPixmap(pixMap.scaled(ui.outputTab.size(), QtCore.Qt.KeepAspectRatio))
    ui.outputLabel.setPixmap(pixMap)
    #ui.outputLabel.setScaledContents(True)

    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.outputLabel)
    scrollArea.setFixedHeight(525)
    scrollArea.horizontalScrollBar().setValue(
        scrollArea.horizontalScrollBar().value() + 3400)
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.outputTab.setLayout(hLayout)

    ui.progressBar.setValue(100)

    ui.algorithmText.setText('Built decision tree')
def runDecisionTree():

    #Todo: try not to use global variables
    global path
    global alteredPath

    fileName = ''

    if (alteredPath):
        fileName = alteredPath
    elif (path):
        fileName = path
    else:
        print('Must upload file first')
        return

    x = []
    y = []

    file = open(fileName)
    for line in file:
        line = line.rstrip()
        features = []
        classification = []

        list = line.split(',')
        features = list[0:-1]
        if (features and features[0].strip()):
            x.append(features)

        classification = [list[-1]]
        if (classification and classification[0].strip()):
            y.append(classification)


    ui.progressBar.setValue(25)

    samples = [dict(enumerate(sample)) for sample in x]

    # turn list of dicts into a numpy array
    vect = DictVectorizer(sparse=False)
    x = vect.fit_transform(samples)
    ui.progressBar.setValue(50)

    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(x, y)

    
    with open(fileName + '.dot', 'w') as f:
        f = tree.export_graphviz(clf, out_file=f)
    graph = pydot.graph_from_dot_file(fileName + '.dot')
    graph.write_png(fileName + '.png')
    global outputGraph
    outputGraph = fileName + '.png'

    ui.progressBar.setValue(75)
    

    pixMap = QtGui.QPixmap(outputGraph)
    #ui.outputLabel.setPixmap(pixMap.scaled(ui.outputTab.size(), QtCore.Qt.KeepAspectRatio))
    ui.outputLabel.setPixmap(pixMap)
    #ui.outputLabel.setScaledContents(True)

    
    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.outputLabel)
    scrollArea.setFixedHeight(525)
    scrollArea.horizontalScrollBar().setValue(scrollArea.horizontalScrollBar().value() + 3400); 
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.outputTab.setLayout(hLayout)

    ui.progressBar.setValue(100)

    ui.algorithmText.setText('Built decision tree')
Exemple #7
0
    def init_UI(self):
        """Create all of the widget objects required"""
        layout = QVBoxLayout()
        self.setLayout(layout)

        # place scroll bars if the contents of the window are too large
        scroll = QScrollArea(self)
        layout.addWidget(scroll)
        scroll_content = QWidget(scroll)
        scroll.setWidgetResizable(True)
        scroll.setFixedHeight(800)
        self.grid = QGridLayout()
        scroll_content.setLayout(self.grid)

        #### validators for user input ####
        double_validator = QDoubleValidator()  # floats
        int_validator = QIntValidator(0, 10000000)  # positive integers
        msr_validator = QIntValidator(-1, 1000000)  # integers >= -1
        nat_validator = QIntValidator(1, 10000000)  # natural numbers
        col_validator = QIntValidator(1,
                                      self.ncols - 1)  # for number of columns

        #### table dimensions and ordering ####
        # choose the number of rows = number of multirun steps
        labels = ['# Omit', '# in Histogram', '# Columns', '# Rows']
        default = ['5', '100', str(self.ncols), str(self.nrows)]
        vldtr = [int_validator, nat_validator, nat_validator, nat_validator]
        self.omit_edit, self.nhist_edit, self.cols_edit, self.rows_edit = [
            self.make_label_edit(labels[i], self.grid, [0, 2 * i, 1, 1],
                                 default[i], vldtr[i])[1] for i in range(4)
        ]
        self.cols_edit.textChanged[str].connect(self.change_array_size)
        self.rows_edit.textChanged[str].connect(self.change_array_size)
        self.omit_edit.editingFinished.connect(self.update_repeats)
        self.nhist_edit.editingFinished.connect(self.update_repeats)

        # choose the order
        self.order_edit = QComboBox(self)
        self.order_edit.addItems(
            ['ascending', 'descending', 'random', 'coarse random', 'unsorted'])
        self.grid.addWidget(self.order_edit, 0, 8, 1, 1)

        #### create multirun list of values ####
        # metadata for the multirun list: which channels and timesteps
        self.measures = OrderedDict()
        labels = ['Variable label', 'measure', 'measure_prefix', '1st hist ID']
        defaults = ['Variable 0', '0', 'Measure0', '0']
        for i in range(len(labels)):
            label = QLabel(labels[i], self)
            self.grid.addWidget(label, i + 1, 0, 1, 1)
            self.measures[labels[i]] = QLineEdit(defaults[i], self)
            self.measures[labels[i]].textChanged.connect(self.update_all_stats)
            self.grid.addWidget(self.measures[labels[i]], i + 1, 1, 1, 3)
        self.measures['measure'].setValidator(int_validator)
        self.measures['1st hist ID'].setValidator(msr_validator)
        label.setText('1st ID (-1 to append)')  # change label

        self.chan_choices = OrderedDict()
        labels = [
            'Type', 'Time step name', 'Analogue type', 'Analogue channel'
        ]
        sht = self.tr.get_esc()[2][2:]  # 'Sequence header top'
        options = [
            [
                'Time step length', 'Analogue voltage', 'GPIB',
                'AWG1 chan : seg', 'AWG2 chan : seg', 'DDS1 port : profile',
                'DDS2 module : profile', 'SLM holograms', 'Other'
            ],
            list(
                map(str.__add__, [str(i) for i in range(len(sht))],
                    [': ' + hc[6][1].text for hc in sht])),  # time step names
            ['Fast analogue', 'Slow analogue'],
            self.get_anlg_chans('Fast')
        ]
        positions = [[1, 4, 3, 2], [1, 6, 6, 1], [1, 7, 3, 1], [1, 8, 6, 1]]
        widgets = [QComboBox, QListWidget]
        for i in range(0, len(labels)):
            self.chan_choices[labels[i]] = widgets[i % 2]()
            if i % 2:
                self.chan_choices[labels[i]].setSelectionMode(3)
            self.chan_choices[labels[i]].addItems(options[i])
            self.grid.addWidget(self.chan_choices[labels[i]], *positions[i])
        self.chan_choices['Type'].currentTextChanged[str].connect(
            self.change_mr_type)
        self.chan_choices['Analogue type'].currentTextChanged[str].connect(
            self.change_mr_anlg_type)
        self.chan_choices['Analogue channel'].setEnabled(False)

        # enter desired time step selection via python cmd
        self.index_slice = QLineEdit('range(0,1,2)', self)
        self.grid.addWidget(self.index_slice, 3, 4, 3, 2)
        self.apply_slice_btn = QPushButton('Apply range', self)
        self.grid.addWidget(self.apply_slice_btn, 4, 4, 3, 2)
        self.apply_slice_btn.clicked.connect(self.apply_slice)

        # AWG takes a list for some arguments, so needs an index
        label = QLabel('List index:', self)
        self.grid.addWidget(label, 3, 7, 3, 1)
        self.list_index = QLineEdit('0', self)
        self.grid.addWidget(self.list_index, 4, 7, 3, 1)
        self.list_index.setValidator(int_validator)
        self.list_index.textEdited[str].connect(self.save_chan_selection)

        # add a new list of multirun values to the array
        self.col_index = self.make_label_edit('column index:',
                                              self.grid,
                                              position=[5, 0, 1, 1],
                                              default_text='0',
                                              validator=col_validator)[1]
        self.col_range = QLineEdit('np.linspace(0,1,%s)' % (self.nrows), self)
        self.grid.addWidget(self.col_range, 5, 2, 1, 2)
        # show the previously selected channels for this column:
        self.chan_choices['Time step name'].itemClicked.connect(
            self.save_chan_selection)
        self.chan_choices['Analogue channel'].itemClicked.connect(
            self.save_chan_selection)
        self.col_range.editingFinished.connect(self.save_chan_selection)
        self.col_index.textChanged[str].connect(self.set_chan_listbox)

        # add the column to the multirun values array
        add_var_button = QPushButton('Add column', self)
        add_var_button.clicked.connect(self.add_column_to_array)
        add_var_button.resize(add_var_button.sizeHint())
        self.grid.addWidget(add_var_button, 6, 0, 1, 1)

        # clear the current list of user variables
        clear_vars_button = QPushButton('Clear', self)
        clear_vars_button.clicked.connect(self.clear_array)
        clear_vars_button.resize(clear_vars_button.sizeHint())
        self.grid.addWidget(clear_vars_button, 6, 1, 1, 1)

        # suggest new measure when multirun started
        self.suggest_button = QPushButton('Auto-increment measure',
                                          self,
                                          checkable=True,
                                          checked=True)
        self.suggest_button.resize(self.suggest_button.sizeHint())
        self.grid.addWidget(self.suggest_button, 6, 2, 1, 2)

        # choose last time step for multirun
        lts_label = QLabel('Last time step: ', self)
        self.grid.addWidget(lts_label, 7, 0, 1, 1)
        self.last_step_run_edit = self.make_label_edit('Running: ',
                                                       self.grid,
                                                       position=[7, 1, 1,
                                                                 3])[1]
        self.last_step_run_edit.setText(self.ui_param['Last time step run'])
        self.last_step_run_edit.textChanged[str].connect(self.update_last_step)
        self.last_step_end_edit = self.make_label_edit('End: ',
                                                       self.grid,
                                                       position=[7, 5, 1,
                                                                 3])[1]
        self.last_step_end_edit.setText(self.ui_param['Last time step end'])
        self.last_step_end_edit.textChanged[str].connect(self.update_last_step)

        # display current progress
        multirun_progress = QLabel(
            'User variable: , omit 0 of 0 files, 0 of 100 histogram files, 0% complete'
        )
        self.grid.addWidget(multirun_progress, 8, 0, 1, 12)
        reset_slot(self.progress, multirun_progress.setText, True)

        # table stores multirun values:
        self.table = QTableWidget(self.nrows, self.ncols)
        self.reset_array()
        self.grid.addWidget(self.table, 9, 0, 20, 12)

        scroll.setWidget(scroll_content)
    def __init__(self, sids, es, parent=None):
        super(StudentProfile, self).__init__(parent)

        red = 50 + es
        reds = 50 + es

        self.setGeometry(red, reds, 700, 700)
        self.textStyle = "background-color: white; color:black; border: 3px ridge #ccc"
        self.minW = 670
        self.maxW = 700

        self.sid = sids
        self.student = sids
        cn = Db()
        self.myterms = cn.getTermClass(self.sid)
        menu = self.menuUi()
        data = self.pullStudents(self.sid)

        fullnamex = data['surname'] + ' ' + data['firstname'] + ' ' + data[
            'othername']
        self.fullname = fullnamex.title()
        self.schno = str(data['schno']).upper()

        if data['gender'] == 0:
            self.gender = 'Male'
        elif data['gender'] == 1:
            self.gender = 'Female'
        else:
            self.gender = 'None Stated'

        now = datetime.datetime.today()

        dob = data['dob']
        dt = datetime.datetime.strptime(dob, '%d/%m/%Y').date()
        dt1 = now.date()
        diff = (dt1 - dt).days
        age1 = int(diff) / 365.25
        agey = round(int(diff) / 365.25, 0)
        agem = age1 - agey
        months = round(agem * 12)
        self.dob = "{:%d, %b %Y}".format(dt)
        self.age = str(math.floor(agey)) + ' yrs ' + str(
            math.floor(months)) + ' months '

        admit = data['admit']
        dt2 = datetime.datetime.strptime(admit, '%d/%m/%Y').date()
        dt3 = now.date()
        diff1 = (dt3 - dt2).days
        admit1 = int(diff1) / 365.25
        admity = round(int(diff1) / 365.25, 0)
        admitm = admit1 - admity
        amonths = round(admitm * 12)
        self.admit = "{:%d, %b %Y}".format(dt2)
        self.admit_dur = str(math.floor(admity)) + ' yrs ' + str(
            math.floor(amonths)) + ' months '

        self.data = data

        self.h1_box = QVBoxLayout()
        self.h2_box = QVBoxLayout()
        self.h3_box = QVBoxLayout()
        self.h4_box = QVBoxLayout()
        self.h5_box = QVBoxLayout()

        self.profileStack = QStackedWidget()

        bioText = QTextEdit(self)
        bioText.setMinimumWidth(self.minW)
        bioText.setMinimumHeight(self.maxW)
        bioText.setMaximumHeight(self.maxW)
        btext = self.buildBio()
        bioText.insertHtml(btext)
        bioText.setStyleSheet(self.textStyle)
        self.profileStack.setCurrentIndex(0)
        self.h1_box.addWidget(bioText)
        self.h1_box.setSizeConstraint(QLayout.SetFixedSize)
        self.doc1 = bioText

        self.academicText = QTextEdit()
        self.academicText.setMinimumWidth(self.minW)
        self.academicText.setMinimumHeight(self.maxW)
        self.academicText.setMaximumHeight(self.maxW)
        actext = self.buildBio()
        self.academicText.insertHtml(actext)
        self.academicText.setStyleSheet(self.textStyle)
        self.h2_box.addWidget(self.academicText)
        self.h2_box.setSizeConstraint(QLayout.SetFixedSize)
        self.doc2 = self.academicText

        self.affectiveText = QTextEdit()
        self.affectiveText.setMinimumWidth(self.minW)
        self.affectiveText.setMinimumHeight(self.maxW)
        self.affectiveText.setMaximumHeight(self.maxW)
        aftext = self.buildBio()
        self.affectiveText.insertHtml(aftext)
        self.affectiveText.setStyleSheet(self.textStyle)
        self.h3_box.addWidget(self.affectiveText)
        self.h3_box.setSizeConstraint(QLayout.SetFixedSize)
        self.doc3 = self.affectiveText

        self.psychomotorText = QTextEdit()
        self.psychomotorText.setMinimumWidth(self.minW)
        self.psychomotorText.setMinimumHeight(self.maxW)
        self.psychomotorText.setMaximumHeight(self.maxW)
        pstext = self.buildBio()
        self.psychomotorText.insertHtml(pstext)
        self.psychomotorText.setStyleSheet(self.textStyle)
        self.h4_box.addWidget(self.psychomotorText)
        self.h4_box.setSizeConstraint(QLayout.SetFixedSize)
        self.doc4 = self.psychomotorText

        self.feeText = QTextEdit()
        self.feeText.setMinimumWidth(self.minW)
        self.feeText.setMinimumHeight(self.maxW)
        self.feeText.setMaximumHeight(self.maxW)
        fetext = self.buildBio()
        self.feeText.insertHtml(fetext)
        self.feeText.setStyleSheet(self.textStyle)
        self.h5_box.addWidget(self.feeText)
        self.h5_box.setSizeConstraint(QLayout.SetFixedSize)
        self.doc5 = self.feeText

        scrollArea = QScrollArea(self)
        scrollArea.setWidgetResizable(True)
        scrollArea.setFixedHeight(700)
        scrollArea.setFixedWidth(700)

        bioProfileWidget = QWidget()
        academicProfileWidget = QWidget()
        affectiveProfileWidget = QWidget()
        psychomotorProfileWidget = QWidget()
        feeProfileWidget = QWidget()

        self.profileStack.addWidget(bioProfileWidget)
        self.profileStack.addWidget(academicProfileWidget)
        self.profileStack.addWidget(affectiveProfileWidget)
        self.profileStack.addWidget(psychomotorProfileWidget)
        self.profileStack.addWidget(feeProfileWidget)

        bioProfileWidget.setLayout(self.h1_box)
        academicProfileWidget.setLayout(self.h2_box)
        affectiveProfileWidget.setLayout(self.h3_box)
        psychomotorProfileWidget.setLayout(self.h4_box)
        feeProfileWidget.setLayout(self.h5_box)
        #Main layout
        Hbox = QVBoxLayout()
        Hbox.addWidget(menu)
        Hbox.addStretch()
        Hbox.addWidget(self.profileStack)
        Hbox.setContentsMargins(0, 0, 0, 0)

        #Create central widget, add layout and set
        central_widget = QWidget(scrollArea)
        scrollArea.setWidget(central_widget)
        central_widget.setContentsMargins(0, 0, 0, 0)
        central_widget.setGeometry(0, 0, 650, 700)
        central_widget.setStyleSheet("background-color: #ccc; color:#000")
        central_widget.setLayout(Hbox)

        self.setWindowTitle(fullnamex.title())
        self.show()
Exemple #9
0
    def init_UI(self):
        """Create all of the widget objects required"""
        self.centre_widget = QWidget()
        self.tabs = QTabWidget()  # make tabs for each main display
        self.centre_widget.layout = QVBoxLayout()
        self.centre_widget.layout.addWidget(self.tabs)
        self.centre_widget.setLayout(self.centre_widget.layout)
        self.setCentralWidget(self.centre_widget)

        num_e = len(self.tr.seq_dic['Event list array in'])
        num_s = len(self.tr.seq_dic['Experimental sequence cluster in']
                    ['Sequence header top'])
        menubar = self.menuBar()

        # save/load a sequence file
        menubar.clear(
        )  # prevents recreating menubar if init_UI() is called again
        seq_menu = menubar.addMenu('Sequence')
        load = QAction('Load Sequence', self)
        load.triggered.connect(self.load_seq_from_file)
        seq_menu.addAction(load)
        save = QAction('Save Sequence', self)
        save.triggered.connect(self.save_seq_file)
        seq_menu.addAction(save)

        #### tab for previewing sequences ####
        preview_tab = QWidget()
        prv_layout = QVBoxLayout()
        preview_tab.setLayout(prv_layout)
        scroll_widget = QWidget()
        prv_layout.addWidget(scroll_widget)
        prv_vbox = QVBoxLayout()
        scroll_widget.setLayout(prv_vbox)
        self.tabs.addTab(preview_tab, "Sequence")

        # position the widgets on the layout:
        # metadata
        self.routine_name = QLabel('', self)
        self.routine_desc = QLabel('', self)
        for label, name in [[self.routine_name, 'Routine name: '],
                            [self.routine_desc, 'Routine description: ']]:
            layout = QHBoxLayout()
            title = QLabel(name, self)
            title.setFixedWidth(200)
            layout.addWidget(title)
            label.setStyleSheet('border: 1px solid black')
            label.setFixedWidth(400)
            layout.addWidget(label)
            prv_vbox.addLayout(layout)

        # list of event descriptions
        self.e_list = QTableWidget(4, num_e)
        self.e_list.setVerticalHeaderLabels([
            'Event name: ', 'Routine specific event? ', 'Event indices: ',
            'Event path: '
        ])
        self.e_list.setFixedHeight(150)
        self.reset_table(self.e_list, 0)
        prv_vbox.addWidget(self.e_list)

        # event header top
        self.head_top = QTableWidget(14, num_s)
        self.head_top.setVerticalHeaderLabels([
            'Skip Step: ', 'Event name: ', 'Hide event steps: ', 'Event ID: ',
            'Time step name: ', 'Populate multirun: ', 'Time step length: ',
            'Time unit: ', 'D/A trigger: ', 'Trigger this time step? ',
            'Channel: ', 'Analogue voltage (V): ', 'GPIB event name: ',
            'GPIB on/off? '
        ])
        self.head_top.setFixedHeight(450)
        self.reset_table(self.head_top, 0)
        prv_vbox.addWidget(self.head_top)

        # fast digital channels
        fd_head = QLabel('Fast Digital', self)
        prv_vbox.addWidget(fd_head)

        self.fd_chans = QTableWidget(self.tr.nfd, num_s)
        self.fd_chans.setFixedHeight(400)
        self.reset_table(self.fd_chans, 1)
        prv_vbox.addWidget(self.fd_chans)

        # fast analogue channels
        fa_head = QLabel('Fast Analogue', self)
        prv_vbox.addWidget(fa_head)
        self.fa_chans = QTableWidget(self.tr.nfa, num_s * 2)
        self.fa_chans.setFixedHeight(260)
        self.reset_table(self.fa_chans, 0)
        prv_vbox.addWidget(self.fa_chans)

        # event header middle
        self.head_mid = QTableWidget(14, num_s)
        self.head_mid.setVerticalHeaderLabels([
            'Skip Step: ', 'Event name: ', 'Hide event steps: ', 'Event ID: ',
            'Time step name: ', 'Populate multirun: ', 'Time step length: ',
            'Time unit: ', 'D/A trigger: ', 'Trigger this time step? ',
            'Channel: ', 'Analogue voltage (V): ', 'GPIB event name: ',
            'GPIB on/off? '
        ])
        self.head_mid.setFixedHeight(450)
        self.reset_table(self.head_mid, 0)
        prv_vbox.addWidget(self.head_mid)

        # slow digital channels
        sd_head = QLabel('Slow Digital', self)
        prv_vbox.addWidget(sd_head)

        self.sd_chans = QTableWidget(self.tr.nsd, num_s)
        self.sd_chans.setFixedHeight(400)
        self.reset_table(self.sd_chans, 1)
        prv_vbox.addWidget(self.sd_chans)

        # slow analogue channels
        sa_head = QLabel('Slow Analogue', self)
        prv_vbox.addWidget(sa_head)

        self.sa_chans = QTableWidget(self.tr.nsa, num_s * 2)
        self.sa_chans.setFixedHeight(400)
        self.reset_table(self.sa_chans, 0)
        prv_vbox.addWidget(self.sa_chans)

        # place scroll bars if the contents of the window are too large
        scroll = QScrollArea(self)
        scroll.setWidget(scroll_widget)
        scroll.setWidgetResizable(True)
        scroll.setFixedHeight(800)
        prv_layout.addWidget(scroll)

        #### tab for multi-run settings ####
        self.mr = multirun_widget(self.tr)
        self.tabs.addTab(self.mr, "Multirun")

        mr_menu = menubar.addMenu('Multirun')
        mrload = QAction('Load Parameters', self)
        mrload.triggered.connect(self.mr.load_mr_params)
        mr_menu.addAction(mrload)
        mrsave = QAction('Save Parameters', self)
        mrsave.triggered.connect(self.mr.save_mr_params)
        mr_menu.addAction(mrsave)
        mrqueue = QAction('View Queue', self)
        mrqueue.triggered.connect(self.mr.view_mr_queue)
        mr_menu.addAction(mrqueue)

        # choose main window position and dimensions: (xpos,ypos,width,height)
        self.setWindowTitle('Multirun Editor and Sequence Preview')
        self.setWindowIcon(QIcon('docs/previewicon.png'))