__main__.py 14.3 KB
Newer Older
Yan's avatar
Yan committed
1
2
3
4
#!/usr/bin/env python3

from PyQt5 import QtCore
from PyQt5 import QtWidgets
Yan's avatar
Yan committed
5
from PyQt5 import QtGui
6
from PyQt5 import QtPrintSupport
Yan's avatar
Yan committed
7
from rawprasslib import load_raw
Yan's avatar
Yan committed
8
from rawprasslib import rawprasslib
Yan's avatar
Yan committed
9
from prasopes.predictmz import predict as getmzpattern
Yan's avatar
Yan committed
10
11
12
try:
    from rawautoparams import load_params
    autoparams = True
13
except ImportError:
Yan's avatar
Yan committed
14
    autoparams = False
Yan's avatar
Yan committed
15
import numpy as np
Yan's avatar
Yan committed
16
import prasopes.config as cf
17
import prasopes.datatools as dt
Yan's avatar
Yan committed
18
import prasopes.drltools as drl
Yan's avatar
Yan committed
19
import prasopes.filetools as ft
Yan's avatar
Yan committed
20
21
import prasopes.graphtools as gt
import prasopes.imagetools as imgt
Yan's avatar
Yan committed
22
import prasopes.zcetools as zce
Yan's avatar
Yan committed
23
import prasopes.docks as docks
Yan's avatar
Yan committed
24
import prasopes.tangoicons
Yan's avatar
Yan committed
25
26
import sys
import logging
3Yan's avatar
3Yan committed
27
import os.path
Yan's avatar
Yan committed
28
29


30
31
32
33
class update_signal(QtCore.QObject):
    signal = QtCore.pyqtSignal()


34
35
36
37
class QStatusBarLogger(logging.Handler):
    def __init__(self, parent=None):
        super().__init__()
        self.statusBar = QtWidgets.QStatusBar(parent)
Yan's avatar
Yan committed
38
39
        self.trigger = update_signal()
        self.msg = str("")
40
41

    def emit(self, record):
Yan's avatar
Yan committed
42
43
        self.msg = self.format(record)
        self.trigger.signal.emit()
44
45


46
def load_file(parent, augCanvas, update, settings, loadthread, filename=None):
Yan's avatar
Yan committed
47
    """populates dataset and plots it"""
48
49
50
    directory = augCanvas.filename or settings.value("open_folder")
    filename = filename or QtWidgets.QFileDialog.getOpenFileName(
            caption="Open spectrum", directory=directory,
3Yan's avatar
3Yan committed
51
            filter="Finnigan RAW files (*.raw, *.RAW)")[0]
52
53
    if filename != '' and os.path.isfile(filename)\
            and not os.path.isdir(filename):
Yan's avatar
Yan committed
54
55
        error = update_signal()
        errormsg = []
56

57
        def runfnc():
Yan's avatar
Yan committed
58
            try:
Yan's avatar
Yan committed
59
                [i.clear() for i in (
60
61
                    augCanvas.ds, augCanvas.chrom['timesarg'],
                    augCanvas.ms['params'], augCanvas.ms['headers'])]
62
63
                [augCanvas.ds.append(dict(
                    chrom_dat=i[0], masses=i[1], matrix=i[2]))
64
                 for i in load_raw(filename, settings.value("tmp_location"))]
65
            except rawprasslib.ParsingException as pex:
Yan's avatar
Yan committed
66
67
                errormsg.append("Opening of the file has failed!")
                errormsg.append(
68
69
                    "File is incompatible with the rawprasslib, "
                    "canceling request!\n\n"
Yan's avatar
Yan committed
70
                    "Error message:\n{}".format(pex.args[0]))
Yan's avatar
Yan committed
71
                error.signal.emit()
72
                return
73
            if autoparams:
74
                try:
75
76
                    (augCanvas.ms['params'], rawheaders,
                        augCanvas.chrom['machtype']) = load_params(filename)
