drltools.py 18 KB
Newer Older
Yan's avatar
Yan committed
1
2
3
4
5
#!/usr/bin/env python3
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5 import QtCore
from PyQt5 import QtWidgets
6
from PyQt5 import QtGui
Yan's avatar
Yan committed
7
from PyQt5 import QtPrintSupport
Yan's avatar
Yan committed
8
9
import matplotlib
import numpy as np
Yan's avatar
Yan committed
10
11
import prasopes.datatools as dt
import prasopes.graphtools as gt
Yan's avatar
Yan committed
12
import prasopes.filetools as ft
Yan's avatar
Yan committed
13
14
matplotlib.use("Qt5Agg")

Yan's avatar
Yan committed
15

Yan's avatar
Yan committed
16
class HBar(QtWidgets.QFrame):
17
    """horizontal bar class"""
Yan's avatar
Yan committed
18
19
20
21
22
23
    def __init__(self):
        super(HBar, self).__init__()
        self._main = QtWidgets.QWidget()
        self.setFrameShape(QtWidgets.QFrame.HLine)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def floatize(table, row, column):
    """grabs the tableWidgetItem and transforms its text safely to
    float, if the text is not acceptable as float, returns zero"""
    imptext = table.item(row, column).text()
    validator = QtGui.QDoubleValidator()
    validator.setBottom(0)
    status = validator.validate(imptext, 0)[0]
    if status == QtGui.QValidator.Acceptable:
        outfloat = float(imptext)
    else:
        outfloat = 0
    return outfloat


def update_profile(pt, row, dataset):
39
    """spectrum updating procedure"""
Yan's avatar
Yan committed
40
41
    # Dont do anything to graph when the spectrum is not populated
    if isinstance(dataset['masses'], type(None)):
42
43
        return

44
45
46
    start = floatize(pt, row, 1)
    end = floatize(pt, row, 2)
    spectrum = pt.cellWidget(row, 3).figure.get_axes()[0]
Yan's avatar
Yan committed
47
48
    masses = dataset['masses']
    massargs = dt.argsubselect(masses, start, end)
49
    yshape = np.mean(dataset['matrix'], axis=0)
Yan's avatar
Yan committed
50
51
    spectrum.clear()
    dots_x = masses
52
    dots_y = yshape
Yan's avatar
Yan committed
53
54
    full_x = masses[massargs]
    full_y = yshape[massargs]
55
56
    spectrum.plot(dots_x, dots_y, ':', color='gray')
    spectrum.plot(full_x, full_y, 'r')
Yan's avatar
Yan committed
57
58
59
60
    xex = (masses[massargs[-1]]-masses[massargs[0]])*0.25
    spectrum.set_xlim(masses[massargs[0]]-xex,
                      masses[massargs[-1]]+xex)
    ymax = max(yshape[massargs])
61
62
63
    spectrum.set_ylim(ymax*-0.1, ymax*1.2)
    spectrum.figure.canvas.draw()

Yan's avatar
Yan committed
64

Yan's avatar
Yan committed
65
def get_daughterset(ptable, dtable, ds):
66
    # TODO: write a less resources demanding function
Yan's avatar
Yan committed
67
    names = []
Yan's avatar
Yan committed
68
    times = ds['chrom_dat'][0, :]
Yan's avatar
Yan committed
69
    intensities = []
Yan's avatar
Yan committed
70
    # TODO: resolve intensities trouble
Yan's avatar
Yan committed
71
    for row in range(dtable.rowCount()):
Yan's avatar
Yan committed
72
        if dtable.cellWidget(row, 0).checkState() == 2:
73
74
            startm = floatize(ptable, row, 1)
            endm = floatize(ptable, row, 2)
Yan's avatar
Yan committed
75
76
77
            massargs = dt.argsubselect(ds['masses'], startm, endm)
            intensity = (np.sum(
                ds['matrix'].T[massargs].T, axis=1)) / ds['chrom_dat'][1]
78
79
            cor = dtable.cellWidget(row, 1).currentIndex() - 1
            # TODO: check if cor still produce the mess or it started to behave
80
            if cor not in (-2, -1):
81
82
83
                factor = floatize(dtable, row, 2)
                startm = floatize(ptable, cor, 1)
                endm = floatize(ptable, cor, 2)
Yan's avatar
Yan committed
84
                massargs = dt.argsubselect(ds['masses'], startm, endm)
