__main__.py 16.9 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 matplotlib.widgets import SpanSelector
Yan's avatar
Yan committed
6
from matplotlib.gridspec import GridSpec
Yan's avatar
Yan committed
7
8
from PyQt5 import QtCore
from PyQt5 import QtWidgets
Yan's avatar
Yan committed
9
from PyQt5 import QtGui
10
from PyQt5 import QtPrintSupport
Yan's avatar
Yan committed
11
from rawprasslib import load_raw
Yan's avatar
Yan committed
12
from rawprasslib import rawprasslib
Yan's avatar
Yan committed
13
from prasopes.predictmz import predict as getmzpattern
Yan's avatar
Yan committed
14
15
16
17
18
try:
    from rawautoparams import load_params
    autoparams = True
except:
    autoparams = False
Yan's avatar
Yan committed
19
import numpy as np
Yan's avatar
Yan committed
20
import prasopes.config as cf
21
import prasopes.datatools as dt
Yan's avatar
Yan committed
22
import prasopes.drltools as drl
Yan's avatar
Yan committed
23
import prasopes.filetools as ft
Yan's avatar
Yan committed
24
25
import prasopes.graphtools as gt
import prasopes.imagetools as imgt
Yan's avatar
Yan committed
26
import prasopes.zcetools as zce
Yan's avatar
Yan committed
27
import prasopes.tangoicons
Yan's avatar
Yan committed
28
29
30
import sys
import matplotlib
import logging
3Yan's avatar
3Yan committed
31
import os.path
Yan's avatar
Yan committed
32
33
34
matplotlib.use("Qt5Agg")


35
36
37
38
class update_signal(QtCore.QObject):
    signal = QtCore.pyqtSignal()


39
40
41
42
43
44
45
46
47
48
class QStatusBarLogger(logging.Handler):
    def __init__(self, parent=None):
        super().__init__()
        self.statusBar = QtWidgets.QStatusBar(parent)

    def emit(self, record):
        msg = self.format(record)
        self.statusBar.showMessage(msg)


49
def load_file(parent, chrom_plot, spc, d_set, ms_s, fn, chrom_s,
50
              update, settings, loadthread, filename=None):
Yan's avatar
Yan committed
51
    """populates dataset and plots it"""
3Yan's avatar
3Yan committed
52
53
54
    directory=settings.value("open_folder")
    if fn[0] is not None:
        directory=fn[0]
Yan's avatar
Yan committed
55
56
    if filename == None:
        filename = QtWidgets.QFileDialog.getOpenFileName(
3Yan's avatar
3Yan committed
57
58
59
            caption="Open spectrum",
            directory=directory,
            filter="Finnigan RAW files (*.raw, *.RAW)")[0]
60
61
62
    if filename is not '' and os.path.isfile(filename)\
                          and not os.path.isdir(filename):
        def runfnc():
Yan's avatar
Yan committed
63
            try:
64
65
66
67
68
                d_set.clear()
                chrom_s['timesarg'].clear()
                [d_set.append(dict(chrom_dat=i[0], masses=i[1], matrix=i[2]))
                    for i in load_raw(filename, settings.value("tmp_location"))]
            except rawprasslib.ParsingException as pex:
Yan's avatar
Yan committed
69
                QtWidgets.QMessageBox.critical(
70
71
72
                    parent, "Opening of the file has failed!",
                    "File is incompatible with the rawprasslib, "
                    "canceling request!\n\n"
Yan's avatar
Yan committed
73
                    "Error message:\n{}".format(pex.args[0]))
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
                return
            [i.clear() for i in (ms_s['params'],ms_s['headers'])]
            if autoparams == True:
                try:
                    ms_s['params'], rawheaders = load_params(filename)
                    segments = [len(subset['chrom_dat'][0]) for subset in d_set]
                    indicies = [sum(segments[:i+1]) for i in 
                            range(len(segments))]
                    ms_s['headers'] = np.split(rawheaders, indicies)[:-1]
                except Exception as pex:
                    QtWidgets.QMessageBox.critical(
                        parent, "Parameters readout has failed!",
                        "File is incompatible with the rawautoparams, "
                        "no parameters loaded!\n\n"
                        "Error message:\n{}".format(pex.args[0]))
            gt.populate(chrom_plot, spc, d_set, ms_s, chrom_s)
            fn[0] = filename
            parent.setWindowTitle("Prasopes - {}".format(
                os.path.basename(filename)))
            update.signal.emit()
        loadthread.run = runfnc
        loadthread.start()