77
                    segments = [len(subset['chrom_dat'][0])
78
                                for subset in augCanvas.ds]
79
                    indicies = [sum(segments[:i+1])
80
                                for i in range(len(segments))]
81
82
                    augCanvas.ms['headers'] = np.split(
                            rawheaders, indicies)[:-1]
83
                except Exception as pex:
84
85
                    errormsg.append(
                            "File is incompatible with the rawautoparams,")
Yan's avatar
Yan committed
86
87
88
89
                    errormsg.append(
                            "no parameters loaded!\n\n"
                            "Error message:\n{}".format(pex.args[0]))
                    error.signal.emit()
90
91
            gt.populate(augCanvas)
            augCanvas.filename = filename
92
93
94
            parent.setWindowTitle("Prasopes - {}".format(
                os.path.basename(filename)))
            update.signal.emit()
95
96
        error.signal.connect(lambda: QtWidgets.QMessageBox.critical(
            parent, errormsg[0], errormsg[1]))
97
98
        loadthread.run = runfnc
        loadthread.start()
3Yan's avatar
3Yan committed
99

Yan's avatar
Yan committed
100

101
def print_graph(augCanvas):
Yan's avatar
Yan committed
102
    def printimage(printdevice, img):
Yan's avatar
Yan committed
103
        printer.setResolution(600)
Yan's avatar
Yan committed
104
        painter = QtGui.QPainter(printdevice)
Yan's avatar
Yan committed
105
106
107
108
        font = painter.font()
        linesize = printer.resolution()/15
        font.setPixelSize(linesize)
        painter.setFont(font)
109
        painter.drawImage(0, 0, img)
Yan's avatar
Yan committed
110
111
112
        offset = img.size().height()
        line = 1
        spacing = 1.5
113
114
115
116
117
        for row in range(augCanvas.paramstable.rowCount()):
            if augCanvas.paramstable.cellWidget(row, 0).checkState() == 2:
                text = augCanvas.paramstable.item(row, 1).text() +\
                       augCanvas.paramstable.item(row, 2).text()
                painter.drawText(300, int(offset+line*linesize*spacing), text)
Yan's avatar
Yan committed
118
                line += 1
Yan's avatar
Yan committed
119
        painter.end()
120
    # TODO: substitute the QPrintPreviewDialog with QPrintPreviewWidget
121
122
    printPreview = QtPrintSupport.QPrintPreviewDialog()
    printer = printPreview.printer()
Yan's avatar
Yan committed
123
124
    printer.setPageSize(printer.A5)
    printer.setDuplex(printer.DuplexNone)
125
126
    image = imgt.paint_image(augCanvas.ms, augCanvas.spectplot,
                             augCanvas.filename, printer)
Yan's avatar
Yan committed
127
    printPreview.paintRequested.connect(lambda:
Yan's avatar
Yan committed
128
                                        printimage(printer, image))
129
130
131
    printPreview.exec()


132
133
134
135
136
137
138
139
140
141
142
143
def update_spectrum(augCanvas, config):
    if augCanvas.filename:
        slims = [augCanvas.spectplot.get_xlim(),
                 augCanvas.spectplot.get_ylim()]
        augCanvas.ds.clear()
        [augCanvas.ds.append(dict(chrom_dat=i[0], masses=i[1], matrix=i[2]))
         for i in load_raw(augCanvas.filename, config.value("tmp_location"))]
        gt.populate(augCanvas)
        augCanvas.spectplot.set_xlim(slims[0])
        augCanvas.spectplot.set_ylim(slims[1])
        gt.ann_spec(augCanvas.spectplot, augCanvas.ms)
        augCanvas.draw()
Yan's avatar
Yan committed
144
145


146
def dropped(event, parent, augCanvas, update, config, loadthread):
147
    dropurl = event.mimeData().urls()[0].toLocalFile()
148
    load_file(parent, augCanvas, update, config, loadthread, filename=dropurl)
Yan's avatar
Yan committed
149
150
151
152