Yan's avatar
Yan committed
85
                correction = ((np.sum(
Yan's avatar
Yan committed
86
                    ds['matrix'].T[massargs].T, axis=1))
Yan's avatar
Yan committed
87
88
                              / ds['chrom_dat'][1]) * factor
                intensity = intensity - correction
Yan's avatar
Yan committed
89
            intensities.append(intensity)
Yan's avatar
Yan committed
90
91
92
93
            names.append("{} - {} * {}".format(
                dtable.item(row, 0).text(),
                dtable.item(row,2).text(),
                dtable.cellWidget(row,1).currentText()))
Yan's avatar
Yan committed
94
95
96
97
    return names, times, intensities


def update_drlspectrum(ptable, dtable, ds, drlspectrum):
98
    # Dont do anything when the dataset is not populated
Yan's avatar
Yan committed
99
    if isinstance(ds['masses'], type(None)):
Yan's avatar
Yan committed
100
        return
101
    colors = np.array([[0, 0, 0], [255, 0, 0], [0, 255, 0], [0, 0, 255],
102
103
104
                       [0, 200, 255], [255, 200, 0], [255, 100, 0],
                       [200, 50, 0], [255, 0, 200], [0, 100, 0],
                       [0, 100, 255], [100, 100, 100]])
Yan's avatar
Yan committed
105

106
    # TODO: write a less resources demanding function
Yan's avatar
Yan committed
107
108
109
    names, times, intensities = get_daughterset(ptable, dtable, ds)
    for i in range(len(drlspectrum.lines)):
        drlspectrum.lines[0].remove()
110

111
    i = 0
112
    for row in range(dtable.rowCount()):
Yan's avatar
Yan committed
113
        if dtable.cellWidget(row, 0).checkState() == 2:
114
            dtable.blockSignals(True)
Yan's avatar
Yan committed
115
            dtable.item(row, 0).setBackground(QtGui.QBrush(
116
                QtGui.QColor(*colors[row % len(colors)], alpha=50)))
117
118
            dtable.blockSignals(False)
            label = " {}".format(ptable.item(row, 0).text())
119
120
121
            drlspectrum.plot(times, intensities[i], label=label,
                             color=(colors[row % len(colors)] / 255))
            i += 1
122
        else:
Yan's avatar
Yan committed
123
            dtable.item(row, 0).setBackground(QtGui.QBrush())
124

125
126
127
128
    if len(names) != 0:
        drlspectrum.set_ylim(top=np.amax(intensities)*1.1,
                             bottom=np.amax(intensities)*-0.01)
        drlspectrum.legend(loc=2)
129
130
    drlspectrum.figure.canvas.draw()

Yan's avatar
Yan committed
131

Yan's avatar
Yan committed
132
def gettableitemlist(ptable):
133
    ion_list = []
Yan's avatar
Yan committed
134
135
136
    for row in range(ptable.rowCount()):
        text = []
        for i in range(3):
137
138
            if not isinstance(ptable.item(row, i), type(None)):
                frg = ptable.item(row, i).text()
Yan's avatar
Yan committed
139
140
141
142
143
            else:
                frg = ""
            text.append(frg)
        line = "{} ({}-{})".format(*text)
        ion_list.append(line)
144
145
146
    return ion_list


147
148
149
150
151
152
153
154
155
156
157
158
def update_corrfors(ptable, dtable):
    """update corrections selection layout of the daughter table"""
    ionlist = gettableitemlist(ptable)
    for row in range(dtable.rowCount()):
        corfor = dtable.cellWidget(row, 1)
        index = corfor.currentIndex()
        corfor.blockSignals(True)
        corfor.clear()
        corfor.addItem("")
        corfor.addItems(ionlist)
        corfor.setCurrentIndex(index)
        corfor.blockSignals(False)
Yan's avatar
Yan committed
159

160

Yan's avatar
Yan committed
161
162
def ptable_changed(row, column, ptable, dtable, ds, drlspectrum,
                   addline=True):
163
164
165
166
167
    """routine called by change of the ptable spectra"""
    update_corrfors(ptable, dtable)
    dtable.item(row, 0).setText(gettableitemlist(ptable)[row])
    if column in (1, 2):
        update_profile(ptable, row, ds)
Yan's avatar
Yan committed
168
169
    if row == ptable.rowCount() - 1 and addline == True:
        add_line(ds, ptable, dtable, drlspectrum)
170

171