3Yan's avatar
3Yan committed
96

Yan's avatar
Yan committed
97

Yan's avatar
Yan committed
98
99
def print_graph(data_set, mass_spec, chrom_spec, spect, fn):
    def printimage(printdevice, img):
Yan's avatar
Yan committed
100
        printer.setResolution(600)
Yan's avatar
Yan committed
101
        painter = QtGui.QPainter(printdevice)
Yan's avatar
Yan committed
102
        painter.drawImage(0,0,img)
Yan's avatar
Yan committed
103
104
        painter.end()
    #TODO: substitute the QPrintPreviewDialog with QPrintPreviewWidget
105
106
    printPreview = QtPrintSupport.QPrintPreviewDialog()
    printer = printPreview.printer()
Yan's avatar
Yan committed
107
108
    printer.setPageSize(printer.A5)
    printer.setDuplex(printer.DuplexNone)
Yan's avatar
Yan committed
109
    image = imgt.paint_image(mass_spec, spect, printer)
Yan's avatar
Yan committed
110
    printPreview.paintRequested.connect(lambda:
Yan's avatar
Yan committed
111
                                        printimage(printer, image))
112
113
114
    printPreview.exec()


Yan's avatar
Yan committed
115
116
def update_spectrum(chromatogram, spect, ds, ms, fn, chrom, config):
    if fn[0] is not None:
Yan's avatar
Yan committed
117
        slims = [spect.get_xlim(), spect.get_ylim()]
3Yan's avatar
3Yan committed
118
119
120
        ds.clear()
        [ds.append(dict(chrom_dat=i[0], masses=i[1], matrix=i[2])) for i
                in load_raw(fn[0], config.value("tmp_location"))]
Yan's avatar
Yan committed
121
122
123
        gt.populate(chromatogram, spect, ds, ms, chrom)
        spect.set_xlim(slims[0])
        spect.set_ylim(slims[1])
Yan's avatar
Yan committed
124
        gt.ann_spec(spect, ms)
Yan's avatar
Yan committed
125
126
127
        spect.get_figure().canvas.draw()


128
def dropped(event, parent, chromatogram, spectrum, ds, ms, filename,
129
            chrom, update, config, loadthread):
130
    dropurl = event.mimeData().urls()[0].toLocalFile()
131
    load_file(parent, chromatogram, spectrum, ds, ms, filename,
132
              chrom, update, config, loadthread, filename=dropurl)
Yan's avatar
Yan committed
133
134
135
136


def drag_entered(event):
    if event.mimeData().hasUrls() and event.mimeData().urls()[0]\
137
        .toLocalFile().lower().endswith('.raw'):
Yan's avatar
Yan committed
138
139
140
        event.accept()


Yan's avatar
Yan committed
141
142
143
144
145
146
147
148
149
150
151
152
153
def predictmz(form, chromatogram, spect, ds, ms, chrom):
    text = form.text()
    if text == "":
        ms["predict"] = None
        return
    slims = [spect.get_xlim(), spect.get_ylim()]
    ms["predict"] = getmzpattern(text)
    gt.populate(chromatogram, spect, ds, ms, chrom)
    spect.set_xlim(slims[0])
    spect.set_ylim(slims[1])
    spect.get_figure().canvas.draw()


3Yan's avatar
3Yan committed
154
155
156
157
158
159
def oddeven_changed(chromatogram, spectrum, ds, ms, filename, chrom, config,
        oddevenact):
    config.setValue("view/oddeven", oddevenact.isChecked())
    update_spectrum(chromatogram, spectrum, ds, ms, filename, chrom, config)


