graphtools.py 20.2 KB
Newer Older
Yan's avatar
Yan committed
1
2
from PyQt5 import QtWidgets
from PyQt5 import QtCore
3
4
5
from matplotlib.backends.backend_qt5agg import\
    FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
Yan's avatar
Yan committed
6
from matplotlib.widgets import SpanSelector
Yan's avatar
Yan committed
7
import numpy as np
Yan's avatar
Yan committed
8
import prasopes.datatools as dt
Yan's avatar
Yan committed
9
import prasopes.config as cf
10
import matplotlib
11
matplotlib.use("Qt5Agg")
Yan's avatar
Yan committed
12

Yan's avatar
Yan committed
13

3Yan's avatar
3Yan committed
14
15
16
17
18
colors = np.array([[0, 0, 0], [255, 0, 0], [0, 255, 0], [0, 0, 255],
                   [0, 200, 255], [255, 200, 0], [255, 100, 0],
                   [200, 50, 0], [255, 0, 200], [0, 100, 0],
                   [0, 100, 255], [100, 100, 100]])

19

20
ann_bbox = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.5)
3Yan's avatar
3Yan committed
21

22

23
24
25
26
27
28
class AugFigureCanvas(FigureCanvas):
    """Figure canvas fitted with mass spectrum, chromatogram and more"""
    def __init__(self):
        self.figure = Figure(figsize=(5, 4), dpi=100, facecolor="None",
                             constrained_layout=True)
        super().__init__(self.figure)
Yan's avatar
Yan committed
29
        self.ds = None
30
        self.ms = dict(annotation=[], name="Spectrum", xlabel="m/z",
Yan's avatar
Yan committed
31
                       ylabel="ion count", xtics=20, predict=None, texts=[])
32
33
34
35
36
        self.chrom = dict(
            x=[0], y=[0], t_start=None, t_end=None, machtype=None,
            name="Chromatogram", xlabel="time(min)", ylabel="total ion count",
            timesarg=[])
        self.drlcache = [None, None]
Yan's avatar
Yan committed
37
        self.tofcache = [None, None]
38
39
40
41
42
43
44
45
46
        grid = self.figure.add_gridspec(2, 1)
        self.chromplot = self.figure.add_subplot(grid[0, 0],
                                                 facecolor=(1, 1, 1, 0.8))
        self.spectplot = self.figure.add_subplot(grid[1, 0],
                                                 facecolor=(1, 1, 1, 0.8))
        self.setStyleSheet("background-color:transparent;")
        self.setAutoFillBackground(False)
        self.paramstable = dt.table(["", "name", "value"], 100)
        pan_factory(self.chromplot)
3Yan's avatar
3Yan committed
47
        zoom_factory(self.chromplot, 0.9)
48
        pan_factory(self.spectplot, self.ms)
3Yan's avatar
3Yan committed
49
        zoom_factory(self.spectplot, 0.9, self.ms)
50
51
52
53
54
55
        textedit_factory(self.spectplot, self.ms)
        self.mass_selector = AugSpanSelector(self.spectplot, self.ms)
        self.time_selector = SpanSelector(
                self.chromplot, lambda x_min, x_max: pick_times(
                    x_min, x_max, self), 'horizontal', useblit=True,
                rectprops=dict(alpha=0.15, facecolor='purple'), button=3)
Yan's avatar
Yan committed
56
57
58
59
60
        self.figure.set_constrained_layout(False)

    def constrained_draw(self):
        self.figure.execute_constrained_layout()
        self.draw()
61
62


Yan's avatar
Yan committed
63
64
class AugSpanSelector(SpanSelector):
    def __init__(self, ax, data):
65
66
67
68
69
        super().__init__(
            ax, onselect=lambda x, y: None, direction='horizontal',
            minspan=0.01, useblit=True, rectprops=dict(
                alpha=0.15, facecolor='purple'),
            onmove_callback=None, span_stays=False, button=3)