def drag_entered(event):
    if event.mimeData().hasUrls() and event.mimeData().urls()[0]\
153
            .toLocalFile().lower().endswith('.raw'):
Yan's avatar
Yan committed
154
155
156
        event.accept()


157
def predictmz(form, augCanvas):
Yan's avatar
Yan committed
158
159
    text = form.text()
    if text == "":
160
        augCanvas.ms["predict"] = None
Yan's avatar
Yan committed
161
        return
162
163
164
165
166
167
168
    slims = [augCanvas.spectplot.get_xlim(),
             augCanvas.spectplot.get_ylim()]
    augCanvas.ms["predict"] = getmzpattern(text)
    gt.populate(augCanvas)
    augCanvas.spectplot.set_xlim(slims[0])
    augCanvas.spectplot.set_ylim(slims[1])
    augCanvas.draw()
Yan's avatar
Yan committed
169
170


171
def oddeven_changed(augCanvas, config, oddevenact):
3Yan's avatar
3Yan committed
172
    config.setValue("view/oddeven", oddevenact.isChecked())
173
    update_spectrum(augCanvas, config)
3Yan's avatar
3Yan committed
174
175


176
def key_pressed(event, augCanvas, config):
Yan's avatar
Yan committed
177
    if event.key() == QtCore.Qt.Key_F5:
178
        update_spectrum(augCanvas, config)
179
180
    if event.key() == QtCore.Qt.Key_C:
        if event.modifiers().__int__() == QtCore.Qt.ControlModifier:
181
182
183
184
185
            if augCanvas.paramstable.underMouse():
                dt.clip_tablestr(augCanvas)
            else:
                imgt.clip_spect_img(augCanvas.ms, augCanvas.spectplot,
                                    augCanvas.filename)
186
187
        if event.modifiers().__int__() == QtCore.Qt.ControlModifier + \
                QtCore.Qt.ShiftModifier:
188
            dt.clip_spectstr(augCanvas)
Yan's avatar
Yan committed
189
    if event.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Right):
190
        gt.shift_times(event, augCanvas)
Yan's avatar
Yan committed
191
192


Yan's avatar
Yan committed
193
194
195
196
197
def about(parent):
    """constructs window with "about" info"""
    QtWidgets.QMessageBox.information(
            parent, "About Prasopes",
            "Prasopes Finnigan raw file viewer\n\n"
Yan's avatar
Yan committed
198
            "Version: 0.0.13 (alpha)")
Yan's avatar
Yan committed
199
200


Yan's avatar
Yan committed
201
def main():
202
    app = QtWidgets.QApplication(sys.argv)
203
    loadthread = QtCore.QThread()
204

205
    augCanvas = gt.AugFigureCanvas()
206
    update = update_signal()
Yan's avatar
Yan committed
207

Yan's avatar
Yan committed
208
209
    config = cf.settings()

210
    barHandler = QStatusBarLogger()
211
212
    barHandler.trigger.signal.connect(
        lambda: barHandler.statusBar.showMessage(barHandler.msg))
213

Yan's avatar
Yan committed
214
    p_logger = logging.getLogger('parseLogger')
215
    params_logger = logging.getLogger('acqLogLogger')
Yan's avatar
Yan committed
216
    drl_logger = logging.getLogger('drlLogger')
217
    zce_logger = logging.getLogger('zceLogger')
Yan's avatar
Yan committed
218
    logging.basicConfig()
219
220
221
    # p_logger.setLevel("WARN")
    # p_logger.setLevel("DEBUG")
    # drl_logger.setLevel("INFO")
Yan's avatar
Yan committed
222
    drl_logger.setLevel("DEBUG")
223
    zce_logger.setLevel("DEBUG")
224
    # params_logger.setLevel("DEBUG")
225
226
    p_logger.addHandler(barHandler)
    zce_logger.addHandler(barHandler)
227
228
    params_logger.addHandler(barHandler)
    barHandler.setLevel("DEBUG")
Yan's avatar
Yan committed
229