Yan's avatar
Yan committed
160
161
162
def key_pressed(event, chrom, spect, ds, ms_ds, fn, chrom_ds, config):
    if event.key() == QtCore.Qt.Key_F5:
        update_spectrum(chrom, spect, ds, ms_ds, fn, chrom_ds, config)
163
164
165
166
167
168
    if event.key() == QtCore.Qt.Key_C:
        if event.modifiers().__int__() == QtCore.Qt.ControlModifier:
            imgt.clip_spect_img(ms_ds, spect)
        if event.modifiers().__int__() == QtCore.Qt.ControlModifier+\
                                          QtCore.Qt.ShiftModifier:
            dt.clip_spectstr(spect, chrom_ds, fn)
Yan's avatar
Yan committed
169
170
    if event.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Right):
        gt.shift_times(event, spect, chrom, ds, ms_ds, chrom_ds)
Yan's avatar
Yan committed
171
172


Yan's avatar
Yan committed
173
174
175
176
177
def about(parent):
    """constructs window with "about" info"""
    QtWidgets.QMessageBox.information(
            parent, "About Prasopes",
            "Prasopes Finnigan raw file viewer\n\n"
178
            "Version: 0.0.12 (alpha)")
Yan's avatar
Yan committed
179
180


Yan's avatar
Yan committed
181
def main():
182
    app = QtWidgets.QApplication(sys.argv)
183
    loadthread = QtCore.QThread()
184

3Yan's avatar
3Yan committed
185
186
    ds = []
    ms = dict(annotation=[], name="Spectrum", xlabel="m/z",
Yan's avatar
Yan committed
187
188
              ylabel="ion count", xtics=20, predict=None,
              params=[], headers=[])
189
    chrom = dict(x=[0], y=[0], t_start=None, t_end=None,
Yan's avatar
Yan committed
190
                 name="Chromatogram", xlabel="time(min)",
3Yan's avatar
3Yan committed
191
                 ylabel="total ion count", timesarg=[])
Yan's avatar
Yan committed
192
    filename = [None]
3Yan's avatar
3Yan committed
193
    drlcache = [None, None]
194
    update = update_signal()
Yan's avatar
Yan committed
195

Yan's avatar
Yan committed
196
197
    config = cf.settings()

198
199
    barHandler = QStatusBarLogger()

Yan's avatar
Yan committed
200
    p_logger = logging.getLogger('parseLogger')
201
    params_logger = logging.getLogger('acqLogLogger')
Yan's avatar
Yan committed
202
    drl_logger = logging.getLogger('drlLogger')
203
    zce_logger = logging.getLogger('zceLogger')
Yan's avatar
Yan committed
204
    logging.basicConfig()
205
206
    p_logger.setLevel("WARN")
    #p_logger.setLevel("DEBUG")
Yan's avatar
Yan committed
207
    #drl_logger.setLevel("INFO")
208
    #drl_logger.setLevel("DEBUG")
209
    zce_logger.setLevel("DEBUG")
210
    params_logger.setLevel("DEBUG")
211
212
    p_logger.addHandler(barHandler)
    zce_logger.addHandler(barHandler)
213
214
    params_logger.addHandler(barHandler)
    barHandler.setLevel("DEBUG")
Yan's avatar
Yan committed
215

Yan's avatar
Yan committed
216
    graph = Figure(figsize=(5, 4), dpi=100, facecolor="None")
Yan's avatar
Yan committed
217
218
219
    grid = graph.add_gridspec(2, 1)
    chromatogram = graph.add_subplot(grid[0,0], facecolor=(1, 1, 1, 0.8))
    spectrum = graph.add_subplot(grid[1,0], facecolor=(1, 1, 1, 0.8))
Yan's avatar
Yan committed
220
221
222
223
224
225
226
227
228
    graph.tight_layout()
    mpl_canvas = FigureCanvas(graph)
    mpl_canvas.setStyleSheet("background-color:transparent;")
    mpl_canvas.setAutoFillBackground(False)
    
    gt.pan_factory(chromatogram)
    gt.zoom_factory(chromatogram, 1.15)
    gt.pan_factory(spectrum, ms)
    gt.zoom_factory(spectrum, 1.15, ms)