172
173
174
175
176
177
178
def dtable_changed(row, column, ptable, dtable, ds, drlspectrum):
    """routine called by change of the dtable spectra"""
    if dtable.cellWidget(row, 0).checkState() == 2:
        if (column == 0)\
           or (column == 2
               and dtable.cellWidget(row, 1).currentIndex() != 0):
                update_drlspectrum(ptable, dtable, ds, drlspectrum)
179

Yan's avatar
Yan committed
180

181
182
183
184
185
def corr_changed(row, ptable, dtable, ds, drlspectrum):
    """routine called by change of correction for ion"""
    if (dtable.cellWidget(row, 0).checkState() == 2
       and floatize(dtable, row, 2) != 0):
        update_drlspectrum(ptable, dtable, ds, drlspectrum)
186
187


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
def delete_row(row, ptable, dtable, ds, drlspectrum):
    dtable.cellWidget(row,0).setCheckState(0)
    dtable.removeRow(row)
    ptable.removeRow(row)
    for i in range(dtable.rowCount()):
        corfor = dtable.cellWidget(i, 1)
        corfor.disconnect()
        index = corfor.currentIndex()
        corfor.clear()
        corfor.addItem("")
        corfor.addItems(gettableitemlist(ptable))
        if index == row+1:
            corfor.setCurrentIndex(0)
            corr_changed(i, ptable, dtable, ds, drlspectrum)
        elif index > row+1:
            corfor.setCurrentIndex(index-1)
        else:
            corfor.setCurrentIndex(index)
        corfor.currentIndexChanged.connect(lambda: corr_changed(
            i, ptable, dtable, ds, drlspectrum))


210
def remove_rows(ptable, dtable, ds, drlspectrum):
Yan's avatar
Yan committed
211
    # TODO: maybe nicer selection in future, but this works for now
212
    rows = reversed(list(set(
Yan's avatar
Yan committed
213
        map(lambda x: x.row(), ptable.selectedIndexes()))))
214
    for row in rows:
215
        delete_row(row, ptable, dtable, ds, drlspectrum)
216
217


Yan's avatar
Yan committed
218
def add_line(ds, parenttable, daughtertable, drlspectrum):
219
    """add parent ion to the table"""
220
221
222
223
224
225
226
227
228
229
230
231
    newrow = parenttable.rowCount()

    parenttable.blockSignals(True)
    daughtertable.blockSignals(True)

    parenttable.setRowCount(newrow + 1)
    for i in range(3):
        parenttable.setItem(newrow, i, QtWidgets.QTableWidgetItem())
        if newrow is not 0:
            parenttable.item(newrow, i).setText(str(floatize(
                    parenttable, newrow-1, i)+1))

232
    ion_graph = Figure(figsize=(3, 1.5), dpi=100, facecolor="None")
233
234
    ion_graph.add_subplot(111, facecolor=(1, 1, 1, 0.8),
                          position=(-0.01, -0.01, 1.02, 1.02))
235
236
237
238
    graph_canvas = FigureCanvas(ion_graph)
    graph_canvas.setStyleSheet("background-color:transparent;")
    graph_canvas.setAutoFillBackground(False)
    parenttable.setCellWidget(newrow, 3, graph_canvas)
239

240
    daughtertable.setRowCount(newrow + 1)
Yan's avatar
Yan committed
241
    checkbox = QtWidgets.QCheckBox()
242
243
    dname = QtWidgets.QTableWidgetItem()
    dname.setFlags(dname.flags() & ~QtCore.Qt.ItemIsEditable)
Yan's avatar
Yan committed
244
    dname.setTextAlignment(QtCore.Qt.AlignRight)
Yan's avatar
Yan committed
245
246
    daughtertable.setItem(newrow, 0, dname)
    daughtertable.setCellWidget(newrow, 0, checkbox)
247
248
249
250
251
252
253
254
    corfor = QtWidgets.QComboBox()
    corfor.setFrame(False)
    daughtertable.setCellWidget(newrow, 1, corfor)
    daughtertable.setItem(newrow, 2, QtWidgets.QTableWidgetItem())

    parenttable.blockSignals(False)
    daughtertable.blockSignals(False)

Yan's avatar
Yan committed
255
256
    ptable_changed(newrow, 1, parenttable, daughtertable, ds,
                   drlspectrum, False)
257

Yan's avatar
Yan committed
258
259
    checkbox.stateChanged.connect(lambda: update_drlspectrum(
        parenttable, daughtertable, ds, drlspectrum))
260
261
    corfor.currentIndexChanged.connect(lambda: corr_changed(
        newrow, parenttable, daughtertable, ds, drlspectrum))