Yan's avatar
Yan committed
70
        self.data = data
71

Yan's avatar
Yan committed
72
73
74
75
76
77
78
79
80
81
    def _press(self, event):
        """on button press event override"""
        if QtWidgets.QApplication.keyboardModifiers() ==\
                QtCore.Qt.ShiftModifier:
            self.direction = 'vertical'
            self.onselect = self.pick_intensities
        else:
            self.direction = 'horizontal'
            self.onselect = self.pick_masses
        self.new_axes(self.ax)
82
        super()._press(event)
Yan's avatar
Yan committed
83

84
85
86
87
88
    def _release(self, event):
        """on button release event"""
        if self.pressv is None:
            return
        elif self.direction == 'horizontal':
89
            super()._release(event)
90
91
92
93
94
95
96
97
98
99
100
101
102
103
        else:
            self.rect.set_visible(False)
            self.canvas.draw_idle()
            vmax = self._get_data(event)[1] or self.prev[1]
            span = vmax - self.ax.get_ylim()[0]
            if self.minspan is not None and span < self.minspan:
                return
            self.onselect(self.ax.get_ylim()[0], vmax)
            self.pressv = None
            return False

    def _set_span_xy(self, event):
        """Setting the span coordinates override"""
        if self.direction == 'horizontal':
104
            super()._set_span_xy(event)
105
        else:
106
            x, y = self._get_data(event)
107
108
109
110
111
            if y is None:
                return
            self.prev = x, y
            self.rect.set_y(self.ax.get_ylim()[0])
            self.rect.set_height(y)
Yan's avatar
Yan committed
112
113
114
115
116
117
118
119
120
121
122

    def pick_masses(self, vmin, vmax):
        """zoom the spectrum in x axis by mass range"""
        self.ax.set_xlim(vmin, vmax)
        autozoomy(self.ax)
        ann_spec(self.ax, self.data)

    def pick_intensities(self, vmin, vmax):
        """zoom the spectrum in y axis by top intensity from range"""
        self.ax.set_ylim(-vmax*0.01, vmax)
        ann_spec(self.ax, self.data)
Yan's avatar
Yan committed
123
124


Yan's avatar
Yan committed
125
126
127
class FixedScalarFormatter(matplotlib.ticker.ScalarFormatter):
    def __init__(self):
        super().__init__()
Yan's avatar
Yan committed
128
        self._powerlimits = (0, 0)
Yan's avatar
Yan committed
129
130
131
132
133
134

    def _set_format(self):
        """_set_format override"""
        self.format = "%.2f"


Yan's avatar
Yan committed
135
def zoom_factory(axis, base_scale, plot_data=None):
Yan's avatar
Yan committed
136
    """returns zooming functionality to axis"""
Yan's avatar
Yan committed
137
    def zoom_fun(event, pd, ax, scale):
Yan's avatar
Yan committed
138
        """zoom when scrolling"""
Yan's avatar
Yan committed
139
        if event.inaxes == axis:
3Yan's avatar
3Yan committed
140
            scale_factor = np.power(scale, event.step)
141
            if QtWidgets.QApplication.keyboardModifiers() !=\
Yan's avatar
Yan committed
142
                    QtCore.Qt.ShiftModifier:
143
                data = event.ydata
Yan's avatar
Yan committed
144
145
                new_top = data + (ax.get_ylim()[1] - data) \
                    * scale_factor
Yan's avatar
Yan committed
146
147
148
149
                ymin = -0.01
                if type(pd) is dict and "c_ymin" in pd:
                    ymin = pd['c_ymin']
                axis.set_ylim([new_top * ymin, new_top])
150
151
            else:
                data = event.xdata
Yan's avatar
Yan committed
152
153
                x_left = data - ax.get_xlim()[0]
                x_right = ax.get_xlim()[1] - data
