#!/usr/bin/env python
# encoding: utf-8
"""
A set of utilities to use spike in NMR or FTMS within jupyter
First version MAD june 2017
definitive ? version MAD october 2019
"""
from __future__ import print_function, division
import unittest
import sys
import os
import os.path as op
import glob
import matplotlib.pylab as plt
import matplotlib.gridspec as gridspec
from matplotlib.widgets import MultiCursor
from ipywidgets import fixed, Layout, HBox, VBox, Label, Output, Button, Tab
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
import numpy as np
from ..File.BrukerNMR import Import_1D
from .. import NPKData
from ..NMR import NMRData
try:
import spike.plugins.bcorr as bcorr
except:
print('Baseline correction plugins not installed !')
# REACTIVE modify callback behaviour
# True is good for inline mode / False is better for notebook mode
REACTIVE = True
HEAVY = False
[docs]def hidecode(initial='show', message=True):
"""
this func adds a button to hide/show the code on a jupyter page
initial is either 'show' or 'hide'
inspired from: https://stackoverflow.com/questions/27934885/how-to-hide-code-from-cells-in-ipython-notebook-visualized-with-nbviewer/28073228#28073228
"""
from IPython.display import display, HTML, Markdown
if initial == 'show':
init = 'false'
elif initial == 'hide':
init = 'true'
if message:
msg = "<i>usefull to show/print a clean screen when processing is finished</i>"
else:
msg = ""
display(HTML('''
<style>hr {height: 2px; border: 0;border-top: 1px solid #ccc;margin: 1em 0;padding: 0; }</style>
<script>
code_show=%s;
function code_toggle()
{ if (code_show)
{ $('div.input').hide(); $('#but').val("show python code");
} else { $('div.input').show(); $('#but').val("hide python code");
}
code_show = !code_show }
$(document).ready(code_toggle);
</script>
<form action="javascript:code_toggle()">
<input id="but" type="submit" style="border:1px solid black; background-color:#DDD">
%s
</form>'''%(init, msg)))
[docs]def jsalert(msg):
"send a javascript alert"
display(Javascript("alert('%s')"%msg))
[docs]class FileChooser:
"""a simple file chooser for Jupyter - obsolete - not used"""
def __init__(self, base=None, filetype=['fid','ser'], mode='r', show=True):
if base is None:
self.curdir = "/"
else:
self.curdir = base
self.filetype = filetype
self.mode = mode
self.wfile = widgets.Text(layout=Layout(width='70%'),description='File to load')
self.ldir = widgets.Label(value="Chosen dir: "+self.curdir)
self.wdir = widgets.Select(
options=self.dirlist(),
description='Choose Dir',
layout=Layout(width='70%'))
if mode=='r':
self.wchooser = widgets.Select(
options=self.filelist(),
description='Choose File',
layout=Layout(width='70%'))
self.wchooser.observe(self.wob)
self.wfile.disabled=True # not mofiable in read mode
elif mode=="w":
self.wfile.description = 'File to create'
self.wfile.disabled=False
self.wchooser = widgets.Select(
options=self.filelist(),
description='Files',
layout=Layout(width='70%'))
else:
raise Exception('Only "r" and "w" modes supported')
self.wsetdir = Button(description='❯',layout=Layout(width='20%'),
button_style='success', # 'success', 'info', 'warning', 'danger' or ''
tooltip='descend in directory')
self.wup = Button(description='❮',layout=Layout(width='20%'),
button_style='success', # 'success', 'info', 'warning', 'danger' or ''
tooltip='up to previous directory')
self.wsetdir.on_click(self.setdir)
self.wup.on_click(self.updir)
if show: self.show()
[docs] def filelist(self):
fl = []
if self.mode == 'r':
if type(self.filetype) is str:
fl = glob.glob(op.join(self.curdir,self.filetype))
elif type(self.filetype) in (tuple, list):
for f in self.filetype:
fl += glob.glob(op.join(self.curdir,f))
else:
raise Exception('TypeError, filetype should be either a string or a list')
else: # 'w'
fl = [f for f in glob.glob(op.join(self.curdir,'*')) if op.isfile(f)]
self.wfile.value = op.join(self.curdir,self.filetype)
if fl == []:
fl = [" "]
return fl
[docs] def dirlist(self):
base = self.curdir
return [d for d in glob.glob(op.join(base,'*')) if (op.isdir(d) and not d.endswith('__pycache__'))]
[docs] def wob(self, e):
self.wfile.value = self.wchooser.value
[docs] def updir(self, e):
self.curdir = op.dirname(self.curdir)
self.ldir.value = "Chosen dir: "+self.curdir
self.wdir.options = self.dirlist()
self.wchooser.options = self.filelist()
[docs] def setdir(self, e):
self.curdir = self.wdir.value
self.ldir.value = "Chosen dir: "+self.curdir
self.wdir.options = self.dirlist()
self.wchooser.options = self.filelist()
[docs] def show(self):
display(VBox(
[ self.ldir,
HBox( [self.wdir, VBox([self.wup,self.wsetdir])] ),
self.wchooser,
self.wfile
])
)
return self
@property
def file(self):
"the chosen complete filename"
return self.wfile.value
@property
def dirname(self):
"the final dirname containing the chosen file"
if op.isdir(self.wfile.value):
return op.basename(self.wfile.value)
else:
return op.basename(op.dirname(self.wfile.value))
@property
def nmrname(self):
"the final dirname containing the chosen file for TopSpin files"
if op.isdir(self.wfile.value):
return op.join(
op.basename(op.dirname(self.wfile.value)), self.dirname)
else:
return op.join(
op.basename(op.dirname(op.dirname(self.wfile.value))), self.dirname)
@property
def basename(self):
"the basename of the chosen file"
return op.basename(self.wfile.value)
[docs]class Show1D(HBox):
"""
An interactive display, 1D NMR
Show1D(spectrum)
to be developped for peaks and integrals
"""
def __init__(self, data, title=None, figsize=None, reverse_scroll=False, show=True):
"""
data : to be displayed
title : text for window
figsize : size in inches (x,y)
reverse_scroll : if True, reverses direction of mouse scroll
"""
super().__init__()
self.data = data
self.title = title
if figsize is None:
figsize = (10,5)
if reverse_scroll:
self.reverse_scroll = -1
else:
self.reverse_scroll = 1
self.blay = Layout(width='80px') # default layout for buttons
self.done = Button(description="Done", button_style='success',layout=self.blay)
self.done.on_click(self.on_done)
self.reset = Button(description="Reset", button_style='success',layout=self.blay,
tooltip="Reset to full spectrum")
self.reset.on_click(self.on_reset)
self.scale = widgets.FloatSlider(description='scale:', value=1.0, min=1.0, max=200, step=0.1,
layout=Layout(width='80px', height=str(0.8*2.54*figsize[1])+'cm'), continuous_update=REACTIVE,
orientation='vertical')
for widg in (self.scale,):
widg.observe(self.ob)
plt.ioff()
fi,ax = plt.subplots(figsize=figsize)
self.ax = ax
self.fig = fi
self.xb = self.ax.get_xbound()
self.blank = widgets.HTML(" ",layout=self.blay)
self.children = [ VBox([self.blank, self.reset, self.scale, self.done]), self.fig.canvas ]
self.set_on_redraw()
plt.ion()
if show:
display( self )
self.data.display(figure=self.ax, title=self.title)
[docs] def on_done(self, b):
self.close()
display(self.fig) # shows spectrum
[docs] def on_reset(self, b):
self.scale.value = 1.0
self.ax.set_xbound( (self.data.axis1.itop(0),self.data.axis1.itop(self.data.size1)) )
[docs] def ob(self, event):
"observe events and display"
if event['name']=='value':
self.disp()
[docs] def scale_up(self, step):
self.scale.value *= 1.1892**(self.reverse_scroll*step) # 1.1892 is 4th root of 2.0
[docs] def set_on_redraw(self):
def on_scroll(event):
self.scale_up(event.step)
cids = self.fig.canvas.mpl_connect('scroll_event', on_scroll)
[docs] def disp(self):
self.xb = self.ax.get_xbound()
self.ax.clear()
self.data.display(scale=self.scale.value, new_fig=False, figure=self.ax, title=self.title)
self.ax.set_xbound(self.xb)
#self.set_on_redraw()
[docs]class baseline1D(Show1D):
def __init__(self, data, figsize=None, reverse_scroll=False, show=True):
super().__init__( data, figsize=figsize, reverse_scroll=reverse_scroll, show=False)
self.data.real()
ppos = self.data.axis1.itop(self.data.axis1.size/2)
#self.ax.plot([ppos,ppos], self.ax.get_ybound())
self.select = widgets.FloatSlider(description='select:',
min=0.0, max=self.data.size1,
layout=Layout(width='100%'),
value=0.5*self.data.size1, readout=False, continuous_update=REACTIVE)
self.smooth = widgets.IntSlider(description='smooth:', min=0, max=20, layout=Layout(width='70%'),
tooltip='apply a local smoothing for pivot points',
value=1, readout=True, continuous_update=REACTIVE)
self.bsl_points = []
for w in [self.select, self.smooth]:
w.observe(self.ob)
bsize = '15%'
self.cancel = widgets.Button(description="Cancel", button_style='warning', layout=Layout(width='10%'))
self.cancel.on_click(self.on_cancel)
self.auto = widgets.Button(description="Auto", button_style='success', layout=Layout(width=bsize),
tooltip='Automatic set of points')
self.auto.on_click(self.on_auto)
self.set = widgets.Button(description="Add", button_style='success', layout=Layout(width=bsize),
tooltip='Add a baseline point at the selector position')
self.set.on_click(self.on_set)
self.unset = widgets.Button(description="Rem", button_style='warning', layout=Layout(width=bsize),
tooltip='Remove the baseline point closest to the selector')
self.unset.on_click(self.on_unset)
self.toshow = widgets.Dropdown( options=['baseline', 'corrected', 'points'], description='Display:')
self.toshow.observe(self.ob)
self.Box = VBox([
HBox([self.done, self.cancel, self.toshow,
widgets.HTML('Choose baseline points')]),
HBox([self.select,self.set, self.unset, self.auto, self.smooth]),
self])
def on_press(event):
v = self.data.axis1.ptoi(event.xdata)
self.select.value = abs(v)
cids = self.fig.canvas.mpl_connect('button_press_event', on_press)
if show: self.show()
[docs] def show(self):
"create the widget and display the spectrum"
display(self.Box)
self.data.display(figure=self.ax)
self.xb = self.ax.get_xbound() # initialize zoom
ppos = self.data.axis1.itop(self.select.value)
self.ax.plot([ppos,ppos], self.ax.get_ybound())
[docs] def close(self):
"close all widget"
for w in [ self.select, self.auto, self.set, self.unset, self.cancel, self.toshow, self.smooth, self.Box]:
w.close()
super().close()
[docs] def on_done(self, e):
if self.bsl_points == []:
jsalert('Please define control points before applying baseline correction')
return
self.close()
print('Applied correction:\n', sorted(self.bsl_points))
self.data.set_buffer( self.data.get_buffer() - self.correction() )
super().disp()
display(self.fig) # shows spectrum
[docs] def on_auto(self, e):
"automatically set baseline points"
self.bsl_points = [self.data.axis1.itop(x) for x in bcorr.autopoints(self.data)]
self.disp()
[docs] def on_cancel(self, e):
self.close()
super().disp()
display(self.fig) # shows spectrum
[docs] def on_set(self, e):
"add baseline points at selector"
self.bsl_points.append( self.selpos() )
self.disp()
[docs] def on_unset(self, e):
"remove baseline points closest from selector"
here = self.selpos()
distclose = np.inf
pclose = np.NaN
for i,p in enumerate(self.bsl_points):
if abs(p-here)< distclose:
pclose = p
distclose = abs(p-here)
self.bsl_points.remove(pclose)
self.disp()
[docs] def selpos(self):
"returns selector pos in ppm"
return self.data.axis1.itop(self.select.value)
[docs] def smoothed(self):
"returns a smoothed version of the data"
from scipy.signal import fftconvolve
buf = self.data.get_buffer()
mask = np.array([1,1,1,1,1])
return fftconvolve(buf, mask, mode='same')
[docs] def correction(self):
"returns the correction to apply as a numpy array"
ibsl_points = self.data.axis1.ptoi( np.array(self.bsl_points) ).astype(int)
x = np.arange(self.data.size1)
yy = self.data.get_buffer()
if len(self.bsl_points) == 0 :
return 0.0
elif len(self.bsl_points) == 1 :
value = self.data[ibsl_points[0]] * np.ones( self.data.size1 )
elif len(self.bsl_points) < 4 :
corr = bcorr._linear_interpolate(yy, ibsl_points, nsmooth=self.smooth.value)
value = corr(x)
else:
corr = bcorr._spline_interpolate(yy, ibsl_points, nsmooth=self.smooth.value)
value = corr(x)
return value
[docs] def corrected(self):
value = self.data.copy()
value.set_buffer( value.get_buffer() - self.correction() )
return value
[docs] def disp(self):
"compute and display the spectrum"
self.xb = self.ax.get_xbound()
# box
super().disp()
# data
if len(self.bsl_points)>0:
if self.toshow.value == 'baseline':
( self.data.copy()-self.corrected() ).display(new_fig=False, figure=self.ax, color='r')
elif self.toshow.value == 'corrected':
self.ax.clear()
self.corrected().display(new_fig=False, figure=self.ax, color='r', scale=self.scale.value)
# selector
ppos = self.selpos()
self.ax.plot([ppos,ppos], self.ax.get_ybound())
# pivots
y = bcorr.get_ypoints( self.data.get_buffer(),
self.data.axis1.ptoi( np.array(self.bsl_points)),
nsmooth=self.smooth.value )
self.ax.scatter(self.bsl_points, y, c='r', marker='o')
# set zoom
self.ax.set_xbound(self.xb)
Colors = ('black','red','blue','green','orange',
'blueviolet','crimson','turquoise','indigo',
'magenta','gold','pink','purple','salmon','darkblue','sienna')
[docs]class SpforSuper(object):
"a holder for SuperImpose"
def __init__(self, i, name):
j = i%len(Colors)
self.name = widgets.Text(value=name, layout=Layout(width='40em'))
self.color = widgets.Dropdown(options=Colors,value=Colors[j],layout=Layout(width='80px'))
self.direct = widgets.Dropdown(options=['up','down','off'],value='off', layout=Layout(width='70px'))
self.offset = widgets.FloatText(value=0.0, layout=Layout(width='70px'), tooltip="offset")
self.me = HBox([widgets.HTML(value="<b>%d</b>"%i),self.name, self.offset, self.color,self.direct])
self.fig = False
[docs] def display(self, unit='ppm'):
if self.name != 'None' and self.direct.value != 'off':
scale = 1
if self.direct.value == 'up':
mult = 1
elif self.direct.value == 'down':
mult = -1
else:
return
NMRData(name=self.name.value).set_unit(unit).mult(mult).display(
new_fig=self.fig,
scale=scale,
color=self.color.value,
label=op.basename(op.dirname(self.name.value)))
class _Show1Dplus(Show1D):
def __init__(self, data, figsize=None, title=None, reverse_scroll=False):
super().__init__( data, figsize=figsize, title=title, reverse_scroll=reverse_scroll)
self.scaleint = widgets.FloatSlider(value=0.5, min=0.1, max=10, step=0.05,
layout=Layout(width='20%'), continuous_update=REACTIVE)
self.offset = widgets.FloatSlider(value=0.3, min=0.0, max=1.0, step=0.01,
layout=Layout(width='20%'), continuous_update=REACTIVE)
self.peaks = widgets.Checkbox(value=False, layout=Layout(width='15%'))
self.integ = widgets.Checkbox(value=False, layout=Layout(width='15%'))
for widg in (self.scaleint, self.offset, self.peaks, self.integ):
widg.observe(self.ob)
self.fullBox = VBox([ HBox([Label('Integral scale:'),self.scaleint,Label('offset:'),self.offset]),
HBox([Label('Show Peaks'),self.peaks,Label('integrals'),self.integ])
])
display(self.fullBox)
def on_done(self, e):
self.fullBox.close()
super().close()
self.disp(zoom=True)
display(self.fig)
def disp(self, zoom=False):
"refresh display - if zoom is True, display only in xbound"
self.xb = self.ax.get_xbound()
# self.yb = self.ax.get_ybound()
if zoom:
zoom = self.xb
else:
zoom = None
self.ax.clear()
self.data.display(scale=self.scale.value, new_fig=False, figure=self.ax, title=self.title, zoom=zoom)
if self.integ.value:
try:
self.data.display_integral(label=True, integscale=self.scaleint.value,
integoff=self.offset.value, figure=self.ax, zoom=zoom)
except:
print('no or wrong integrals')
pass
if self.peaks.value:
try:
self.data.display_peaks(peak_label=True, figure=self.ax, scale=self.scale.value, zoom=zoom)
except:
print('no or wrong peaklist')
pass
self.ax.set_xbound(self.xb)
[docs]class Show1Dplus(Show1D):
def __init__(self, data, base='/DATA', N=9, figsize=None, title=None, reverse_scroll=False):
from spike.Interactive.ipyfilechooser import FileChooser
super().__init__( data, figsize=figsize, title=title, reverse_scroll=reverse_scroll)
self.scaleint = widgets.FloatSlider(value=0.5, min=0.1, max=10, step=0.05,
layout=Layout(width='20%'), continuous_update=REACTIVE)
self.offset = widgets.FloatSlider(value=0.3, min=0.0, max=1.0, step=0.01,
layout=Layout(width='20%'), continuous_update=REACTIVE)
self.peaks = widgets.Checkbox(value=False, layout=Layout(width='15%'))
self.integ = widgets.Checkbox(value=False, layout=Layout(width='15%'))
self.Chooser = FileChooser(base=base, filetype="*.gs1", mode='r', show=False)
self.bsel = widgets.Button(description='Copy',layout=self.blay,
button_style='info', # 'success', 'info', 'warning', 'danger' or ''
tooltip='copy selected data-set to entry below')
self.to = widgets.IntText(value=1,min=1,max=N,layout=Layout(width='10%'))
self.bsel.on_click(self.copy)
self.DataList = [SpforSuper(i+1,'None') for i in range(N)]
self.DataList[0].color.value = 'red'
self.DataList[0].fig = True # switches on the very first one
for widg in (self.scaleint, self.offset, self.peaks, self.integ):
widg.observe(self.ob)
self.tabs = Tab()
self.tabs.children = [
VBox([ HBox([Label('Integral scale:'),self.scaleint,Label('offset:'),self.offset]),
HBox([Label('Show Peaks'),self.peaks,Label('integrals'),self.integ]),
HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas])
]),
VBox([ Label("Choose spectra to superimpose"),
HBox([self.Chooser, self.bsel, self.to])]+
[sp.me for sp in self.DataList]
)
]
self.tabs.set_title(0, 'Spectrum')
self.tabs.set_title(1, 'Data-List')
self.children = [self.tabs]
[docs] def copy(self, event):
if self.to.value <1 or self.to.value >len(self.DataList):
print('Destination is out of range !')
else:
self.DataList[self.to.value-1].name.value = self.Chooser.selected
self.DataList[self.to.value-1].direct.value = 'up'
self.to.value = min(self.to.value, len(self.DataList)) +1
[docs] def on_done(self, e):
self.close()
self.disp(zoom=True)
display(self.fig)
[docs] def disp(self, zoom=False):
"refresh display - if zoom is True, display only in xbound"
self.xb = self.ax.get_xbound()
# self.yb = self.ax.get_ybound()
if zoom:
zoom = self.xb
else:
zoom = None
self.ax.clear()
self.data.display(scale=self.scale.value, new_fig=False, figure=self.ax, title=self.title, zoom=zoom)
if self.integ.value:
try:
self.data.display_integral(label=True, integscale=self.scaleint.value,
integoff=self.offset.value, figure=self.ax, zoom=zoom)
except:
print('no or wrong integrals')
pass
if self.peaks.value:
try:
self.data.display_peaks(peak_label=True, figure=self.ax, scale=self.scale.value, zoom=zoom)
except:
print('no or wrong peaklist')
pass
self.ax.set_xbound(self.xb)
[docs]class baseline2D_F2(baseline1D):
def __init__(self, data, figsize=None):
print('WARNING this tool is not functional/tested yet')
self.data2D = data
super().__init__( self.data2D.projF2, figsize=figsize)
[docs] def on_done(self, e):
super().on_done(e)
ibsl_points = [int(self.data2D.axis2.ptoi(x)) for x in self.bsl_points]
self.data2D.bcorr(method='spline', xpoints=ibsl_points)
[docs]class Show2D(object):
"""
A display for 2D NMR with a scale cursor
Show2D(spectrum) where spectrum is a NPKData object
- special display for DOSY.
"""
def __init__(self, data, title=None, figsize=None):
self.data = data
self.isDOSY = isinstance(data.axis1, NPKData.LaplaceAxis)
try:
self.proj2 = data.projF2
except:
self.proj2 = data.proj(axis=2).real()
try:
self.proj1 = data.projF1
except:
self.proj1 = data.proj(axis=1).real()
self.title = title
self.scale = widgets.FloatLogSlider(description='scale:', value=1.0, min=-1, max=3, base=10, step=0.01,
layout=Layout(width='80%'), continuous_update=HEAVY)
self.posview = widgets.Checkbox(value=True,description='Positive', tooltip='Display Positive levels')
self.negview = widgets.Checkbox(value=False,description='Negative', tooltip='Display Negative levels')
self.cursors = widgets.Checkbox(value=False,description='Cursors', tooltip='show cursors (cpu intensive !)')
for w in (self.scale, self.posview, self.negview, self.cursors):
w.observe(self.ob)
grid = {'height_ratios':[1,4],'hspace':0,'wspace':0}
if self.isDOSY:
fsize = (10,5)
grid['width_ratios']=[7,1]
else:
fsize = (8,8)
grid['width_ratios']=[4,1]
# fig, self.axarr = plt.subplots(2, 1, sharex=True, figsize=fsize, gridspec_kw=grid)
self.fig = plt.figure(figsize=fsize, constrained_layout=False)
spec2 = gridspec.GridSpec(ncols=2, nrows=2, figure=self.fig, **grid)
axarr = np.empty((2,2), dtype=object)
axarr[0,0] = self.fig.add_subplot(spec2[0, 0])
axarr[1,0] = self.fig.add_subplot(spec2[1, 0],sharex=axarr[0, 0])
axarr[1,1] = self.fig.add_subplot(spec2[1, 1],sharey=axarr[1, 0])
self.top_ax = axarr[0,0]
self.spec_ax = axarr[1,0]
self.side_ax = axarr[1,1]
self.multitop = None
self.multiside = None
self.Box = HBox( [self.scale, self.posview, self.negview, self.cursors])
display( self.Box )
self.disp(new=True)
[docs] def on_done(self, b):
self.scale.close()
[docs] def ob(self, event):
"observe events and display"
if event['name'] != 'value':
return
self.disp()
[docs] def disp(self,new=False):
if new:
self.proj2.display(figure=self.top_ax, title=self.title)
xb = self.top_ax.get_xbound()
dataxis = self.proj1.axis1.itoc( self.proj1.axis1.points_axis() )
self.side_ax.plot(self.proj1.get_buffer(),dataxis)
yb = self.side_ax.get_ybound()
else:
yb = self.side_ax.get_ybound()
xb = self.top_ax.get_xbound()
self.spec_ax.clear()
if self.cursors.value:
self.multitop = MultiCursor(self.fig.canvas, (self.spec_ax, self.top_ax), color='r', lw=1, horizOn=False, vertOn=True)
self.multiside = MultiCursor(self.fig.canvas, (self.spec_ax, self.side_ax), color='r', lw=1, horizOn=True, vertOn=False)
else:
self.multitop = None
self.multiside = None
if self.posview.value:
self.data.display(scale=self.scale.value, new_fig=False, figure=self.spec_ax)
if self.negview.value:
self.data.display(scale=-self.scale.value, new_fig=False,
figure=self.spec_ax, mpldic={'cmap':'Wistia'})
self.spec_ax.set_xbound(xb)
self.spec_ax.set_ybound(yb)
[docs]class Phaser1D(Show1D):
"""
An interactive phaser in 1D NMR
Phaser1D(spectrum)
requires %matplotlib widget
"""
def __init__(self, data, figsize=None, title=None, reverse_scroll=False, show=True):
data.check1D()
if data.itype == 0:
jsalert('Data is Real - Please redo Fourier Transform')
return
super().__init__( data, figsize=figsize, title=title, reverse_scroll=reverse_scroll, show=False)
self.p0 = widgets.FloatSlider(description='P0:',min=-180, max=180, step=0.1,
layout=Layout(width='100%'), continuous_update=REACTIVE)
self.p1 = widgets.FloatSlider(description='P1:',min=-360, max=360, step=1.0,
layout=Layout(width='100%'), continuous_update=REACTIVE)
self.pivot = widgets.FloatSlider(description='pivot:',
min=0.0, max=self.data.size1,
step=1, layout=Layout(width='80%'),
value=0.5*self.data.size1, readout=False, continuous_update=REACTIVE)
self.cancel = widgets.Button(description="Cancel", button_style='warning')
self.cancel.on_click(self.on_cancel)
# remove done button and create an Apply one
self.done.close()
self.apply = widgets.Button(description="Done", button_style='success')
self.apply.on_click(self.on_Apply)
# draw HBox
self.children = [VBox([
HBox([self.apply, self.cancel, self.pivot, widgets.HTML('<i>set by clicking on spectrum</i>')]),
self.p0,
self.p1,
HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas]) ])]
# add interaction
for w in [self.p0, self.p1, self.scale]:
w.observe(self.ob)
self.pivot.observe(self.on_movepivot)
# add click event on spectral window
def on_press(event):
self.pivot.value = self.data.axis1.ptoi(event.xdata)
cids = self.fig.canvas.mpl_connect('button_press_event', on_press)
self.lp0, self.lp1 = self.ppivot()
if show: self.show()
[docs] def show(self):
self.data.display(figure=self.ax)
self.xb = self.ax.get_xbound() # initialize zoom
ppos = self.data.axis1.itop(self.pivot.value)
self.ax.plot([ppos,ppos], self.ax.get_ybound())
display(self)
[docs] def on_cancel(self, b):
# self.p0.value = 0 # because widget remains active...
# self.p1.value = 0
self.close()
print("no applied phase")
[docs] def on_Apply(self, b):
self.close()
lp0, lp1 = self.ppivot() # get centered values
self.data.phase(lp0, lp1)
self.disp()
self.on_done(b)
print("Applied: phase(%.1f, %.1f)"%(lp0, lp1))
[docs] def ppivot(self):
"converts from pivot values to centered ones"
pp = 1.0-(self.pivot.value/self.data.size1)
return (self.p0.value + (pp-0.5)*self.p1.value, self.p1.value)
[docs] def ctopivot(self, p0, p1):
"convert from centered to pivot values"
pp = 1.0-(self.pivot.value/self.data.size1)
return p0- (pp-0.5)*p1, p1
[docs] def on_movepivot(self, event):
if event['name']=='value':
self.p0.value, self.p1.value = self.ctopivot(self.lp0, self.lp1)
self.phase()
[docs] def ob(self, event):
"observe changes and start phasing"
if event['name']=='value':
self.phase()
[docs] def phase(self):
"apply phase and display"
self.xb = self.ax.get_xbound() # get current zoom
self.ax.clear()
self.lp0, self.lp1 = self.ppivot() # get centered values
self.data.copy().phase(self.lp0, self.lp1).display(scale=self.scale.value, new_fig=False, figure=self.ax)
ppos = self.data.axis1.itop(self.pivot.value)
self.ax.plot([ppos,ppos], self.ax.get_ybound())
self.ax.set_xbound( self.xb )
[docs]class Phaser2D(object):
"""
An interactive phaser in 2D NMR
Phaser2D(spec)
best when in %matplotlib inline
"""
def __init__(self, data):
print('WARNING this tool is not functional/tested yet')
self.data = data
self.scale = widgets.FloatLogSlider(description='scale:', value=1.0, min=-1, max=2, base=10, step=0.01,
layout=Layout(width='80%'), continuous_update=HEAVY)
self.F1p0 = widgets.FloatSlider(min=-180, max=180, step=0.1, description='F1 p0',continuous_update=HEAVY)
self.F1p1 = widgets.FloatSlider(min=-250, max=250, step=1.0, description='F1 p1',continuous_update=HEAVY)
self.F2p0 = widgets.FloatSlider(min=-180, max=180, step=0.1, description='F2 p0',continuous_update=HEAVY)
self.F2p1 = widgets.FloatSlider(min=-250, max=250, step=1.0, description='F2 p1',continuous_update=HEAVY)
for w in [self.F1p0, self.F1p1, self.F2p0, self.F2p1, self.scale]:
w.observe(self.ob)
self.button = widgets.Button(description="Apply correction",button_style='success')
self.button.on_click(self.on_Apply)
self.cancel = widgets.Button(description="Cancel",button_style='warning')
self.cancel.on_click(self.on_cancel)
# interact(self.phase, scale=self.scale, F1p0=self.F1p0, F1p1=self.F1p1, F2p0=self.F2p0, F2p1=self.F2p1)
display(VBox([self.scale,
HBox([VBox([self.F1p0, self.F1p1], layout=Layout(width='40%')), VBox([self.F2p0, self.F2p1], layout=Layout(width='40%'))], layout=Layout(width='80%'))
], layout=Layout(width='100%')))
display(HBox([self.button, self.cancel]))
fi,ax = plt.subplots()
self.ax = ax
self.display()
#self.data.display(figure=self.ax)
[docs] def ob(self, event):
"observe changes and start phasing"
if event['name']=='value':
self.phase()
[docs] def close(self):
for w in [self.F1p0, self.F1p1, self.F2p0, self.F2p1, self.scale, self.button, self.cancel]:
w.close()
[docs] def on_cancel(self, b):
print("No action")
self.ax.clear()
self.data.display(figure=self.ax,scale=self.scale.value)
self.ax.set_xlim(xmin=self.data.axis2.itop(0), xmax=self.data.axis2.itop(self.data.size2))
self.ax.set_ylim(ymin=self.data.axis1.itop(0), ymax=self.data.axis1.itop(self.data.size1))
self.close()
[docs] def on_Apply(self, b):
print("Applied: phase(%.1f,%.1f,axis='F1').phase(%.1f,%.1f,axis='F')"%(self.F1p0.value, self.F1p1.value, self.F2p0.value, self.F2p1.value))
self.data.phase(self.F2p0.value, self.F2p1.value, axis='F2').phase(self.F1p0.value, self.F1p1.value, axis='F1')
self.data.display(figure=self.ax,scale=self.scale.value)
self.ax.set_xlim(xmin=self.data.axis2.itop(0), xmax=self.data.axis2.itop(self.data.size2))
self.ax.set_ylim(ymin=self.data.axis1.itop(0), ymax=self.data.axis1.itop(self.data.size1))
self.close()
[docs] def display(self,todisplay=None):
"display either the current data or the one provided - red and blue"
self.ax.clear()
if not todisplay:
todisplay = self.data
todisplay.display(scale=self.scale.value, new_fig=False, figure=self.ax,color='blue')
todisplay.display(scale=-self.scale.value, new_fig=False, figure=self.ax, color='red')
self.ax.set_xlim(xmin=self.data.axis2.itop(0), xmax=self.data.axis2.itop(self.data.size2))
self.ax.set_ylim(ymin=self.data.axis1.itop(0), ymax=self.data.axis1.itop(self.data.size1))
[docs] def phase(self):
"compute phase and display"
dp = self.data.copy().phase(self.F2p0.value, self.F2p1.value, axis='F2').phase(self.F1p0.value, self.F1p1.value, axis='F1')
self.display(dp)
# def phase(self, scale, F1p0, F1p1, F2p0, F2p1):
# self.data.copy().phase(F1p0,F1p1,axis='F1').phase(F2p0,F2p1,axis='F2').display(scale=scale);
[docs]class AvProc1D:
"Detailed 1D NMR Processing"
def __init__(self, filename=""):
print('WARNING this tool is not functional/tested yet')
self.wfile = widgets.Text(description='File to process',layout=Layout(width='80%'), value=filename)
self.wapod = widgets.Dropdown(
options=['None', 'apod_sin (sine bell)', 'apod_em (Exponential)', 'apod_gm (Gaussian)', 'gaussenh (Gaussian Enhacement)', 'kaiser'],
value='apod_sin (sine bell)',
description='Apodisation')
self.wpapod_Hz = widgets.FloatText(
value=1.0,
min=0, # max exponent of base
max=30, # min exponent of base
description='Width in Hz',
layout=Layout(width='15%'),
disabled = True)
self.wpapod_enh = widgets.FloatText(
value=2.0,
min=0.0, # max exponent of base
max=5.0, # min exponent of base
description='strength',
layout=Layout(width='15%'),
step=1,
disabled = True)
self.wpapod_sin = widgets.FloatText(
value=0.0,
min=0, # max exponent of base
max=0.5, # min exponent of base
description='bell shape',
layout=Layout(width='15%'),
step=0.01,
tooltip='value is the maximum of the bell, 0 is pure cosine, 0.5 is pure sine',
disabled = False)
self.wzf = widgets.Dropdown(
options=[0, 1, 2, 4, 8],
value=1,
description='Zero-Filling')
self.wphase0 = widgets.FloatText(
value=0, description='Phase : P0', layout=Layout(width='20%'), disabled = True)
self.wphase1 = widgets.FloatText(
value=0, description='P1', layout=Layout(width='20%'), disabled = True)
self.wapmin = widgets.Checkbox(
value=True, description='AutoPhasing', tooltip='Perform AutoPhasing')
self.wapmin.observe(self.apmin_select)
self.wbcorr = widgets.Checkbox(
value=False, description='Baseline Correction', tooltip='Perform AutoPhasing')
self.wapod.observe(self.apod_select)
self.bapod = widgets.Button(description='Show effect on FID')
self.bapod.on_click(self.show_apod)
self.bdoit = widgets.Button(description='Process')
self.bdoit.on_click(self.process)
self.show()
fi,ax = plt.subplots()
self.ax = ax
if os.path.exists(filename):
self.load()
#self.data.set_unit('sec')
self.display()
[docs] def apod_select(self, e):
test = self.wapod.value.split()[0]
self.wpapod_sin.disabled = True
self.wpapod_Hz.disabled = True
self.wpapod_enh.disabled = True
if test == "apod_sin":
self.wpapod_sin.disabled = False
if test in ('apod_em', 'apod_gm','gaussenh'):
self.wpapod_Hz.disabled = False
if test == 'gaussenh':
self.wpapod_enh.disabled = False
[docs] def apmin_select(self, e):
for w in self.wphase0, self.wphase1:
w.disabled = self.wapmin.value
[docs] def load(self):
self.data = Import_1D(self.wfile.value)
[docs] def apod(self):
func = self.wapod.value.split()[0]
todo = None
if func == 'apod_sin':
todo = 'self.data.apod_sin(%f)'%(self.wpapod_sin.value,)
elif func in ('apod_em', 'apod_gm'):
todo = 'self.data.%s(%f)'%(func, self.wpapod_Hz.value)
elif func == 'gaussenh':
todo = 'self.data.gaussenh(%f,enhancement=%f)'%(self.wpapod_Hz.value, self.wpapod_enh.value)
if todo is not None:
eval(todo)
return self.data
[docs] def show_apod(self, e):
self.load()
self.apod()
self.display()
[docs] def process(self, e):
self.load()
self.apod().zf(self.wzf.value).ft_sim().bk_corr().set_unit('ppm')
if self.wapmin.value:
self.data.apmin()
self.wphase0.value = round(self.data.axis1.P0,1)
self.wphase1.value = self.data.axis1.P1
else:
self.data.phase(self.wphase0.value, self.wphase1.value)
self.display()
[docs] def display(self):
self.ax.clear()
self.data.display(figure=self.ax)
[docs] def show(self):
display(
VBox([self.wfile,
HBox([self.wapod, self.wpapod_sin, self.wpapod_Hz, self.wpapod_enh, self.bapod]),
self.wzf,
HBox([self.wapmin, self.wphase0, self.wphase1]),
# self.wbcorr,
self.bdoit]) )
from spike.plugins import Peaks
[docs]class NMRPeaker1D(Show1D):
"""
a peak-picker for NMR experiments
"""
# self.peaks : the defined peaklis, copyied in and out of data
# self.temppk : the last computed pklist
def __init__(self, data, figsize=None, reverse_scroll=False, show=True):
super().__init__( data, figsize=figsize, reverse_scroll=reverse_scroll, show=False)
self.data = data.real()
try:
self.peaks = self.data.peaks
except AttributeError:
self.peaks = Peaks.Peak1DList()
self.temppk = Peaks.Peak1DList()
self.thresh = widgets.FloatLogSlider(value=20.0,
min=-1, max=2.0, base=10, step=0.01, layout=Layout(width='30%'),
continuous_update=False, readout=True, readout_format='.2f')
try:
self.thresh.value = 100*self.data.peaks.threshold/self.data.absmax # if already peak pickeds
except:
self.thresh.value = 20.0
pass
self.thresh.observe(self.pickpeak)
self.peak_mode = widgets.Dropdown(options=['marker', 'bar'],value='marker',description='show as')
self.peak_mode.observe(self.ob)
self.out = Output(layout={'border': '1px solid red'})
# self.done = widgets.Button(description="Done", button_style='success')
# self.done.on_click(self.on_done)
self.badd = widgets.Button(description="Add", button_style='success', layout=self.blay)
self.badd.on_click(self.on_add)
self.brem = widgets.Button(description="Rem", button_style='warning', layout=self.blay)
self.brem.on_click(self.on_rem)
self.cancel = widgets.Button(description="Cancel", button_style='warning', layout=self.blay)
self.cancel.on_click(self.on_cancel)
self.selval = widgets.FloatText(
value=0.0, description='selection', layout=Layout(width='20%'), step=0.001, disabled = True)
self.newval = widgets.FloatText(
value=0.0, description='calibration', layout=Layout(width='20%'), step=0.001, disabled = True)
self.setcalib = widgets.Button(description="Set", layout=Layout(width='10%'),
button_style='success', tooltip='Set spectrum calibration')
self.setcalib.on_click(self.on_setcalib)
def on_press(event):
v = event.xdata
iv = self.data.axis1.ptoi(v) # store position in index (peaks are internally in index)
distclose = np.inf # search closest peak
pclose = 0.0
for p in self.data.peaks:
if abs(p.pos-iv) < distclose:
pclose = p.pos
distclose = abs(p.pos-iv)
self.selval.value = self.data.axis1.itop(pclose) # back to ppm
for w in (self.selval, self.newval):
w.disabled = False
cids = self.fig.canvas.mpl_connect('button_press_event', on_press)
# redefine Box
self.tabs = Tab()
self.tabs.children = [
VBox([
HBox([self.badd, self.brem, Label('threshold - % largest signal'), self.thresh, self.peak_mode]),
HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas])
]),
VBox([
HBox([ Label('Select a peak with mouse and set calibrated values'), self.selval, self.newval, self.setcalib]),
HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas])
]),
self.out]
self.tabs.set_title(0, 'Peak Picker')
self.tabs.set_title(1, 'calibration')
self.tabs.set_title(2, 'Peak Table')
self.children = [VBox([HBox([self.done, self.cancel]),self.tabs])]
if show: self.show()
[docs] def show(self):
self.data.display(figure=self.ax)
self.xb = self.ax.get_xbound() # initialize zoom
self.pp()
self.data.display(figure=self.ax)
self.ax.set_xbound( (self.data.axis1.itop(0),self.data.axis1.itop(self.data.size1)) )
self.disp()
display(self)
[docs] def on_add(self, b):
self.peaks = Peaks.peak_aggreg(self.peaks + self.temppk, distance=1.0)
self.temppk = Peaks.Peak1DList()
self.disp()
[docs] def on_rem(self, b):
(up,down) = self.ax.get_xbound()
iup = self.data.axis1.ptoi(up)
idown = self.data.axis1.ptoi(down)
iup,idown = (max(iup,idown), min(iup,idown))
to_rem = []
for pk in self.peaks:
if pk.pos < iup and pk.pos>idown:
to_rem.append(pk)
for pk in to_rem:
self.peaks.remove(pk)
self.disp()
[docs] def on_cancel(self, b):
self.close()
del self.data.peaks
print("no Peak-Picking done")
[docs] def on_done(self, b):
self.temppk = Peaks.Peak1DList() # clear temp peaks
self.close()
# new figure
self.disp()
# and display
tabs = Tab()
tabs.children = [self.fig.canvas, self.out]
tabs.set_title(0, '1D Display')
tabs.set_title(1, 'Peak Table')
display(tabs)
self.data.peaks = self.peaks # and copy
[docs] def on_setcalib(self, e):
off = self.selval.value-self.newval.value
self.data.axis1.offset -= off*self.data.axis1.frequency # off is in ppm, axis1.offset is in Hz
self.selval.value = self.newval.value
self.pp()
[docs] def pkprint(self,event):
self.out.clear_output(wait=True)
with self.out:
if len(self.temppk)>0:
self.data.peaks = self.temppk
display(HTML("<p style=color:red> Transient peak list </p>"))
display(HTML(self.data.pk2pandas().to_html()))
display(HTML("<p style=color:blue> Defined peak list </p>"))
self.data.peaks = self.peaks
display(HTML(self.data.pk2pandas().to_html()))
def _pkprint(self,event):
self.out.clear_output(wait=True)
with self.out:
print(self.pklist())
[docs] def pklist(self):
"creates peaklist for printing or exporting"
text = ["ppm\tInt.(%)\twidth (Hz)"]
data = self.data
intmax = max(data.peaks.intens)/100
for pk in data.peaks:
ppm = data.axis1.itop(pk.pos)
width = 2*pk.width*data.axis1.specwidth/data.size1
l = "%.3f\t%.1f\t%.2f"%(ppm, pk.intens/intmax, width)
text.append(l)
return "\n".join(text)
[docs] def ob(self, event):
if event['name']=='value':
self.disp()
[docs] def disp(self):
"interactive wrapper to peakpick"
self.xb = self.ax.get_xbound()
#self.yb = self.ax.get_ybound()
self.ax.clear()
#super().disp()
self.data.display(scale=self.scale.value, new_fig=False, figure=self.ax, title=self.title)
x = [self.data.axis1.itoc(z) for z in (0, self.data.size1) ]
y = [self.data.absmax*self.thresh.value/100]*2
self.ax.plot(x,y,':r')
try:
self.temppk.display(peak_label=False, peak_mode=self.peak_mode.value, f=self.data.axis1.itoc, figure=self.ax,color='red')
self.peaks.display(peak_label=False, peak_mode=self.peak_mode.value, f=self.data.axis1.itoc, color='blue', figure=self.ax)
except:
rrr("problem")
self.temppk.display(peak_label=True, peak_mode=self.peak_mode.value, color='red', figure=self.ax)
self.ax.set_xbound(self.xb)
self.ax.set_ylim(ymax=self.data.absmax/self.scale.value)
self.pkprint({'name':'value'}) # send pseudo event to display peak table
[docs] def pickpeak(self, event):
"interactive wrapper to peakpick"
if event['name']=='value':
self.pp()
[docs] def pp(self):
"do the peak-picking calling pp().centroid()"
#self.spec.clear_output(wait=True)
th = self.data.absmax*self.thresh.value/100
zm = self.ax.get_xbound()
self.data.set_unit('ppm').peakpick(threshold=th, verbose=False, zoom=zm).centroid()
self.temppk = self.data.peaks
self.disp()
self.ax.annotate('%d peaks detected'%len(self.data.peaks) ,(0.05,0.95), xycoords='figure fraction')
from spike.plugins.Integrate import Integrals, Integralitem
[docs]class NMRIntegrate(Show1D):
"an integrator for NMR experiments"
def __init__(self, data, figsize=None, reverse_scroll=False, show=True):
super().__init__( data, figsize=figsize, reverse_scroll=reverse_scroll, show=False)
try:
self.Integ = data.integrals
except:
self.Integ = Integrals(data, compute=False) # initialize with empty list
self.thresh = widgets.FloatLogSlider(description='sensitivity',value=10.0,
min=-1, max=2.0, base=10, step=0.01, layout=Layout(width='30%'),
continuous_update=HEAVY, readout=False, readout_format='.2f')
self.bias = widgets.FloatSlider(
description='bias', layout=Layout(width='20%'),
value=0.0,min=-10.0, max=10.0, step=0.1,
continuous_update=HEAVY, readout=False, readout_format='.1f')
self.sep = widgets.FloatSlider(
description='separation', layout=Layout(width='30%'),
value=3.0,min=0.0, max=20.0, step=0.1,
continuous_update=HEAVY, readout=False, readout_format='.1f')
self.wings = widgets.FloatSlider(
description='extension', layout=Layout(width='30%'),
value=5.0,min=0.5, max=20.0, step=0.1,
continuous_update=HEAVY, readout=False, readout_format='.1f')
for w in (self.bias, self.sep, self.wings):
w.observe(self.integrate)
self.thresh.observe(self.peak_and_integrate)
self.cancel = widgets.Button(description="Cancel", button_style='warning', layout=self.blay)
self.cancel.on_click(self.on_cancel)
self.bprint = widgets.Button(description="Print", layout=self.blay,
button_style='success', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Print to screen')
self.bprint.on_click(self.print)
self.badd = widgets.Button(description="Add", layout=self.blay,
button_style='success', tooltip='Add an entry from current zoom')
self.badd.on_click(self.on_add)
self.brem = widgets.Button(description="Rem", layout=self.blay,
button_style='warning', tooltip='Remove all entries in current zoom')
self.brem.on_click(self.on_rem)
self.bauto = widgets.Button(description="Compute", layout=self.blay,
button_style='success', tooltip='Automatic definition of integrals')
self.bauto.on_click(self.peak_and_integrate)
self.entry = widgets.IntText(value=0,description='Entry',min=0,layout=Layout(width='15%'))
self.value = widgets.FloatText(value=100,description='Value',layout=Layout(width='15%'))
self.set = widgets.Button(description="Set", button_style='success', layout=Layout(width='10%'))
self.set.on_click(self.set_value)
self.out = Output(layout={'border': '1px solid red'})
# redefine children
self.tabs = Tab()
self.tabs.children = [
VBox([
HBox([self.badd, self.brem,
Label("Use buttons to add and remove integrals in the current zoom window")]),
HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas]),
]),
VBox([HBox([self.bauto, Label("Define integral shapes using the sliders below")]),
HBox([self.thresh, self.sep, self.wings]),
HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas]),
]),
VBox([HBox([Label('Choose an integral for calibration'),
self.entry, self.value, self.set, self.blank, self.bprint] ),
self.out ])
]
self.tabs.set_title(0, 'Manual integration')
self.tabs.set_title(1, 'Automatic')
self.tabs.set_title(2, 'Integral Table & Calibration')
self.children = [VBox([HBox([self.done, self.cancel]),self.tabs])]
# self.children = [VBox([HBox([self.done, self.cancel, self.bias, self.sep, self.wings]),
# HBox([Label('Choose an integral for calibration'),
# self.entry, self.value, self.set, self.blank, self.bprint] ),
# HBox([VBox([self.blank, self.reset, self.scale]), self.fig.canvas]),
# self.out ])]
if show: self.show()
[docs] def show(self):
self.data.display(figure=self.ax)
self.xb = self.ax.get_xbound() # initialize zoom
#self.int()
self.data.display(figure=self.ax)
self.ax.set_xbound( (self.data.axis1.itop(0),self.data.axis1.itop(self.data.size1)) )
self.disp()
display(self)
[docs] def on_cancel(self, b):
self.close()
print("No integration")
[docs] def on_done(self, b):
self.close()
self.disp(zoom=True)
display(self.fig)
display(self.out)
self.data.integrals = self.Integ # copy integrals
[docs] def on_add(self, b):
start, end = self.ax.get_xbound()
self.Integ.append( Integralitem(self.data.axis1.ptoi(start), self.data.axis1.ptoi(end), [], 0.0) )
self.Integ.zonestocurves()
self.disp()
self.print(None)
[docs] def on_rem(self, b):
start, end = self.ax.get_xbound()
start, end = self.data.axis1.ptoi(start), self.data.axis1.ptoi(end)
start, end = (min(start, end), max(start, end))
to_rem = []
for ii in self.Integ:
if ii.start>start and ii.end<end:
to_rem.append(ii)
for ii in to_rem:
self.Integ.remove(ii)
self.disp()
self.print(None)
[docs] def set_value(self,b):
self.Integ.recalibrate(self.entry.value, self.value.value)
self.disp()
self.print(None)
[docs] def print(self,event):
self.out.clear_output()
self.Integ.sort(key=lambda x: x.start) # sort integrals
with self.out:
display(HTML( self.Integ.to_pandas().to_html() ))
[docs] def peak_and_integrate(self, event):
self.data.pp(threshold=self.data.absmax*self.thresh.value/100,
verbose=False, zoom=self.ax.get_xbound()).centroid()
if len(self.data.peaks)>0:
self.int()
[docs] def integrate(self, event):
#"integrate from event"
#if event['name']=='value':
self.int()
[docs] def int(self):
"do the automatic integration from peaks and parameters"
self.on_rem(None)
try:
calib = self.Integ.calibration
except:
calib = None
self.data.set_unit('ppm')
try:
self.data.peaks
except:
self.data.pp(threshold=self.data.absmax*self.thresh.value/100,
verbose=False, zoom=self.ax.get_xbound()).centroid()
# appending to the list, self and Integrals are equivalent to list -
self.Integ += Integrals(self.data, separation=self.sep.value, wings=self.wings.value,
bias=self.data.absmax*self.bias.value/100)
self.Integ.calibrate(calibration=calib)
self.print(None)
self.disp()
[docs] def ob(self, event):
if event['name']=='value':
self.disp()
[docs] def disp(self, zoom=False):
"refresh display from event - if zoom is True, display only in xbound"
self.xb = self.ax.get_xbound()
# self.yb = self.ax.get_ybound()
self.ax.clear()
if zoom:
zoom = self.xb
else:
zoom = None
self.data.display(new_fig=False, figure=self.ax, scale=self.scale.value, zoom=zoom)
try:
self.Integ.display(label=True, figure=self.ax, labelyposition=0.01, regions=False, zoom=zoom)
except:
pass
self.ax.set_xbound(self.xb)
# self.ax.set_ybound(self.yb)
# if __name__ == '__main__':
# unittest.main()