zcetools.py 6.69 KB
Newer Older
Yan's avatar
Yan committed
1
2
3
4
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5 import QtCore
from PyQt5 import QtWidgets
Yan's avatar
Yan committed
5
from PyQt5 import QtPrintSupport
3Yan's avatar
3Yan committed
6
from prasopes.zcetools_help import helpstr
Yan's avatar
Yan committed
7
8
9
10
11
import numpy as np
import prasopes.graphtools as gt
import prasopes.filetools as ft
import os.path
import pkg_resources
12
13
14
15
import logging


logger = logging.getLogger('zceLogger')
Yan's avatar
Yan committed
16
17


Yan's avatar
Yan committed
18
def pop_dial(zcespec, gradspect, data_set, coff_d, grad_d,
Yan's avatar
Yan committed
19
             textfield, fn, parent):
20
    logger.debug("populating ZCE dialog")
Yan's avatar
Yan committed
21
22
23
    if fn[0] is None:
        QtWidgets.QMessageBox.warning(
            parent, "ZCE calculation",
Yan's avatar
Yan committed
24
            "No spectrum opened, nothing to display")
Yan's avatar
Yan committed
25
26
27
28
        return
    zcespec.clear()
    gradspect.clear()

3Yan's avatar
3Yan committed
29
30
31
32
33
34
35
    coff_x = data_set[0]['masses'] - 196
    coff_y = np.mean(data_set[0]['matrix'], axis=0)
    grad_x = coff_x
    halfl = int(len(grad_x)/2)
    grad_y = -np.gradient(coff_y)\
            if np.sum(coff_y[:halfl]) > np.sum(coff_y[halfl:])\
            else np.gradient(coff_y)
Yan's avatar
Yan committed
36
37
    gradspect.axhline(0, color="#FF000088", linestyle=":")
    zcespec.axhline(0, color="#0000FF88", linestyle=":")
3Yan's avatar
3Yan committed
38
39
    gt.pop_plot(coff_x, coff_y, zcespec, coff_d)
    gt.pop_plot(grad_x, grad_y, gradspect, grad_d)
Yan's avatar
Yan committed
40
    gradspect.lines[-1].set_color("red")
Yan's avatar
Yan committed
41
42
43
    gradspect.set_ylim(bottom=gradspect.get_ylim()[1] * -0.1)
    zcespec.set_title("COFF", loc="center")

3Yan's avatar
3Yan committed
44
45
46
47
    maxarg = np.argmax(grad_y)
    grad_d['gmax'] = coff_x[maxarg]
    halfmax = np.max(grad_y) / 2
    peakargs = np.where(grad_y > halfmax)[0]
Yan's avatar
Yan committed
48
49
    start = [peakargs[0]-1, peakargs[0]]
    end = [peakargs[-1]+1, peakargs[-1]]
Yan's avatar
Yan committed
50
51
    grad_d['fwhm_y'] = [halfmax, halfmax]
    grad_d['fwhm_x'] = [
3Yan's avatar
3Yan committed
52
53
        np.interp(halfmax, grad_y[start], grad_x[start]),
        np.interp(halfmax, grad_y[end], grad_x[end])]
Yan's avatar
Yan committed
54
55
56
57
58
59
60
61
62
63
    grad_d['fwhm'] = grad_d['fwhm_x'][1] - grad_d['fwhm_x'][0]

    gradspect.plot(grad_d['fwhm_x'], grad_d['fwhm_y'], "#880088")
    textfield.setText(
        "ZCE = {:.2f}\nFWHM = {:.2f}\nCenter(HM) = {:.2f}".format(
            grad_d['gmax'], grad_d['fwhm'],
            np.mean(grad_d['fwhm_x'])))
    gradspect.annotate(' FWHM = {:.2f}'.format(grad_d['fwhm']),
                       xy=(grad_d['fwhm_x'][1], grad_d['fwhm_y'][1]))
    gradspect.annotate('{:.2f}'.format(grad_d['gmax']),
3Yan's avatar
3Yan committed
64
                       xy=(grad_x[maxarg], grad_y[maxarg]))
Yan's avatar
Yan committed
65
66
67
68
69
70
71
72
73
74
    zcespec.figure.canvas.draw()


def exp_zce(zce_spec, zcegrad_spec, fn, parent):
    """export the ZCE graph into the .dat file format"""
    if fn[0] is None:
        QtWidgets.QMessageBox.warning(
            parent, "Export ZCE spectrum",
            "Nothing to export, cancelling request")
        return
Yan's avatar
Yan committed
75
76
    exp_f_name = ft.get_save_filename(
        "Export ZCE spectrum", "dat table (*.dat)", "dat", parent)
Yan's avatar
Yan committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    if exp_f_name is not '':
        expf = open(exp_f_name, 'w')
        expf.write("mass ion_count ion_count_gradient fwhm_x fwhm_y\n"
                   "m/z\n"
                   "{} zce={} fwhm={} hmcenter={}\n".format(
                       os.path.basename(fn[0]), zcegrad_spec['gmax'],
                       zcegrad_spec['fwhm'],
                       np.mean(zcegrad_spec['fwhm_x'])))
        for i in range(len(zce_spec['x'])):
            fwhm = ["", ""]
            if i <= 1:
                fwhm = [zcegrad_spec['fwhm_x'][i],
                        zcegrad_spec['fwhm_y'][i]]
            expf.write("{} {} {} {} {}\n".format(
                zce_spec['x'][i], zce_spec['y'][i], zcegrad_spec['y'][i],
                fwhm[0], fwhm[1]))
        expf.close()


96
def help_msg(pw):
3Yan's avatar
3Yan committed
97
98
    QtWidgets.QMessageBox.information(
            pw, "TSQ zce tool help", "{}".format(helpstr))
99
100


Yan's avatar
Yan committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
def print_graph(ds, coff, coffgrad, filename):
    printfig = Figure(figsize=(5, 2), dpi=100)
    printplot = printfig.add_subplot(111)
    printplot_overlay = printplot.twinx()
    printcanvas = FigureCanvas(printfig)
    textfield = QtWidgets.QLabel()
    pop_dial(printplot, printplot_overlay, ds, coff, coffgrad,
             textfield, filename, None)
    widget = QtWidgets.QDialog(None, windowTitle='Print preview')
    layout = QtWidgets.QVBoxLayout(widget)
    layout.addWidget(printcanvas)
    widget.resize(600, 400)
    widget.show()
    dialog = QtPrintSupport.QPrintDialog()
    if dialog.exec_() == QtWidgets.QDialog.Accepted:
        printcanvas.render(dialog.printer())
    widget.close()


120
def dialog(parent, ds, filename, update_signal):
3Yan's avatar
3Yan committed
121
122
123
124
    coff = dict(name="", xlabel="Voltage (V)", ylabel="ion count")
    coffgrad = dict(c_ymin=-0.1, name="", xlabel="",
                    ylabel="ion count gradient", gmax=None, fwhm_x=None,
                    fwhm_y=None, fwhm=None)
Yan's avatar
Yan committed
125

126
127
128
129
130
131
132
133
134
    def onclose(widget, event, update_fnc):
        logger.debug("ZCE window custom close routine called")
        update_signal.signal.disconnect(update_fnc)
        QtWidgets.QDialog.closeEvent(widget, event)

    def update_fnc():
        pop_dial(coffspect, coffspect_grad, ds, coff, coffgrad,
                 textfield, filename, parent)

Yan's avatar
Yan committed
135
136
    dial_widget = QtWidgets.QDialog(
            parent, windowTitle='TSQ zero collision energy calculator')
137
138
139
    dial_widget.closeEvent = lambda event: onclose(
        dial_widget, event, update_fnc)
    update_signal.signal.connect(update_fnc)
Yan's avatar
Yan committed
140

Yan's avatar
Yan committed
141
    dial_graph = Figure(figsize=(5, 2), dpi=100, facecolor="None")
Yan's avatar
Yan committed
142
143
144
145
146
147
148
149
150
151
152
153
154
    coffspect = dial_graph.add_subplot(111, facecolor=(1, 1, 1, 0.8))
    coffspect_grad = coffspect.twinx()
    graph_canvas = FigureCanvas(dial_graph)
    graph_canvas.setStyleSheet("background-color:transparent;")
    graph_canvas.setAutoFillBackground(False)
    graph_canvas.setFocusPolicy(QtCore.Qt.ClickFocus)

    gt.zoom_factory(coffspect_grad, 1.15, coffgrad)
    gt.pan_factory(coffspect_grad, coffgrad)

    zce_export = QtWidgets.QPushButton("Export ZCE")
    zce_export.clicked.connect(lambda: exp_zce(
        coff, coffgrad, filename, parent))
Yan's avatar
Yan committed
155
156
157
    zce_print = QtWidgets.QPushButton("Print ZCE")
    zce_print.clicked.connect(lambda: print_graph(
        ds, coff, coffgrad, filename))
Yan's avatar
Yan committed
158
    zce_help = QtWidgets.QPushButton("Help")
159
    zce_help.clicked.connect(lambda: help_msg(parent))
Yan's avatar
Yan committed
160
161
162
163
164
165
166
167
168
    close_button = QtWidgets.QPushButton("Close")
    close_button.clicked.connect(dial_widget.close)

    butt_layout = QtWidgets.QHBoxLayout()
    butt_layout.addWidget(zce_help)
    butt_layout.addStretch(1)
    textfield = QtWidgets.QLabel(coffgrad['gmax'])
    butt_layout.addWidget(textfield)
    butt_layout.addStretch(1)
Yan's avatar
Yan committed
169
    butt_layout.addWidget(zce_print)
Yan's avatar
Yan committed
170
171
172
173
174
175
    butt_layout.addWidget(zce_export)
    butt_layout.addWidget(close_button)

    dial_layout = QtWidgets.QVBoxLayout(dial_widget)
    dial_layout.addWidget(graph_canvas)
    dial_layout.addLayout(butt_layout)
Yan's avatar
Yan committed
176
177
    dial_widget.show()
    pop_dial(coffspect, coffspect_grad, ds, coff, coffgrad,
Yan's avatar
Yan committed
178
             textfield, filename, parent)