229
    mass_selector = SpanSelector(
Yan's avatar
Yan committed
230
        spectrum, lambda x_min, x_max: gt.pick_masses(
231
232
233
            x_min, x_max, spectrum, ms), 'horizontal', minspan=0.01,
        useblit=True, rectprops=dict(alpha=0.15, facecolor='purple'),
        button=3)
234
    time_selector = SpanSelector(
Yan's avatar
Yan committed
235
236
237
238
239
         chromatogram, lambda x_min, x_max: gt.pick_times(
             x_min, x_max, spectrum, ds, chromatogram, ms, chrom), 
         'horizontal', useblit=True, rectprops=dict(
             alpha=0.15, facecolor='purple'), button=3)

Yan's avatar
Yan committed
240
    main_window = QtWidgets.QMainWindow(windowTitle="Prasopes")
Yan's avatar
Yan committed
241

Yan's avatar
Yan committed
242
243
244
    if QtGui.QIcon.themeName() is "":
        QtGui.QIcon.setThemeName("TangoMFK")

Yan's avatar
Yan committed
245
    openact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
246
        "document-open"), "&Open...", None)
Yan's avatar
Yan committed
247
248
    openact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_O)
    openact.triggered.connect(lambda: load_file(
249
        main_window, chromatogram, spectrum, ds, ms, filename, chrom,
250
        update, config, loadthread))
Yan's avatar
Yan committed
251
    exportact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
252
        "document-save-as"), "&Export...", None)
Yan's avatar
Yan committed
253
254
    exportact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_E)
    exportact.triggered.connect(lambda: ft.export_dial(
255
        spectrum, chrom, filename, main_window))
256
257
258
    printact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
        "document-print"), "&Print", None)
    printact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_P)
Yan's avatar
Yan committed
259
260
    printact.triggered.connect(lambda: print_graph(
        ds, ms, chrom, spectrum, filename))
Yan's avatar
Yan committed
261
    settingsact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
262
        "preferences-system"), "&Settings...", None)
Yan's avatar
Yan committed
263
264
    settingsact.triggered.connect(lambda: cf.dial(main_window))
    quitact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
265
        "application-exit"), "&Quit", None)
Yan's avatar
Yan committed
266
267
268
    quitact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Q)
    quitact.triggered.connect(main_window.close)
    zceact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
269
        "applications-utilities"), "&TSQ zce...", None)
Yan's avatar
Yan committed
270
271
    zceact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_T)
    zceact.triggered.connect(lambda: zce.dialog(
272
        main_window, ds, filename, update))
Yan's avatar
Yan committed
273
    drlact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
274
        "applications-utilities"), "&DRL...", None)
Yan's avatar
Yan committed
275
276
    drlact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_D)
    drlact.triggered.connect(lambda: drl.main_window(
277
        main_window, ds, filename, drlcache, update))
Yan's avatar
Yan committed
278
279
    aboutact = QtWidgets.QAction("&About Prasopes", None)
    aboutact.triggered.connect(lambda: about(main_window))
Yan's avatar
Yan committed
280
    autozoomy = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
281
282
283
284
        "zoom-original"), "Auto Zoom Y", None, checkable=True,
        checked=config.value("view/autozoomy", type=bool))
    autozoomy.triggered.connect(lambda: config.setValue(
                                "view/autozoomy", autozoomy.isChecked()))
285
286
287
288
289
290
291
292
293
294
295
    autozoomy.triggered.connect(lambda: gt.autozoomy(spectrum))
    intensitiesact = QtWidgets.QAction("&Show intensities", None,
            checkable=True, checked=config.value("view/intensities",
                type=bool))
    intensitiesact.triggered.connect(lambda: config.setValue(
        "view/intensities", intensitiesact.isChecked()))
    intensitiesact.triggered.connect(lambda: gt.ann_spec(spectrum, ms))
    intensitiesact.triggered.connect(lambda: spectrum.figure.canvas.draw())
    oddevenact = QtWidgets.QAction("&Odd / even", None, checkable=True,
            checked=config.value("view/oddeven", type=bool))
    oddevenact.triggered.connect(lambda:
3Yan's avatar
3Yan committed
296
297
        oddeven_changed(chromatogram, spectrum, ds, ms, filename, chrom,
            config, oddevenact))