Yan's avatar
Yan committed
154
                ax.set_xlim([data - x_left * scale_factor,
Yan's avatar
Yan committed
155
                            data + x_right * scale_factor])
Yan's avatar
Yan committed
156
            if type(pd) is dict and "annotation" in pd:
Yan's avatar
Yan committed
157
                ann_spec(event.inaxes, pd)
158
            ax.figure.canvas.draw()
Yan's avatar
Yan committed
159

Yan's avatar
Yan committed
160
    fig = axis.get_figure()
161
    fig.canvas.mpl_connect('scroll_event', lambda event: zoom_fun(
3Yan's avatar
3Yan committed
162
        event, plot_data, axis, base_scale))
Yan's avatar
Yan committed
163
164


Yan's avatar
Yan committed
165
def pan_factory(axis, plot=None):
Yan's avatar
Yan committed
166
    """pan spectrum when you press a button"""
Yan's avatar
Yan committed
167
    def pan_fun(event, ax, pd):
168
        # Release focus from other objects when clicking on graph.
Yan's avatar
Yan committed
169
        focusedWidget = QtWidgets.QApplication.focusWidget()
170
        if focusedWidget and event.inaxes == ax:
Yan's avatar
Yan committed
171
            focusedWidget.clearFocus()
Yan's avatar
Yan committed
172
        # re-scale to origin if doubleclicked
Yan's avatar
Yan committed
173
174
175
        if event.dblclick and event.inaxes == ax:
            ax.get_figure()
            ax.autoscale(True)
Yan's avatar
Yan committed
176
177
178
179
            ymin = -0.01
            if type(pd) is dict and "c_ymin" in pd:
                ymin = pd['c_ymin']
            ax.set_ylim(ax.get_ylim()[1]*ymin, ax.get_ylim()[1]*1.1)
Yan's avatar
Yan committed
180
181
            if type(pd) is dict and "annotation" in pd:
                ann_spec(ax, pd)
Yan's avatar
Yan committed
182
            ax.figure.canvas.draw()
Yan's avatar
Yan committed
183
        # otherwise pan
Yan's avatar
Yan committed
184
        elif event.button == 1 and event.inaxes == ax:
Yan's avatar
Yan committed
185
            ax.start_pan(event.x, event.y, event.button)
Yan's avatar
Yan committed
186
187
188
            id_drag = fig.canvas.mpl_connect(
                'motion_notify_event',
                lambda action: drag_fun(action, ax))
Yan's avatar
Yan committed
189
            id_release = fig.canvas.mpl_connect(
Yan's avatar
Yan committed
190
191
                'button_release_event',
                lambda action: drag_end(
Yan's avatar
Yan committed
192
                    action, id_drag, id_release, pd, ax))
Yan's avatar
Yan committed
193

194
    def drag_fun(event, ax):
Yan's avatar
Yan committed
195
196
197
        ax.drag_pan(1, 'x', event.x, event.y)
        ax.figure.canvas.draw()

Yan's avatar
Yan committed
198
    def drag_end(event, id_drag, id_release, pd, ax):
Yan's avatar
Yan committed
199
200
201
        if event.button == 1:
            fig.canvas.mpl_disconnect(id_drag)
            fig.canvas.mpl_disconnect(id_release)
Yan's avatar
Yan committed
202
203
            if type(pd) is dict and "annotation" in pd:
                ann_spec(ax, pd)
204
            ax.figure.canvas.draw()
Yan's avatar
Yan committed
205

Yan's avatar
Yan committed
206
    fig = axis.get_figure()
Yan's avatar
Yan committed
207
    fig.canvas.mpl_connect('button_press_event',
Yan's avatar
Yan committed
208
                           lambda action: pan_fun(action, axis, plot))
Yan's avatar
Yan committed
209

Yan's avatar
Yan committed
210