262
263


Yan's avatar
Yan committed
264
def iontable(labels):
265
266
    """creates a table for ions"""
    table = QtWidgets.QTableWidget(columnCount=len(labels))
267
    table.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
268
269
                        QtWidgets.QSizePolicy.Expanding)
    table.setHorizontalHeaderLabels(labels)
270
271
272
273
274
    table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)

    for n in range(table.columnCount()):
        table.horizontalHeader().setSectionResizeMode(
            n, QtWidgets.QHeaderView.Stretch)
Yan's avatar
Yan committed
275
    table.setMinimumSize(600, 0)
276

277
    return table
278
279


Yan's avatar
Yan committed
280
281
282
283
284
285
286
287
288
289
290
291
292
293
def load_drltables(parent, ptable, dtable, dataset, drlspectrum):
    filename = QtWidgets.QFileDialog.getOpenFileName(
            caption="Load DRL config tables",
            filter="comma-separated values (*.csv)")[0]
    if filename is not '':
        names = []
        start_masses = []
        end_masses = []
        states = []
        corrected_to = []
        corr_factors = []

        with open(filename, 'r') as cfile:
            rawdata = cfile.read().splitlines()
Yan's avatar
Yan committed
294
295
        for i in range(1, len(rawdata)):
            rawline = rawdata[i].split(",")
Yan's avatar
Yan committed
296
297
298
299
300
301
302
303
            if len(rawline) != 6 or int(rawline[3]) not in range(3) \
                    or int(rawline[4]) not in range(len(rawdata)):
                QtWidgets.QMessageBox.warning(
                    parent, "Load DRL config tables",
                    "Config file corrupted on line {},"
                    " cancelling request".format(i+1))
                return
            for j, k in enumerate((names, start_masses, end_masses,
Yan's avatar
Yan committed
304
                                   states, corrected_to, corr_factors)):
Yan's avatar
Yan committed
305
                k.append(rawline[j])
Yan's avatar
Yan committed
306
307
308
        for row in reversed(range(ptable.rowCount())):
            dtable.removeRow(row)
            ptable.removeRow(row)
Yan's avatar
Yan committed
309
        # first populate only parent table
Yan's avatar
Yan committed
310
        for i in range(len(names)):
Yan's avatar
Yan committed
311
            add_line(dataset, ptable, dtable, drlspectrum)
312
313
314
            ptable.item(i, 0).setText(names[i])
            ptable.item(i, 1).setText(start_masses[i])
            ptable.item(i, 2).setText(end_masses[i])
Yan's avatar
Yan committed
315
        # and after that daughter table
Yan's avatar
Yan committed
316
        for i in range(len(names)):
Yan's avatar
Yan committed
317
            dtable.cellWidget(i, 1).setCurrentIndex(
Yan's avatar
Yan committed
318
                int(corrected_to[i]))
319
            dtable.item(i, 2).setText(corr_factors[i])
Yan's avatar
Yan committed
320
            dtable.cellWidget(i, 0).setCheckState(int(states[i]))
Yan's avatar
Yan committed
321
322


Yan's avatar
Yan committed
323
324
325
326
327
328
329
330
331
332
333
334
def save_drlconfig(ptable, dtable, parent):
    """safe DRL table layout so it can be summoned when needed"""
    exp_f_name = ft.get_save_filename(
        "Save DRL table layout", "comma-separated values (*.csv)",
        "csv", parent)
    if exp_f_name is not '':
        expf = open(exp_f_name, 'w')
        expf.write("#ion_name, start m/z, end m/z, visible,"
                   "corrected_to, factor\n")
        for row in range(ptable.rowCount()):
            vals = []
            for i in range(3):
335
                vals.append(ptable.item(row, i).text())
Yan's avatar
Yan committed
336
337
            vals.append(dtable.cellWidget(row, 0).checkState())
            vals.append(dtable.cellWidget(row, 1).currentIndex())
338
            vals.append(dtable.item(row, 2).text())
Yan's avatar
Yan committed
339
340
341
            expf.write("{}\n".format((",".join(map(str, vals)))))
        expf.close()

Yan's avatar
Yan committed
342