Yan's avatar
Yan committed
298
299
300
301
302
    filebrowseract = QtWidgets.QAction(
            "&File browser", None, checkable=True,
            checked=config.value("view/filebrowservisible", type=bool))
    filebrowseract.triggered.connect(lambda: config.setValue(
        "view/filebrowservisible", filebrowseract.isChecked()))
303
304
305
    filebrowseract.triggered.connect(
        lambda: treedock.show() if filebrowseract.isChecked() == True
                else treedock.hide())
Yan's avatar
Yan committed
306

Yan's avatar
Yan committed
307
308
309
310
    predictform = QtWidgets.QLineEdit(maximumWidth=150)
    predictform.editingFinished.connect(lambda: predictmz(
        predictform, chromatogram, spectrum, ds, ms, chrom))

Yan's avatar
Yan committed
311
312
    file_menu = QtWidgets.QMenu('&File', main_window)
    main_window.menuBar().addMenu(file_menu)
Yan's avatar
Yan committed
313
314
315
    file_menu.addAction(openact)
    file_menu.addAction(exportact)
    file_menu.addSeparator()
316
317
    file_menu.addAction(printact)
    file_menu.addSeparator()
Yan's avatar
Yan committed
318
319
320
    file_menu.addAction(settingsact)
    file_menu.addSeparator()
    file_menu.addAction(quitact)
Yan's avatar
Yan committed
321
322
    tools_menu = QtWidgets.QMenu('&Tools', main_window)
    main_window.menuBar().addMenu(tools_menu)
Yan's avatar
Yan committed
323
324
    tools_menu.addAction(zceact)
    tools_menu.addAction(drlact)
325
    tools_menu.addSeparator()
Yan's avatar
Yan committed
326
327
328
    view_menu = QtWidgets.QMenu('&View', main_window)
    view_menu.addAction(filebrowseract)
    view_menu.addAction(autozoomy)
329
330
331
    view_menu.addAction(intensitiesact)
    view_menu.addSeparator()
    view_menu.addAction(oddevenact)
Yan's avatar
Yan committed
332
    main_window.menuBar().addMenu(view_menu)
Yan's avatar
Yan committed
333
334
335
    help_menu = QtWidgets.QMenu('&Help', main_window)
    main_window.menuBar().addMenu(help_menu)
    help_menu.addAction(aboutact)
Yan's avatar
Yan committed
336

337
    main_window.setCentralWidget(mpl_canvas)
Yan's avatar
Yan committed
338

Yan's avatar
Yan committed
339
340
341
342
343
    toolBar = QtWidgets.QToolBar(main_window)
    toolBar.setAllowedAreas(QtCore.Qt.TopToolBarArea)
    toolBar.setFloatable(False)
    toolBar.setMovable(False)
    toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
Yan's avatar
Yan committed
344

Yan's avatar
Yan committed
345
346
347
    toolBar.addAction(openact)
    toolBar.addAction(exportact)
    toolBar.addSeparator()
Yan's avatar
Yan committed
348
349
350
    toolBar.addWidget(QtWidgets.QLabel("Predict Formula:"))
    toolBar.addWidget(predictform)
    toolBar.addSeparator()
Yan's avatar
Yan committed
351
352
    toolBar.addAction(zceact)
    toolBar.addAction(drlact)
Yan's avatar
Yan committed
353
354
    toolBar.addSeparator()
    toolBar.addAction(autozoomy)
Yan's avatar
Yan committed
355

3Yan's avatar
3Yan committed
356
    fileModel = QtWidgets.QFileSystemModel()
357
358
    fileModel.setRootPath('')
    activeDir = fileModel.index(config.value("open_folder"))