211
212
213
214
215
216
def textedit_factory(axis, plot_data):
    def annpicked(pickevent):
        if isinstance(pickevent.artist, matplotlib.text.Annotation) and\
                pickevent.mouseevent.button == 2:
            annotation = pickevent.artist
            textdial = QtWidgets.QInputDialog.getText(
217
                    None, "Enter new annotation", "",
218
                    text=annotation.get_text())
219
220
            if textdial[1]:
                annotation.set_text(textdial[0].replace('\\n', '\n'))
221
222
                if len(textdial[0]) == 0 and annotation in plot_data['texts']:
                    plot_data['texts'].remove(annotation)
3Yan's avatar
3Yan committed
223
                elif annotation in plot_data['annotation']:
224
225
226
                    annotation.set_bbox(ann_bbox)
                    plot_data['annotation'].remove(annotation)
                    plot_data['texts'].append(annotation)
3Yan's avatar
3Yan committed
227
                axis.figure.canvas.draw()
228
229
230
231

    axis.figure.canvas.mpl_connect('pick_event', annpicked)


232
def plot_subtime(augCanvas):
Yan's avatar
Yan committed
233
    """plot averaged spectrum of subselected part of the chromatogram"""
234
235
236
237
238
239
    slims = [augCanvas.spectplot.get_xlim(), augCanvas.spectplot.get_ylim()]
    chlims = [augCanvas.chromplot.get_xlim(), augCanvas.chromplot.get_ylim()]
    augCanvas.ms['annotation'].clear()
    augCanvas.spectplot.clear()
    augCanvas.chromplot.clear()

Yan's avatar
Yan committed
240
241
242
243
244
    chromargs = augCanvas.ds.get_chromargs()
    populate(augCanvas)

    for i, args in enumerate(chromargs):
        if len(args):
Yan's avatar
Yan committed
245
            dots_x, dots_y = [augCanvas.ds.chromatograms[i][j][args]
Yan's avatar
Yan committed
246
                              for j in (0, 1)]
Yan's avatar
Yan committed
247
            augCanvas.chromplot.plot(dots_x, dots_y, '.', color=(
Yan's avatar
Yan committed
248
                                     colors[i % len(colors)]/255))
249

250
    augCanvas.spectplot.set_xlim(slims[0])
Yan's avatar
Yan committed
251
    if not cf.settings().value("view/autozoomy", type=bool):
252
        augCanvas.spectplot.set_ylim(slims[1])
Yan's avatar
Yan committed
253
    if augCanvas.ds.headers:
Yan's avatar
Yan committed
254
255
256
257
258
        for ax in (augCanvas.spectplot, augCanvas.chromplot):
            ax.legend(loc=2)
            ax.get_legend().set_in_layout(False)
            ax.get_legend().set_visible(
                    cf.settings().value("view/legend", type=bool))
Yan's avatar
Yan committed
259
    else:
260
261
262
263
        autozoomy(augCanvas.spectplot)
    ann_spec(augCanvas.spectplot, augCanvas.ms)
    augCanvas.chromplot.set_xlim(chlims[0])
    augCanvas.chromplot.set_ylim(chlims[1])
264
    augCanvas.draw()
Yan's avatar
Yan committed
265
    update_paramstable(augCanvas)
266
267


268
def pick_times(x_min, x_max, augCanvas):
269
    """subselect part of the chromatogram and plot it"""
Yan's avatar
Yan committed
270
271
    augCanvas.ds.mintime = x_min
    augCanvas.ds.maxtime = x_max
Yan's avatar
Yan committed
272
    plot_subtime(augCanvas)
273
274


275
def shift_times(event, augCanvas):
Yan's avatar
Yan committed
276
277
278
279
280
281
282
    """shifts times when arrow is pressed"""
    if event.key() == QtCore.Qt.Key_Left:
        move = -1
    elif event.key() == QtCore.Qt.Key_Right:
        move = +1
    else:
        return