Yan's avatar
Yan committed
230
    main_window = QtWidgets.QMainWindow(windowTitle="Prasopes")
Yan's avatar
Yan committed
231

232
    if QtGui.QIcon.themeName() == "":
Yan's avatar
Yan committed
233
234
        QtGui.QIcon.setThemeName("TangoMFK")

Yan's avatar
Yan committed
235
236
237
    consoledock = docks.consoleDockWidget(
            locals(), "&Console", "view/consolevisible")
    treedock = docks.treeDockWidget(
238
239
            "&File browser", "view/filebrowservisible", update, load_file,
            main_window, augCanvas, config, loadthread)
Yan's avatar
Yan committed
240
    paramsdock = docks.AugDock("Acquisition parameters", "&Acq parameters",
241
                               "view/acqparvisible")
242
243
    update.signal.connect(lambda: gt.update_paramstable(augCanvas))
    paramsdock.setWidget(augCanvas.paramstable)
Yan's avatar
Yan committed
244

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, augCanvas, update, config, loadthread))
Yan's avatar
Yan committed
250
    exportact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
251
        "document-save-as"), "&Export...", None)
Yan's avatar
Yan committed
252
253
    exportact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_E)
    exportact.triggered.connect(lambda: ft.export_dial(
254
        augCanvas, main_window))
255
256
257
    printact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
        "document-print"), "&Print", None)
    printact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_P)
258
    printact.triggered.connect(lambda: print_graph(augCanvas))
Yan's avatar
Yan committed
259
    settingsact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
260
        "preferences-system"), "&Settings...", None)
Yan's avatar
Yan committed
261
262
    settingsact.triggered.connect(lambda: cf.dial(main_window))
    quitact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
263
        "application-exit"), "&Quit", None)
Yan's avatar
Yan committed
264
265
266
    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
267
        "applications-utilities"), "&TSQ zce...", None)
Yan's avatar
Yan committed
268
269
    zceact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_T)
    zceact.triggered.connect(lambda: zce.dialog(
270
        main_window, augCanvas, update))
Yan's avatar
Yan committed
271
    drlact = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
272
        "applications-utilities"), "&DRL...", None)
Yan's avatar
Yan committed
273
274
    drlact.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_D)
    drlact.triggered.connect(lambda: drl.main_window(
275
        main_window, augCanvas, update))
Yan's avatar
Yan committed
276
277
    aboutact = QtWidgets.QAction("&About Prasopes", None)
    aboutact.triggered.connect(lambda: about(main_window))
Yan's avatar
Yan committed
278
    autozoomy = QtWidgets.QAction(QtGui.QIcon.fromTheme(
Yan's avatar
Yan committed
279
280
281
282
        "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()))
Yan's avatar
Yan committed
283
    autozoomy.triggered.connect(lambda: gt.autozoomy(augCanvas.spectplot))
284
    intensitiesact = QtWidgets.QAction(
Yan's avatar
Yan committed
285
286
        "&Show intensities", None, checkable=True,
        checked=config.value("view/intensities", type=bool))
287
288
    intensitiesact.triggered.connect(lambda: config.setValue(
        "view/intensities", intensitiesact.isChecked()))
Yan's avatar
Yan committed
289
290
    intensitiesact.triggered.connect(lambda: gt.ann_spec(
        augCanvas.spectplot, augCanvas.ms))
291
    intensitiesact.triggered.connect(lambda: augCanvas.draw())
292
    oddevenact = QtWidgets.QAction(
Yan's avatar
Yan committed
293
294
            "&Odd / even", None, checkable=True,
            checked=config.value("view/oddeven", type=bool))
295
296
    oddevenact.triggered.connect(
        lambda: oddeven_changed(augCanvas, config, oddevenact))
Yan's avatar
Yan committed
297

Yan's avatar
Yan committed
298
299
    predictform = QtWidgets.QLineEdit(maximumWidth=150)
    predictform.editingFinished.connect(lambda: predictmz(
300
        predictform, augCanvas))
Yan's avatar
Yan committed
301

Yan's avatar
Yan committed
302
303
    file_menu = QtWidgets.QMenu('&File', main_window)
    main_window.menuBar().addMenu(file_menu)
Yan's avatar
Yan committed
304
305
306
    file_menu.addAction(openact)
    file_menu.addAction(exportact)
    file_menu.addSeparator()
307
308
    file_menu.addAction(printact)
    file_menu.addSeparator()
Yan's avatar
Yan committed
309
310
311
    file_menu.addAction(settingsact)
    file_menu.addSeparator()
    file_menu.addAction(quitact)
Yan's avatar
Yan committed
312
313
    tools_menu = QtWidgets.QMenu('&Tools', main_window)
    main_window.menuBar().addMenu(tools_menu)
Yan's avatar
Yan committed
314
315
    tools_menu.addAction(zceact)
    tools_menu.addAction(drlact)
316
    tools_menu.addSeparator()
Yan's avatar
Yan committed
317
    view_menu = QtWidgets.QMenu('&View', main_window)
318
319
    [view_menu.addAction(i.action) for i in
     (treedock, paramsdock, consoledock)]
Yan's avatar
Yan committed
320
    [view_menu.addAction(i) for i in (autozoomy, intensitiesact)]
321
322
    view_menu.addSeparator()
    view_menu.addAction(oddevenact)
Yan's avatar
Yan committed
323
    main_window.menuBar().addMenu(view_menu)
Yan's avatar
Yan committed
324
325
326
    help_menu = QtWidgets.QMenu('&Help', main_window)
    main_window.menuBar().addMenu(help_menu)
    help_menu.addAction(aboutact)
Yan's avatar
Yan committed
327

328
    main_window.setCentralWidget(augCanvas)
Yan's avatar
Yan committed
329

Yan's avatar
Yan committed
330
331
332
333
334
    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
335

Yan's avatar
Yan committed
336
337
338
    toolBar.addAction(openact)
    toolBar.addAction(exportact)
    toolBar.addSeparator()
Yan's avatar
Yan committed
339
340
341
    toolBar.addWidget(QtWidgets.QLabel("Predict Formula:"))
    toolBar.addWidget(predictform)
    toolBar.addSeparator()
Yan's avatar
Yan committed
342
343
    toolBar.addAction(zceact)
    toolBar.addAction(drlact)
Yan's avatar
Yan committed
344
345
    toolBar.addSeparator()
    toolBar.addAction(autozoomy)
Yan's avatar
Yan committed
346

Yan's avatar
Yan committed
347
348
    main_window.dragEnterEvent = lambda event: drag_entered(event)
    main_window.dropEvent = lambda event: dropped(
349
        event, main_window, augCanvas, update, config, loadthread)
Yan's avatar
Yan committed
350
    main_window.setAcceptDrops(True)
351
352
    main_window.keyPressEvent = lambda event: key_pressed(
            event, augCanvas, config)
Yan's avatar
Yan committed
353

354
355
    main_window.addToolBar(QtCore.Qt.TopToolBarArea, toolBar)
    main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, treedock)
Yan's avatar
Yan committed
356
    main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, paramsdock)
Yan's avatar
Yan committed
357
    main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, consoledock)
358
    main_window.setStatusBar(barHandler.statusBar)
359
360
361

    main_window.setFocus()

Yan's avatar
Yan committed
362
    if len(sys.argv) == 2:
363
        load_file(main_window, augCanvas, update, config, loadthread,
364
                  filename=sys.argv[1])
Yan's avatar
Yan committed
365
    else:
366
367
        gt.pop_plot(0, 0, augCanvas.spectplot, augCanvas.ms)
        gt.pop_plot(0, 0, augCanvas.chromplot, augCanvas.chrom)
Yan's avatar
Yan committed
368
369
370

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

372

Yan's avatar
Yan committed
373
374
if __name__ == "__main__":
    main()