Yan's avatar
Yan committed
343
344
345
346
347
348
349
350
351
352
353
354
355
def export_drlspectrum(parent, fn, ptable, dtable, ds):
    if fn[0] is None:
        QtWidgets.QMessageBox.warning(
            main_window, "Export DRL dataset",
            "Nothing to export, cancelling request")
        return
    names, times, intensities = get_daughterset(ptable, dtable, ds)
    exp_f_name = ft.get_save_filename(
        "Export DRL data", "comma-separated values (*.csv)", "csv", parent)
    if exp_f_name is not '':
        expf = open(exp_f_name, 'w')
        expf.write("times, {}\n".format((",".join(names))))
        for i in range(len(times)):
Yan's avatar
Yan committed
356
            dataset = list()
Yan's avatar
Yan committed
357
358
359
360
361
362
            dataset.append(times[i])
            for intensity in intensities:
                dataset.append(intensity[i])
            expf.write("{}\n".format((",".join(map(str, dataset)))))
        expf.close()

Yan's avatar
Yan committed
363

Yan's avatar
Yan committed
364
def print_graph(labels, ptable, dtable, ds):
Yan's avatar
Yan committed
365
    printfig = Figure(figsize=(5, 2), dpi=100)
Yan's avatar
Yan committed
366
367
368
369
    printplot = printfig.add_subplot(111)
    printcanvas = FigureCanvas(printfig)
    gt.pop_plot(printplot, labels)
    update_drlspectrum(ptable, dtable, ds, printplot)
Yan's avatar
Yan committed
370
    widget = QtWidgets.QDialog(None, windowTitle='Print preview')
Yan's avatar
Yan committed
371
372
    layout = QtWidgets.QVBoxLayout(widget)
    layout.addWidget(printcanvas)
Yan's avatar
Yan committed
373
    widget.resize(600, 400)
Yan's avatar
Yan committed
374
375
376
377
378
379
380
    widget.show()
    dialog = QtPrintSupport.QPrintDialog()
    if dialog.exec_() == QtWidgets.QDialog.Accepted:
        printcanvas.render(dialog.printer())
    widget.close()


381
382
383
384
385
386
387
def key_pressed(event, ptable, dtable, ds, drlspectrum):
    if event.key() == QtCore.Qt.Key_Delete:
        for row in map(lambda x: x.row(),
                       ptable.selectionModel().selectedRows()):
            delete_row(row, ptable, dtable, ds, drlspectrum)


Yan's avatar
Yan committed
388
def main_window(parent, ds, filename, cache):
389
    """constructs a dialog window"""
Yan's avatar
Yan committed
390
391
    def saveonclose(widget, event, buffer, ptable, dautable, canvas):
        buffer[0], buffer[1], buffer[2] = ptable, dautable, canvas
Yan's avatar
Yan committed
392
        QtWidgets.QMainWindow.closeEvent(widget, event)
Yan's avatar
Yan committed
393

Yan's avatar
Yan committed
394
    window = QtWidgets.QMainWindow(
Yan's avatar
Yan committed
395
        parent, windowTitle='Delayed reactant labelling')
Yan's avatar
Yan committed
396
397
    main_widget = QtWidgets.QWidget(window)
    window.setCentralWidget(main_widget)
Yan's avatar
Yan committed
398

Yan's avatar
Yan committed
399
    window.closeEvent = lambda event: saveonclose(
Yan's avatar
Yan committed
400
        window, event, cache, pt, dtable, graph_canvas)
Yan's avatar
Yan committed
401

Yan's avatar
Yan committed
402
403
    dial_graph = Figure(figsize=(5, 2), dpi=100, facecolor="None")
    chromplot = dial_graph.add_subplot(111, facecolor=(1, 1, 1, 0.8))
Yan's avatar
Yan committed
404
405
406
    graph_canvas = FigureCanvas(dial_graph)
    graph_canvas.setStyleSheet("background-color:transparent;")
    graph_canvas.setAutoFillBackground(False)
Yan's avatar
Yan committed
407
    graphlabels = dict(x=[0], y=[0], line=None, name="",
Yan's avatar
Yan committed
408
409
                       xlabel="time(min)",
                       ylabel="relative intensity")
Yan's avatar
Yan committed
410
411
412
413
    gt.pan_factory(chromplot)
    gt.zoom_factory(chromplot, 1.15)
    gt.pop_plot(chromplot, graphlabels)

414
415
416
    drl_load = QtWidgets.QPushButton("&Load")
    drl_save = QtWidgets.QPushButton("&Save")
    drl_export = QtWidgets.QPushButton("&Export")
Yan's avatar
Yan committed
417
    drl_print = QtWidgets.QPushButton("&Print")