283
284
285
286
    if not np.array_equal(augCanvas.chrom['timesarg'], []):
        x_min, x_max = augCanvas.chrom['t_start'], augCanvas.chrom['t_end']
        alltimes = np.concatenate([subset['chrom_dat'][0] for subset
                                   in augCanvas.ds])
Yan's avatar
Yan committed
287
        times = dt.argsubselect(alltimes, x_min, x_max) + move
288
        goodtimes = np.where((times < len(alltimes)) & ~(times < 0))[0]
Yan's avatar
Yan committed
289
        if not np.array_equal(goodtimes, []):
290
            x_min, x_max = alltimes[times[goodtimes[[0, -1]]]]
291
            pick_times(x_min, x_max, augCanvas)
Yan's avatar
Yan committed
292

Yan's avatar
Yan committed
293

294
def autozoomy(ms_spec):
3Yan's avatar
3Yan committed
295
    if cf.settings().value("view/autozoomy", type=bool) and not (
296
297
            np.array_equal(ms_spec.lines[0].get_xdata(), [0]) and
            len(ms_spec.lines) == 1):
Yan's avatar
Yan committed
298
        ms_spec.autoscale(True, 'y')
3Yan's avatar
3Yan committed
299
300
        gap = 0.01
        ymax = np.max([np.max(line.get_data()[1][dt.argsubselect(
Yan's avatar
Yan committed
301
            line.get_data()[0], *ms_spec.get_xlim())])*1.1
3Yan's avatar
3Yan committed
302
            for line in ms_spec.lines])
Yan's avatar
Yan committed
303
        ms_spec.set_ylim(-ymax*gap, ymax)
3Yan's avatar
3Yan committed
304
        ms_spec.figure.canvas.draw()
Yan's avatar
Yan committed
305

306

Yan's avatar
Yan committed
307
def ann_spec(ms_spec, msdata, ann_limit=0.01):
Yan's avatar
Yan committed
308
    """annotate spectrum
309
310

    First define the array, in which the annotation should occur.
Yan's avatar
Yan committed
311
312
    Then remove values which are invalid as local maximas. Local maximas are
    then reduced to a representation of the important ones by the sub_peaks
313
    function"""
314

3Yan's avatar
3Yan committed
315
    def sub_peaks(peakz, hardpeaks, xrange, yrange, coef_x=15, coef_y=20):
Yan's avatar
Yan committed
316
        """Returns reasonable subselection of local maximas"""
Yan's avatar
Yan committed
317
318
        hardxy = np.array([i.xy for i in hardpeaks], dtype=[
            ('x', np.float32), ('y', np.float32)])
3Yan's avatar
3Yan committed
319
        sort_peaks = np.flipud(np.sort(np.array(peakz), order='y')).copy()
Yan's avatar
Yan committed
320
321
        red_x = xrange / coef_x
        red_y = yrange / coef_y
Yan's avatar
Yan committed
322
        big_peaks = np.array([], dtype=[('x', np.float32), ('y', np.float32)])
3Yan's avatar
3Yan committed
323
        for peak in np.nditer(sort_peaks, flags=["zerosize_ok"]):
324
325
326
327
328
            if not (np.any((abs(peak['y'] - big_peaks['y']) < red_y)
                           & (abs(peak['x'] - big_peaks['x']) < red_x)) or
                    np.any((abs(peak['y'] - hardxy['y']) < red_y)
                           & (abs(peak['x'] - hardxy['x']) < red_x))):
                big_peaks = np.append(big_peaks, peak)
329
330
        return big_peaks

Yan's avatar
Yan committed
331
    peaks = []
3Yan's avatar
3Yan committed
332
333
    for line in ms_spec.lines:
        xdata, ydata = line.get_data()
Yan's avatar
Yan committed
334
335
336
        # Thanks to:
        # https://gist.github.com/ben741/d8c70b608d96d9f7ed231086b237ba6b
        minlim = ms_spec.get_ylim()[1] * ann_limit