3Yan's avatar
3Yan committed
359
360
361
362
    treeview = QtWidgets.QTreeView()
    treeview.setModel(fileModel)
    treeview.setCurrentIndex(activeDir)
    treeview.expand(activeDir)
363
364
    dirview = QtWidgets.QListView()
    dirview.setModel(fileModel)
3Yan's avatar
3Yan committed
365
    treedock = QtWidgets.QDockWidget()
366
367
368
369
370
371
372
373

    def scrolltoonce():
        fileModel.directoryLoaded.disconnect(scrolltoonce)
        treeview.scrollTo(fileModel.index(config.value("open_folder")), 1)
    fileModel.directoryLoaded.connect(scrolltoonce)
    fileModel.directoryLoaded.connect(
            lambda: treeview.resizeColumnToContents(0))

Yan's avatar
Yan committed
374
375
    if not config.value("view/filebrowservisible",type=bool):
        treedock.hide()
376
377
378
379
    treedock.setWidget(QtWidgets.QWidget())
    treedock_layout = QtWidgets.QVBoxLayout(treedock.widget())
    treedock_layout.addWidget(treeview)
    treedock_layout.addWidget(dirview)
380
381
382
    update.signal.connect(lambda: treeview.setCurrentIndex(fileModel.index(
                                  filename[0])))
    update.signal.connect(lambda: dirview.setRootIndex(fileModel.index(
3Yan's avatar
3Yan committed
383
            os.path.dirname(os.path.realpath(filename[0])))))
384
    clickload = lambda index: load_file(
3Yan's avatar
3Yan committed
385
        main_window, chromatogram, spectrum, ds, ms, filename, chrom,
386
        update, config, loadthread, filename=fileModel.filePath(index))
387
388
389
    for i in [treeview.doubleClicked, dirview.doubleClicked, dirview.clicked]:
        i.connect(clickload)

390
391
392
393
394
395
396
    #fileModel gots stuck sometimes, better give it a separate thread
    #it complains at the start, but still works later 
    #and I did not found better solution
    treedockThread = QtCore.QThread()
    treedockThread.start()
    fileModel.moveToThread(treedockThread)

397
398
399
400
401
402
    def closeOverride(event, dock, action):
        action.setChecked(False)
        dock.hide()
        event.ignore()
    treedock.closeEvent = lambda event: closeOverride(
            event, treedock, filebrowseract)
Yan's avatar
Yan committed
403
    main_window.closeEvent = lambda event: treedockThread.quit()
Yan's avatar
Yan committed
404
405
    main_window.dragEnterEvent = lambda event: drag_entered(event)
    main_window.dropEvent = lambda event: dropped(
406
        event, main_window, chromatogram, spectrum, ds, ms, filename,
3Yan's avatar
3Yan committed
407
        chrom, update, config)
Yan's avatar
Yan committed
408
    main_window.setAcceptDrops(True)
Yan's avatar
Yan committed
409
410
    main_window.keyPressEvent = lambda event: key_pressed(event, chromatogram,
            spectrum, ds, ms, filename, chrom, config)
Yan's avatar
Yan committed
411

412
413
    main_window.addToolBar(QtCore.Qt.TopToolBarArea, toolBar)
    main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, treedock)
414
    main_window.setStatusBar(barHandler.statusBar)
415
416
417

    main_window.setFocus()

Yan's avatar
Yan committed
418
    if len(sys.argv) == 2:
419
        load_file(main_window, chromatogram, spectrum, ds, ms,
420
421
                  filename, chrom, update, config, loadthread,
                  filename=sys.argv[1])
Yan's avatar
Yan committed
422
    else:
3Yan's avatar
3Yan committed
423
424
        gt.pop_plot(0, 0, spectrum, ms)
        gt.pop_plot(0, 0, chromatogram, chrom)
Yan's avatar
Yan committed
425
426
427

    main_window.show()
    sys.exit(app.exec_())
Yan's avatar
Yan committed
428

429

Yan's avatar
Yan committed
430
431
if __name__ == "__main__":
    main()