418
    close = QtWidgets.QPushButton("&Close")
Yan's avatar
Yan committed
419
    close.clicked.connect(window.close)
420

Yan's avatar
Yan committed
421
422
423
    btn_add = QtWidgets.QPushButton("&Add")
    btn_rem = QtWidgets.QPushButton("Remove")

424
425
    # pt = parenttable
    # dt = daughtertable
Yan's avatar
Yan committed
426
    if cache == [None, None, None]:
Yan's avatar
Yan committed
427
        dtable = iontable(["Name", "corrected for", "factor"])
428

Yan's avatar
Yan committed
429
        pt = iontable(["Name", "start (m/z)", "end (m/z)", "profile"])
Yan's avatar
Yan committed
430
        add_line(ds, pt, dtable, chromplot)
Yan's avatar
Yan committed
431
432
    else:
        pt = cache[0]
Yan's avatar
Yan committed
433
        dtable = cache[1]
Yan's avatar
Yan committed
434
        graph_canvas = cache[2]
435

436
437
438
    window.keyPressEvent = lambda event: key_pressed(
        event, pt, dtable, ds, chromplot)

439
    btn_add.clicked.connect(lambda: add_line(
Yan's avatar
Yan committed
440
        ds, pt, dtable, chromplot))
441
442
    btn_rem.clicked.connect(lambda: remove_rows(
        pt, dtable, ds, chromplot))
Yan's avatar
Yan committed
443
    drl_load.clicked.connect(lambda: load_drltables(
Yan's avatar
Yan committed
444
        main_widget, pt, dtable, ds, chromplot))
Yan's avatar
Yan committed
445
    drl_save.clicked.connect(lambda: save_drlconfig(
Yan's avatar
Yan committed
446
        pt, dtable, main_widget))
Yan's avatar
Yan committed
447
    drl_print.clicked.connect(lambda: print_graph(
Yan's avatar
Yan committed
448
        graphlabels, pt, dtable, ds))
Yan's avatar
Yan committed
449
    drl_export.clicked.connect(lambda: export_drlspectrum(
Yan's avatar
Yan committed
450
        main_widget, filename, pt, dtable, ds))
451

452
    pt.itemChanged.connect(lambda item: ptable_changed(
Yan's avatar
Yan committed
453
        item.row(), item.column(), pt, dtable, ds, chromplot))
454
455
456
457

    dtable.itemChanged.connect(lambda item: dtable_changed(
        item.row(), item.column(), pt, dtable, ds, chromplot))

Yan's avatar
Yan committed
458
    main_layout = QtWidgets.QVBoxLayout(main_widget)
Yan's avatar
Yan committed
459
460
    sub_layout = QtWidgets.QHBoxLayout()
    tablelayout = QtWidgets.QVBoxLayout()
Yan's avatar
Yan committed
461
    pt_butlayout = QtWidgets.QHBoxLayout()
Yan's avatar
Yan committed
462
    main_butlayout = QtWidgets.QHBoxLayout()
Yan's avatar
Yan committed
463

Yan's avatar
Yan committed
464
465
466
467
    pt_butlayout.addWidget(btn_add)
    pt_butlayout.addWidget(btn_rem)
    pt_butlayout.addStretch(0)

468
469
    main_layout.addLayout(sub_layout)
    main_layout.addWidget(HBar())
Yan's avatar
Yan committed
470
    main_layout.addLayout(main_butlayout)
471

Yan's avatar
Yan committed
472
473
    main_butlayout.addWidget(drl_load)
    main_butlayout.addWidget(drl_save)
Yan's avatar
Yan committed
474
    main_butlayout.addWidget(drl_print)
Yan's avatar
Yan committed
475
476
    main_butlayout.addStretch(1)
    main_butlayout.addWidget(drl_export)
477
    main_butlayout.addWidget(close)
Yan's avatar
Yan committed
478

479
    sub_layout.addWidget(graph_canvas, stretch=1)
Yan's avatar
Yan committed
480
    sub_layout.addLayout(tablelayout)
481

Yan's avatar
Yan committed
482
483
484
485
    tablelayout.addWidget(QtWidgets.QLabel("Raw ions table:"))
    tablelayout.addWidget(pt)
    tablelayout.addLayout(pt_butlayout)
    tablelayout.addWidget(QtWidgets.QLabel("Corrected ions table:"))
Yan's avatar
Yan committed
486
    tablelayout.addWidget(dtable)
487

Yan's avatar
Yan committed
488
    window.show()