Yan's avatar
Yan committed
337
        lims = [*ms_spec.get_xlim(), *ms_spec.get_ylim()]
Yan's avatar
Yan committed
338
339
340
341
        maxargs = np.where((xdata[1:-1] > lims[0]) & (xdata[1:-1] < lims[1]) &
                           (ydata[1:-1] > minlim) & (ydata[1:-1] < lims[3]) &
                           (ydata[1:-1] > ydata[0:-2]) &
                           (ydata[1:-1] > ydata[2:]))[0] + 1
Yan's avatar
Yan committed
342
343
        peakline = np.empty([len(maxargs)], dtype=[('x', np.float32),
                                                   ('y', np.float32)])
Yan's avatar
Yan committed
344
345
        peakline['x'], peakline['y'] = xdata[maxargs], ydata[maxargs]
        peaks.append(peakline)
Yan's avatar
Yan committed
346

Yan's avatar
Yan committed
347
    # delete objects from the spectra
Yan's avatar
Yan committed
348
    for intensity in msdata['annotation']:
Yan's avatar
Yan committed
349
        intensity.remove()
Yan's avatar
Yan committed
350
    # remove them from tracking
Yan's avatar
Yan committed
351
    msdata['annotation'].clear()
Yan's avatar
Yan committed
352

353
354
355
356
357
358
359
360
    if len(peaks) == 0:
        return
    peaks = np.concatenate(peaks)

    s_peaks = sub_peaks(peaks, msdata['texts'],
                        np.diff(ms_spec.get_xlim()),
                        np.diff(ms_spec.get_ylim()))

Yan's avatar
Yan committed
361
    dispints = cf.settings().value("view/intensities", type=bool)
362
    for peak in s_peaks:
Yan's avatar
Yan committed
363
364
        annotation = '{0:.2f}\n{1: .2e}'.format(peak[0], peak[1])\
                if dispints else '{0:.2f}'.format(peak[0])
365
366
367
        peaktext = ms_spec.annotate(
            annotation, xy=(peak['x'], peak['y']), textcoords='data',
            picker=True, in_layout=False)
368
        msdata['annotation'].append(peaktext)
369

Yan's avatar
Yan committed
370

Yan's avatar
Yan committed
371
372
def pop_plot(xdata, ydata, plot, plot_data, colornum=0,
             legend=None, annotate=True):
Yan's avatar
Yan committed
373
    """Define and populate plot"""
3Yan's avatar
3Yan committed
374
375
376
    if len(xdata):
        plot.plot(xdata, ydata, linewidth=1, color=(
            colors[colornum % len(colors)]/255), label=legend)
Yan's avatar
Yan committed
377
    plot.set_title(plot_data['name'], loc="right")
Yan's avatar
Yan committed
378
379
    plot.set_xlabel(plot_data['xlabel'])
    plot.set_ylabel(plot_data['ylabel'])
380
    plot.set_ylim(plot.get_ylim()[1] * -0.01,
Yan's avatar
Yan committed
381
                  plot.get_ylim()[1] * 1.1)
Yan's avatar
Yan committed
382
    plot.yaxis.set_major_formatter(FixedScalarFormatter())
383
    # put hardcoded annotation if there is some
3Yan's avatar
3Yan committed
384
385
    if "texts" in plot_data and not any(
            data in plot.get_children() for data in plot_data['texts']):
386
        plot_data['texts'] = [plot.annotate(
387
            a.get_text(), a.xy, picker=True, bbox=ann_bbox, in_layout=False)
3Yan's avatar
3Yan committed
388
            for a in plot_data['texts']]
Yan's avatar
Yan committed
389
390
    if "annotation" in plot_data and annotate:
        ann_spec(plot, plot_data)
