Commit 53fbd3af authored by 3Yan's avatar 3Yan
Browse files

Added manual annotation, reduced threading

* removed threading which was problematic
* added support for manual annotation
* printing now in constrained layout
parent 90781676
......@@ -202,7 +202,7 @@ def main():
ds = []
ms = dict(annotation=[], name="Spectrum", xlabel="m/z",
ylabel="ion count", xtics=20, predict=None,
params=[], headers=[])
params=[], headers=[], texts=[])
chrom = dict(x=[0], y=[0], t_start=None, t_end=None,
name="Chromatogram", xlabel="time(min)",
ylabel="total ion count", timesarg=[])
......@@ -248,6 +248,7 @@ def main():
gt.zoom_factory(chromatogram, 1.15)
gt.pan_factory(spectrum, ms)
gt.zoom_factory(spectrum, 1.15, ms)
gt.textedit_factory(spectrum, ms)
mass_selector = SpanSelector(
spectrum, lambda x_min, x_max: gt.pick_masses(
x_min, x_max, spectrum, ms), 'horizontal', minspan=0.01,
......@@ -410,12 +411,6 @@ def main():
update, config, loadthread, filename=fileModel.filePath(index))
for i in [treeview.doubleClicked, dirview.doubleClicked, dirview.clicked]:
i.connect(clickload)
#fileModel gots stuck sometimes, better give it a separate thread
#it complains at the start, but still works later
#and I did not found better solution
treedockThread = QtCore.QThread()
treedockThread.start()
fileModel.moveToThread(treedockThread)
def closeOverride(event, dock, action):
action.setChecked(False)
dock.hide()
......
import numpy as np
import prasopes.datatools as dt
import prasopes.config as cf
import matplotlib
from PyQt5 import QtWidgets
from PyQt5 import QtCore
......@@ -10,6 +11,7 @@ colors = np.array([[0, 0, 0], [255, 0, 0], [0, 255, 0], [0, 0, 255],
[200, 50, 0], [255, 0, 200], [0, 100, 0],
[0, 100, 255], [100, 100, 100]])
ann_bbox = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.5)
def zoom_factory(axis, base_scale, plot_data=None):
"""returns zooming functionality to axis"""
......@@ -92,6 +94,28 @@ def pan_factory(axis, plot=None):
lambda action: pan_fun(action, axis, plot))
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(
None,"Enter new annotation","",
text=annotation.get_text())
if textdial[1] == True:
annotation.set_text(textdial[0])
if len(textdial[0]) != 0:
annotation.set_bbox(ann_bbox)
if annotation in plot_data['annotation']:
plot_data['annotation'].remove(annotation)
plot_data['texts'].append(annotation)
if len(textdial[0]) == 0 and annotation in plot_data['texts']:
plot_data['texts'].remove(annotation)
axis.figure.canvas.draw()
axis.figure.canvas.mpl_connect('pick_event', annpicked)
def pick_masses(x_min, x_max, ms_spec, msdata):
"""zoom the spectrum in x axis by mass range"""
ms_spec.set_xlim(x_min, x_max)
......@@ -212,16 +236,20 @@ def ann_spec(ms_spec, msdata, ann_limit=0.01):
reduced to a representation of the important ones by the sub_peaks
function"""
def sub_peaks(peakz, xrange, yrange, coef_x=10, coef_y=10):
def sub_peaks(peakz, hardpeaks, xrange, yrange, coef_x=10, coef_y=10):
"""Returns reasonable subselection of local maximas"""
hardxy = np.array(([i.xy for i in hardpeaks]), dtype=[
('x', float),('y', float)])
sort_peaks = np.flipud(np.sort(np.array(peakz, dtype=[
('x', float),('y', float)]), order='y')).copy()
red_x = xrange / coef_x
red_y = yrange / coef_y
big_peaks = np.array([], dtype=[('x', float),('y', float)])
for peak in np.nditer(sort_peaks, flags=["zerosize_ok"]):
if not np.any((abs(peak['y'] - big_peaks['y']) < red_y) \
& (abs(peak['x'] - big_peaks['x']) < red_x)):
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)
return big_peaks
......@@ -236,8 +264,8 @@ def ann_spec(ms_spec, msdata, ann_limit=0.01):
for i in argvis:
if ydata[i] > lim and ydata[i] > max(ydata[i-1], ydata[i+1]):
peaks.append((xdata[i],ydata[i]))
s_peaks = sub_peaks(peaks, np.diff(ms_spec.get_xlim()),
np.diff(ms_spec.get_ylim()))
s_peaks = sub_peaks(peaks, msdata['texts'],
np.diff(ms_spec.get_xlim()), np.diff(ms_spec.get_ylim()))
# delete objects from the spectra
for intensity in msdata['annotation']:
......@@ -250,8 +278,9 @@ def ann_spec(ms_spec, msdata, ann_limit=0.01):
annotation = '{0:.2f}\n{1: .2e}'.format(peak['x'], peak['y'])
else:
annotation = '{0:.2f}'.format(peak['x'])
msdata['annotation'].append(ms_spec.annotate(annotation,
xy=(peak['x'], peak['y']), textcoords='data'))
peaktext = ms_spec.annotate(annotation,
xy=(peak['x'], peak['y']), textcoords='data', picker = True)
msdata['annotation'].append(peaktext)
def pop_plot(xdata, ydata, plot, plot_data, colornum=0, legend=None):
......@@ -264,6 +293,12 @@ def pop_plot(xdata, ydata, plot, plot_data, colornum=0, legend=None):
plot.set_ylim(plot.get_ylim()[1] * -0.01,
plot.get_ylim()[1] * 1.1)
plot.ticklabel_format(scilimits=(0, 0), axis='y')
if "texts" in plot_data:
oldtexts = plot_data['texts']
plot_data['texts'] = [plot.annotate(
a.get_text(),a.xy, picker=True, bbox=ann_bbox)
for a in oldtexts]
plot_data['texts'] = oldtexts
if "annotation" in plot_data:
ann_spec(plot, plot_data)
if "xtics" in plot_data:
......
......@@ -18,7 +18,7 @@ def paint_image(mass_spec, spect, painttarget=None):
else:
xinch, yinch, dpi, xtics = [cf.settings().value("imggen/{}".format(i),
type=int) for i in ("xinch", "yinch", "dpi", "xtics")]
paintfig = Figure(figsize=(xinch, yinch), dpi=dpi)
paintfig = Figure(figsize=(xinch, yinch), dpi=dpi, constrained_layout=True)
canvas = FigureCanvas(paintfig)
printplot = paintfig.add_subplot(111)
printplot.set_xlim(spect.get_xlim())
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment