zcetools.py 6.8 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
Yan's avatar
Yan committed
6
7
8
9
10
import numpy as np
import prasopes.graphtools as gt
import prasopes.filetools as ft
import os.path
import pkg_resources
11
12
13
14
import logging


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


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

3Yan's avatar
3Yan committed
28
29
30
31
32
33
34
    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
35
36
    gradspect.axhline(0, color="#FF000088", linestyle=":")
    zcespec.axhline(0, color="#0000FF88", linestyle=":")
3Yan's avatar
3Yan committed
37
38
    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
39
    gradspect.lines[-1].set_color("red")
Yan's avatar
Yan committed
40
41
42
    gradspect.set_ylim(bottom=gradspect.get_ylim()[1] * -0.1)
    zcespec.set_title("COFF", loc="center")

3Yan's avatar
3Yan committed
43
44
45
46
    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
47
48
    start = [peakargs[0]-1, peakargs[0]]
    end = [peakargs[-1]+1, peakargs[-1]]
Yan's avatar
Yan committed
49
50
    grad_d['fwhm_y'] = [halfmax, halfmax]
    grad_d['fwhm_x'] = [
3Yan's avatar
3Yan committed
51
52
        np.interp(halfmax, grad_y[start], grad_x[start]),
        np.interp(halfmax, grad_y[end], grad_x[end])]
Yan's avatar
Yan committed
53
54
55
56
57
58
59
60
61
62
    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
63
                       xy=(grad_x[maxarg], grad_y[maxarg]))
Yan's avatar
Yan committed
64
65
66
67
68
69
70
71
72
73
    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
74
75
    exp_f_name = ft.get_save_filename(
        "Export ZCE spectrum", "dat table (*.dat)", "dat", parent)
Yan's avatar
Yan committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    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()


95
def help_msg(pw):
96
    path = pkg_resources.resource_filename(__name__, 'zcetools_help')
97
98
99
100
101
102
    with open(path, 'r') as helpfile:
        helpcontent = helpfile.read()
        QtWidgets.QMessageBox.information(
            pw, "TSQ zce tool help", "{}".format(helpcontent))


Yan's avatar
Yan committed
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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()


122
def dialog(parent, ds, filename, update_signal):
3Yan's avatar
3Yan committed
123
124
125
126
    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
127

128
129
130
131
132
133
134
135
136
    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
137
138
    dial_widget = QtWidgets.QDialog(
            parent, windowTitle='TSQ zero collision energy calculator')
139
140
141
    dial_widget.closeEvent = lambda event: onclose(
        dial_widget, event, update_fnc)
    update_signal.signal.connect(update_fnc)
Yan's avatar
Yan committed
142

Yan's avatar
Yan committed
143
    dial_graph = Figure(figsize=(5, 2), dpi=100, facecolor="None")
Yan's avatar
Yan committed
144
145
146
147
148
149
150
151
152
153
154
155
156
    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
157
158
159
    zce_print = QtWidgets.QPushButton("Print ZCE")
    zce_print.clicked.connect(lambda: print_graph(
        ds, coff, coffgrad, filename))
Yan's avatar
Yan committed
160
    zce_help = QtWidgets.QPushButton("Help")
161
    zce_help.clicked.connect(lambda: help_msg(parent))
Yan's avatar
Yan committed
162
163
164
165
166
167
168
169
170
    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
171
    butt_layout.addWidget(zce_print)
Yan's avatar
Yan committed
172
173
174
175
176
177
    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
178
179
    dial_widget.show()
    pop_dial(coffspect, coffspect_grad, ds, coff, coffgrad,
Yan's avatar
Yan committed
180
             textfield, filename, parent)