Yan's avatar
Yan committed
391
392
393
394
395
    if "xtics" in plot_data:
        plot.locator_params(nbins=plot_data["xtics"], axis='x')
        plot.minorticks_on()
        plot.tick_params(axis='y', which='minor', left=False)

Yan's avatar
Yan committed
396

Yan's avatar
Yan committed
397
def legendize(rawlegend, augCanvas):
398
    # sanity check
Yan's avatar
Yan committed
399
400
    if len(rawlegend) == 0:
        return None
401
402
403
    marks = ["-", "+"]
    quads = ["q3", "q1"]

Yan's avatar
Yan committed
404
    def translate(wut):
Yan's avatar
Yan committed
405
        if augCanvas.ds.machtype == 47:
406
            if wut[1] in (0, 1):
407
408
409
410
411
                text = "{}{}ms; m/z = {:.1f}-{:.1f}".format(
                        marks[int(wut[0])], quads[int(wut[1])], *wut[4:])
            else:
                text = "{}ms^{} {:.2f}@{:.1f}V; m/z = {:.1f}-{:.1f}".format(
                        marks[int(wut[0])], *wut[1:])
Yan's avatar
Yan committed
412
        elif augCanvas.ds.machtype in (57, 63):
Yan's avatar
Yan committed
413
414
415
            if int(wut[1]) == 1:
                text = "{}ms; m/z = {:.1f}-{:.1f}".format(
                        marks[int(wut[0])], *wut[2:])
Yan's avatar
Yan committed
416
            else:
Yan's avatar
Yan committed
417
418
419
420
                text = ("{}ms^{:.0f};" + "".join([" {:.2f}/{:.1f}@{:.1f}V" for
                                                  _ in range(int(wut[1])-1)]) +
                        "; m/z = {:.1f}-{:.1f}").format(
                                marks[int(wut[0])], *wut[1:])
Yan's avatar
Yan committed
421
        else:
422
            text = "unknown header type"
Yan's avatar
Yan committed
423
        return text
Yan's avatar
Yan committed
424
425
426
427
    uniqindexs = np.unique(np.array(rawlegend), return_index=True)\
        if np.array(rawlegend).dtype == np.dtype('O') else\
        np.unique(np.array(rawlegend), axis=0, return_index=True)
    strdata = [translate(i) for i in rawlegend[np.sort(uniqindexs[1])]]
Yan's avatar
Yan committed
428
    strtext = " and\n".join(strdata) + "; t = {:.2f}-{:.2f} min".format(
Yan's avatar
Yan committed
429
                    augCanvas.ds.mintime, augCanvas.ds.maxtime)
Yan's avatar
Yan committed
430
431
432
    return strtext


433
def populate(augCanvas):
Yan's avatar
Yan committed
434
    """populate the GUI plots with desired dataset"""
435
    if np.array_equal(augCanvas.ds, []):
Yan's avatar
Yan committed
436
        return
437
    [i.clear() for i in (augCanvas.ms['annotation'],
438
     augCanvas.chromplot, augCanvas.spectplot)]
Yan's avatar
Yan committed
439

440
441
    if augCanvas.ms['predict']:
        # TODO: Fix the broken code
442
443
        predict = augCanvas.ms['predict']
        maxm = np.argmax(predict[1]) + predict[0]
3Yan's avatar
3Yan committed
444
445
        maxseek = dt.argsubselect(linex, maxm-.5, maxm+.5)
        maxpos = maxseek[np.argmax(liney[maxseek])]
446
        crudeints = predict[1] * augCanvas.ms['y'][maxpos]
447
        crudemasses = (np.arange(len(predict[1])) + linex[maxpos])
Yan's avatar
Yan committed
448
        pmasses, pints = [], []
449
450
        [pmasses.extend([np.nan, i, i]) for i in crudemasses]
        [pints.extend([np.nan, 0, i]) for i in crudeints]
451
        augCanvas.spectplot.plot(pmasses, pints, linewidth=1)
Yan's avatar
Yan committed
452

Yan's avatar
Yan committed
453
    chromxy = augCanvas.ds.chromatograms
Yan's avatar
Yan committed
454
455
    msxy = augCanvas.ds.get_spectra()
    for i in range(len(msxy)):
Yan's avatar
Yan committed
456
457
        if augCanvas.ds.headers and\
                len(augCanvas.ds.headers) == len(augCanvas.ds.chromatograms):
Yan's avatar
Yan committed
458
            legend = legendize(augCanvas.ds.headers[i], augCanvas)
Yan's avatar
Yan committed
459
460
        else:
            legend = None
Yan's avatar
Yan committed
461
462
        pop_plot(msxy[i][0], msxy[i][1], augCanvas.spectplot,
                 augCanvas.ms, i, legend)
Yan's avatar
Yan committed
463
        pop_plot(chromxy[i][0], chromxy[i][1], augCanvas.chromplot,
Yan's avatar
Yan committed
464
                 augCanvas.chrom, i, legend)
465
    for ax in (augCanvas.spectplot, augCanvas.chromplot):
Yan's avatar
Yan committed
466
        if augCanvas.ds.headers:
Yan's avatar
Yan committed
467
            ax.legend(loc=2)
Yan's avatar
Yan committed
468
            ax.get_legend().set_in_layout(False)
Yan's avatar
Yan committed
469
470
            ax.get_legend().set_visible(
                    cf.settings().value("view/legend", type=bool))
3Yan's avatar
3Yan committed
471
472
        ax.autoscale(True)
        ax.set_ylim(ax.get_ylim()[1]*-0.01, ax.get_ylim()[1]*1.1)
Yan's avatar
Yan committed
473
    augCanvas.constrained_draw()
3Yan's avatar
3Yan committed
474
    return
Yan's avatar
Yan committed
475
476


477
def update_paramstable(augCanvas):
Yan's avatar
Yan committed
478
    if not augCanvas.ds.params:
479
        augCanvas.paramstable.setRowCount(0)
Yan's avatar
Yan committed
480
        return
Yan's avatar
Yan committed
481
    elif len(augCanvas.ds.params[0]) == augCanvas.paramstable.rowCount():
482
483
484
485
        states = [augCanvas.paramstable.cellWidget(row, 0).checkState()
                  for row in range(augCanvas.paramstable.rowCount())]
    else:
        states = False
Yan's avatar
Yan committed
486
487
        augCanvas.paramstable.setRowCount(len(augCanvas.ds.params[0]))
    for row, paramname in enumerate(augCanvas.ds.params[0]):
488
489
490
        [augCanvas.paramstable.setItem(row, col, QtWidgets.QTableWidgetItem())
         for col in range(1, 3)]
        augCanvas.paramstable.setCellWidget(row, 0, QtWidgets.QCheckBox())
491
        if states:
492
493
            augCanvas.paramstable.cellWidget(row, 0).setCheckState(states[row])
        augCanvas.paramstable.item(row, 1).setText(paramname)
Yan's avatar
Yan committed
494
        vals = [param[row] for param in augCanvas.ds.params[1]
Yan's avatar
Yan committed
495
496
                if (param[0] >= augCanvas.ds.mintime and
                param[0] <= augCanvas.ds.maxtime)]
Yan's avatar
Yan committed
497
        if len(vals) == 0:
Yan's avatar
Yan committed
498
            text = ""
Yan's avatar
Yan committed
499
500
501
502
503
504
505
506
        elif all([type(val) in [np.float32, np.float64] for val in vals]):
            aver = np.average(vals)
            minim = min(vals)
            maxim = max(vals)
            text = "{:.2f} (from {:.2f} to {:.2f})".format(aver, minim, maxim)
        else:
            values = [str(i) for i in np.unique(np.array(vals), axis=0)]
            text = " or ".join(values)
507
        augCanvas.paramstable.item(row, 2).setText(text)