prasopes.py 8.16 KB
Newer Older
Yan's avatar
Yan committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python3

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.widgets import SpanSelector
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from rawFin import load_raw
from scipy.signal import find_peaks
import sys
import matplotlib
import numpy as np
import logging
matplotlib.use("Qt5Agg")


17
18
def zoom_factory(ax, base_scale, plot=None, an=None):
    def zoom_fun(event, plot, an):
Yan's avatar
Yan committed
19
20
        if event.inaxes == ax:
            if event.button == 'up':
21
                #zoom in
Yan's avatar
Yan committed
22
23
                scale_factor = 1/base_scale
            elif event.button == 'down':
24
                #zoom out
Yan's avatar
Yan committed
25
26
                scale_factor = base_scale
            else:
27
                #should not happen
Yan's avatar
Yan committed
28
29
                scale_factor = 1
                print(event.button)
30
31
32
33
34
35
36
37
38
39
40

            if event.key == 'shift':
                data = event.ydata
                newtop = data + (ax.get_ylim()[1] - data)*scale_factor
                ax.set_ylim([newtop*-0.01,newtop])
            else:
                data = event.xdata
                xleft = data - ax.get_xlim()[0]
                xright = ax.get_xlim()[1] - data
                ax.set_xlim([data - xleft*scale_factor,
                            data + xright*scale_factor])
41
42
43
            if an != None:
                if type(plot['x']) != type(None):
                    annSpectr(event.inaxes,plot['x'], plot['y'], an)
44
            ax.figure.canvas.draw()
Yan's avatar
Yan committed
45
46
47

    fig = ax.get_figure()  # get the figure of interest
    # attach the call back
48
    fig.canvas.mpl_connect('scroll_event', lambda event: zoom_fun(event, plot, an))
Yan's avatar
Yan committed
49
50
51
52
53

    # return the function
    return zoom_fun


54
def pan_factory(ax, plot=None, an=None):
Yan's avatar
Yan committed
55
56
57
58
59
    def pan_fun(event):
        if event.button == 1 and event.inaxes == ax:
            ax.start_pan(event.x, event.y, event.button)
            id_drag = fig.canvas.mpl_connect('motion_notify_event', drag_fun)
            id_release = fig.canvas.mpl_connect('button_release_event',
60
                                                lambda action: drag_end(action, id_drag, id_release, plot, an))
Yan's avatar
Yan committed
61
62
63
64
65

    def drag_fun(event):
        ax.drag_pan(1, 'x', event.x, event.y)
        ax.figure.canvas.draw()

66
    def drag_end(event, id_drag, id_release, plot, an):
Yan's avatar
Yan committed
67
68
69
        if event.button == 1:
            fig.canvas.mpl_disconnect(id_drag)
            fig.canvas.mpl_disconnect(id_release)
70
71
72
73
            if an != None:
                if type(plot['x']) != type(None):
                    annSpectr(event.inaxes,plot['x'], plot['y'], an)
            ax.figure.canvas.draw()
Yan's avatar
Yan committed
74
75
76
77
    fig = ax.get_figure()
    fig.canvas.mpl_connect('button_press_event', pan_fun)


78
def picktimes(xmin, xmax, mplspectrum, dataset, mplchromatogram, an, ms_s):
Yan's avatar
Yan committed
79
80
81
82
83
84
85
86
    start_scan = 0
    end_scan = -1
    for i, j in enumerate(dataset['chromdat'][0, :]):
        if j > xmin and start_scan == 0:
            start_scan = i
        if j > xmax and end_scan == -1:
            end_scan = i
    mplspectrum.clear()
87
88
89
90
    an.clear()
    ms_s['x'] = dataset['masses']
    ms_s['y'] = np.mean(dataset['matrix'][start_scan:end_scan], axis=0) 
    spectrPlot(spectrum, ms['x'], ms['y'], an)
Yan's avatar
Yan committed
91
92
93
94
    mplchromatogram.clear()
    chromPlot(mplchromatogram, dataset['chromdat'][0, :], dataset['chromdat'][1, :])
    mplchromatogram.plot(dataset['chromdat'][0, start_scan:end_scan], dataset['chromdat'][1, start_scan:end_scan], 'b.')

95
96
97
98
def populate(mplchromatogram, mplspectrum, dataset, timeSel,an, ms_s):
    an.clear()
    def updateSpanSelector(chromatogram, spectrum, dataset, ms_s):
        timeselec = SpanSelector(chromatogram, lambda xmin, xmax: picktimes(xmin, xmax, spectrum, dataset, chromatogram, an, ms_s), 'horizontal', useblit=True, rectprops=dict(alpha=0.15, facecolor='purple'),button=3)
Yan's avatar
Yan committed
99
100
101
        return timeselec
    mplspectrum.clear()
    mplchromatogram.clear()
102
103
104
    ms_s['x'] = dataset['masses']
    ms_s['y'] = np.mean(dataset['matrix'], axis=0)
    spectrPlot(mplspectrum,ms_s['x'], ms_s['y'], an)
Yan's avatar
Yan committed
105
    chromPlot(mplchromatogram, dataset['chromdat'][0,:],dataset['chromdat'][1,:])
106
    timeSel[0] = updateSpanSelector(mplchromatogram, mplspectrum, ds, ms_s)
Yan's avatar
Yan committed
107
108
109
110
111
112
113
    mplchromatogram.figure.canvas.draw()
    mplspectrum.figure.canvas.draw()

def annSpectr(spectrum,mass,intensity,an):
    def sub_peaks(peakz,mass,intensity,x,y):
        gp=[]
        sp=[]
114
        for g in peakz:#[0]:
Yan's avatar
Yan committed
115
116
117
118
119
            if gp == [] or (abs(max(intensity[gp]) - intensity[g])*10 < y and abs(mass[gp[np.argmax(intensity[gp])]] - mass[g])*20 < x ):
                gp.append(g)
            else:
                sp.append(gp[np.argmax(intensity[gp])])
                gp = [g]
120
            if g == peakz[-1]:#[0][-1]:
Yan's avatar
Yan committed
121
122
                sp.append(gp[np.argmax(intensity[gp])])
        return sp
123
124
125
126
127
128
129
130
131

    borders=spectrum.get_xlim()
    start = np.argmax(mass>borders[0])
    end = np.argmax(mass>borders[1])
    if end == 0:
        end = np.argmax(mass)
    #peaks = find_peaks(intensity, height=spectrum.get_ylim()[1]/100)
    peaks = find_peaks(intensity[start:end], height=spectrum.get_ylim()[1]/100)
    peaks = peaks[0] + start
Yan's avatar
Yan committed
132
    sp = sub_peaks(peaks,mass,intensity,spectrum.get_xlim()[1]-spectrum.get_xlim()[0],spectrum.get_ylim()[1]-spectrum.get_ylim()[0])
133
134
135
136
    
    for j in an:
        j.remove()
    an.clear()
Yan's avatar
Yan committed
137
138
139
140
141
142
143
144
145

    for i in sp:
        an.append(spectrum.annotate('{0:.2f}'.format(mass[i]), xy=(mass[i],intensity[i]),textcoords='data'))

def spectrPlot(spetrum,mass,intensity, an):
    spectrum.plot(mass,intensity)
    spectrum.set_title("Spectrum:", loc = "right")
    spectrum.set_xlabel("m/z")
    spectrum.set_ylabel("ion count")
146
    spectrum.set_ylim(spectrum.get_ylim()[1]*-0.01,)
Yan's avatar
Yan committed
147
148
149
150
151
    spectrum.ticklabel_format(scilimits=(0,0),axis='y')
    annSpectr(spectrum, mass, intensity, an)

def chromPlot(chromatogram,times,tic):
    chromatogram.plot(times,tic)
152
    chromatogram.set_ylim(chromatogram.get_ylim()[1]*-0.011,chromatogram.get_ylim()[1]*1.1)
Yan's avatar
Yan committed
153
154
155
156
157
    chromatogram.set_title("Chromatogram:", loc = "right")
    chromatogram.set_xlabel("time (min)")
    chromatogram.set_ylabel("total ion count")
    chromatogram.ticklabel_format(scilimits=(0,0),axis='y')

158
def openFile(cromatogram, spectrum, ds, timeSel, an, ms_s):
Yan's avatar
Yan committed
159
160
161
162
    filename=QtWidgets.QFileDialog.getOpenFileName(caption = "Open spectrum", filter="Finnigan RAW files (*.raw, *.RAW)")[0]
    if filename is '':
        return
    ds['chromdat'],ds['masses'],ds['matrix'] = load_raw(filename)
163
    populate(chromatogram, spectrum, ds, timeSel, an, ms_s)
Yan's avatar
Yan committed
164
165
166
167
168


if __name__=="__main__":
    #ds for data_set
    ds = dict(chromdat=None,masses=None,matrix=None)
169
170
    #mass spectrometry set
    ms = dict(x=None,y=None)
Yan's avatar
Yan committed
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

    nlogger = logging.getLogger('parseLogger')
    logging.basicConfig()
    nlogger.setLevel("WARN")

    graph = Figure(figsize=(5,4),dpi=100)
    graph.patch.set_facecolor("None")

    chromatogram = graph.add_subplot(211,facecolor=(1,1,1,0.8))
    spectrum = graph.add_subplot(212,facecolor=(1,1,1,0.8))
    graph.tight_layout()

    mpl_canvas = FigureCanvas(graph)
    mpl_canvas.setStyleSheet("background-color:transparent;")
    mpl_canvas.setAutoFillBackground(False)
186
    mpl_canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
Yan's avatar
Yan committed
187
188
189
190
    
    timeSelector=[None]
    annotation=[]

191
    pan_factory(chromatogram)
Yan's avatar
Yan committed
192
    zoom_factory(chromatogram, 1.15)
193
194
    pan_factory(spectrum, ms, annotation)
    zoom_factory(spectrum, 1.15, ms, annotation)
Yan's avatar
Yan committed
195
196
197
198
199
200

    app = QtWidgets.QApplication(sys.argv)
    main_window = QtWidgets.QMainWindow()

    file_menu = QtWidgets.QMenu('&File',main_window)
    main_window.menuBar().addMenu(file_menu)
201
    file_menu.addAction('&Open..', lambda: openFile(chromatogram,spectrum, ds, timeSelector,annotation, ms), QtCore.Qt.CTRL + QtCore.Qt.Key_O)
Yan's avatar
Yan committed
202
203
204
205
206
207
208
    file_menu.addAction('&Quit', main_window.close, QtCore.Qt.CTRL + QtCore.Qt.Key_Q)

    main_widget = QtWidgets.QWidget(main_window)
    main_window.setCentralWidget(main_widget)

    layout = QtWidgets.QVBoxLayout(main_widget)
    layout.addWidget(mpl_canvas)
209
    mpl_canvas.setFocus()
Yan's avatar
Yan committed
210
211
212
213

    try:
        rawfile=sys.argv[1]
        ds['chromdat'],ds['masses'],ds['matrix'] = load_raw(rawfile)
214
        populate(chromatogram, spectrum, ds, timeSelector,annotation, ms)
Yan's avatar
Yan committed
215
    except:
216
217
        spectrPlot(spectrum, [0], [0], annotation)
        chromPlot(chromatogram, [0], [0])
Yan's avatar
Yan committed
218
219
220
221

    main_window.show()
    sys.exit(app.exec_())