def display_peaks(npkd, peak_label=False, peak_mode="marker", zoom=None, show=False, color=None, markersize=6, figure=None, scale=1.0, NbMaxPeaks=NbMaxDisplayPeaks, markerdict=None, labeldict=None): """ display the content of the peak list, peak_mode is either "marker" (default) or "bar" (1D only) zoom is in current unit. """ if npkd.dim == 1: z1, z2 = parsezoom(npkd, zoom) if npkd.axis1.itype == 0: # if real ff1 = npkd.axis1.itoc else: ff1 = lambda x: npkd.axis1.itoc(2 * x) return npkd.peaks.display(peak_label=peak_label, peak_mode=peak_mode, zoom=(z1, z2), show=show, f=ff1, color=color, markersize=markersize, figure=figure, scale=scale, NbMaxPeaks=NbMaxPeaks, markerdict=markerdict, labeldict=labeldict) elif npkd.dim == 2: z1lo, z1up, z2lo, z2up = parsezoom(npkd, zoom) if npkd.axis1.itype == 0: # if real ff1 = npkd.axis1.itoc else: ff1 = lambda x: npkd.axis1.itoc(2 * x) if npkd.axis2.itype == 0: # if real ff2 = npkd.axis2.itoc else: ff2 = lambda x: npkd.axis2.itoc(2 * x) return npkd.peaks.display(peak_label=peak_label, zoom=((z1lo, z1up), (z2lo, z2up)), show=show, f1=ff1, f2=ff2, color=color, markersize=markersize, figure=figure, NbMaxPeaks=NbMaxPeaks, markerdict=markerdict, labeldict=labeldict) else: raise Exception("to be done")
def peaks2d(npkd, threshold, zoom): ''' math code for NPKData 2D peak picker ''' npkd.check2D() #print threshold print("########## in peaks2d ") print("zoom ", zoom) z1lo, z1up, z2lo, z2up = parsezoom(npkd, zoom) print("z1lo, z1up, z2lo, z2up ", z1lo, z1up, z2lo, z2up) buff = npkd.get_buffer()[z1lo:z1up, z2lo:z2up] # take the zoom window if npkd.itype != 0: buff = buff.real # listpk=np.where(((buff > gold*np.ones(buff.shape))& # thresholding # (buff > np.roll(buff, 1, 0)) & # laplacian - kind of # (buff > np.roll(buff, -1, 0)) & # (buff > np.roll(buff, 1, 1)) & # (buff > np.roll(buff, -1, 1)))) # listpkF1 = int(z1lo) + listpk[0] # listpkF2 = int(z2lo) + listpk[1] # absolute coordinates # this second version is about 2x faster on my machine tbuff = buff[1:-1, 1:-1] # truncated version for shifting listpk = np.where( ((tbuff > threshold * np.ones(tbuff.shape)) & # thresholding (tbuff > buff[:-2, 1:-1]) & # laplacian - kind of (tbuff > buff[2:, 1:-1]) & (tbuff > buff[1:-1, :-2]) & (tbuff > buff[1:-1, 2:]))) listpkF1 = int(z1lo) + listpk[0] + 1 listpkF2 = int(z2lo) + listpk[1] + 1 # absolute coordinates listint = npkd.buffer[listpkF1, listpkF2] return listpkF1, listpkF2, listint
def display(self, integoff=0.3, integscale=0.5, color='red', label=False, labelyposition=None, regions=False, zoom=None, figure=None): "displays integrals" import matplotlib.transforms as transforms from spike.Display import testplot plt = testplot.plot() if figure is None: ax = plt.subplot(111) else: ax = figure # trans is a coordinate system where x is in current unit and y in 0..1 # used for drawing the integrals trans = transforms.blended_transform_factory( ax.transData, ax.transAxes ) z1, z2 = parsezoom(self.source, zoom) sumax = max([c.curve[-1] for c in self]) for iint in self: # print(a,b,max(c)/sumax) if iint.start>z2 or iint.end<z1: continue # we're outside xinteg = self.source.axis1.itoc( np.linspace(iint.start, iint.end, len(iint.curve)) ) yinteg = integoff + integscale*iint.curve/sumax ax.plot(xinteg, yinteg, transform=trans, color=color) if label: if labelyposition: xl = xinteg[0] + 0.3*(xinteg[-1]- xinteg[0]) yl = labelyposition else: xl = xinteg[-1] yl = yinteg[-1] ax.text(xl,yl,"%.2f"%iint.value, transform=trans, color=color, fontsize=7) if regions: ax.plot([xinteg[0],xinteg[0]], [0,1], transform=trans, color=color, alpha=0.1) ax.plot([xinteg[-1],xinteg[-1]], [0,1], transform=trans, color=color, alpha=0.1 )
def fit(npkd, zoom=None): """ fit the 1D npkd data-set for Lorentzian line-shape current peak list is used as an initial values for fitting Only peaks within the zoom windows are fitted fitting is contraint from the initial values - intensity will not allowed to change by more than x0.5 to x2 - positions by more than 5 points - width by more than x5 (constraints work only for scipy version >= 0.17 ) It may help to use centroid() to pre-optimize the peak list before calling fit(), or calling fit() twice (slower) """ # 3 parameters per peaks : Amp, Pos, Width z1, z2 = parsezoom(npkd, zoom) PP = [] minbound = [] maxbound = [] # load initial values and constraints from peak list for i,pk in enumerate(npkd.peaks): if pk.pos>=z1 and pk.pos<=z2: PP.append(pk.intens) # Amp minbound.append(0.5*pk.intens) maxbound.append(2*pk.intens) PP.append(pk.pos) # Pos minbound.append(pk.pos-5) maxbound.append(pk.pos+5) PP.append(max(1.0,pk.width)) # Width - mini is one pixel ! minbound.append(1E-3) maxbound.append(max(5.0,5*pk.width)) # print (PP) x = np.arange(1.0*npkd.size1)[z1:z2] Y = npkd.get_buffer()[z1:z2] Y = Y.real # kwargs={"jac":cdSpec} if scipy.__version__ > '0.17.0': PP1 = curve_fit(cSpec, x, Y, PP, bounds=(minbound,maxbound), method='dogbox') else: PP1 = curve_fit(cSpec, x, Y, PP) results = PP1[0] errors = np.sqrt(np.diag(PP1[1])) chi2 = tofit(results,x,Y) # computes error and store it npkd.peaks.chi2 = chi2 # copy back i = 0 for pk in npkd.peaks: if pk.pos>=z1 and pk.pos<=z2: pk.intens = results[3*i] pk.pos = results[3*i+1] pk.width = results[3*i+2] pk.intens_err = errors[3*i] pk.pos_err = errors[3*i+1] pk.width_err = errors[3*i+2] i += 1 return npkd
def simulate(npkd, zoom=None): """ Simulate the 1D npkd data-set using the content of the Peak List replace the current data-set """ # 3 parameters per peaks : Amp, Pos, Width z1, z2 = parsezoom(npkd, zoom) PP = [] for i,pk in enumerate(npkd.peaks): if pk.pos>=z1 and pk.pos<=z2: PP.append(pk.intens) # Amp PP.append(pk.pos) # Pos PP.append(max(1.0,pk.width)) # Width - mini is one pixel ! # print (PP) x = np.arange(1.0*npkd.cpxsize1) npkd.set_buffer( Spec(PP, x) ) return npkd
def peaks1d(npkd, threshold, zoom=None): """ math code for NPKData 1D peak picker """ npkd.check1D() z1, z2 = parsezoom(npkd, zoom) buff = npkd.get_buffer()[z1:z2] # take the zoom window if npkd.itype == 1: buff = buff.real tbuff = buff[1:-1] listpk = np.where( ((tbuff > threshold * np.ones(tbuff.shape)) & # thresholding (tbuff > buff[:-2]) & (tbuff > buff[2:]))) # roll 1 and -1 on axis 0 # return listpk[0] listpkF1 = int(z1) + listpk[0] + 1 listint = npkd.get_buffer()[listpkF1].real return listpkF1, listint
def to_display(self, zoom=((0, 1), (0, FTICR.FTMS.HighestMass)), verbose=False): """ computes and return which dataset to display at a given zoom and scale level" in: zoom = ((tlow, tup), (F2low,F2up)) - in min / m/z out: a tuple (data, zoomwindow), where data is a NPKData and zoomwindow an eventually recalibrated zoom window so, if DATA is an MR() object and Zoom a defined window in m/z ((F1low, F1up), (F2low,F2up)) the sequence: datasel, zz = DATA.to_display(Zoom) datasel.display(zoom=zz, scale=...) will display the selected zone with the best possible resolution """ # WARNING - different from 2DFTICR version z1, z2, z3, z4 = flatten(zoom) if verbose: print("F1: %.1f - %.1f min / F2: %.1f - %.1f m/z" % (z1, z2, z3, z4)) z1, z2 = min(z1, z2), max(z1, z2) z3, z4 = min(z3, z4), max(z3, z4) for reso, dl in enumerate(self.data): z11 = max(z1, self.Tmin) z33 = max(z3, float(dl.axis2.lowmass)) z22 = min(z2, self.Tmax) z44 = min(z4, self.highmass) z1lo, z1up, z2lo, z2up = parsezoom(dl, (z11, z22, z33, z44)) sz = (z1lo - z1up) * (z2lo - z2up) if sz < self.SIZEMAX: if verbose: print(reso, dl.size1, dl.size2, z1lo, z1up, z2lo, z2up, sz) break zooml = (dl.axis1.itom(z1lo), dl.axis1.itom(z1up), dl.axis2.itomz(z2up), dl.axis2.itomz(z2lo)) if verbose or self.Debug: print("zoom: F1 %.1f-%.1f / F2 %.1f-%.1f" % zooml) print("resolution level %d - %.1f Mpix zoom window" % (reso, sz / 1024 / 1024)) return dl, zooml
def display(self, integoff=0.3, integscale=0.5, color='red', label=False, labelxposition=1, labelyposition=None, regions=False, zoom=None, figure=None, curvedict=None, labeldict=None): """ displays integrals figure mpl axes to draw on - will create one if None zoom zoom integoff offset of drawing 0..1 integscale scale of the largest integral color color regions highlight regions curvedict additional parameters for the drawing label draw integral values labelxposition position of label in x 0..1 with respect to the integral drawing labelyposition position of label in y 0..1 with respect to the screen - None means top of integral labeldict additional parameters for the labels """ import matplotlib.transforms as transforms from spike.Display import testplot plt = testplot.plot() if figure is None: ax = plt.subplot(111) else: ax = figure # trans is a coordinate system where x is in current unit and y in 0..1 # used for drawing the integrals trans = transforms.blended_transform_factory(ax.transData, ax.transAxes) z1, z2 = parsezoom(self.source, zoom) sumax = max([c.curve[-1] for c in self]) # copy color to dict if needed if curvedict is None: curvedict = {} if labeldict is None: labeldict = {} for dico in (curvedict, labeldict): if 'color' not in dico.keys(): dico['color'] = color for iint in self: # print(a,b,max(c)/sumax) if iint.start > z2 or iint.end < z1: continue # we're outside xinteg = self.source.axis1.itoc( np.linspace(iint.start, iint.end, len(iint.curve))) yinteg = integoff + integscale * iint.curve / sumax ax.plot(xinteg, yinteg, transform=trans, **curvedict) if label: xl = xinteg[0] + labelxposition * (xinteg[-1] - xinteg[0]) if labelyposition is not None: yl = labelyposition else: yl = yinteg[-1] ax.text(xl, yl, "%.2f" % iint.value, transform=trans, **labeldict) if regions: ax.plot([xinteg[0], xinteg[0]], [0, 1], transform=trans, color=color, alpha=0.1) ax.plot([xinteg[-1], xinteg[-1]], [0, 1], transform=trans, color=color, alpha=0.1)
def bokeh_display(npkd, scale=1.0, autoscalethresh=3.0, absmax=None, show=False, title=None, label=None, xlabel="_def_", ylabel="_def_", axis=None, image=False, mode3D=False, zoom=None, mpldic={}, dbkdic={}, dfigdic={}, linewidth=1, color=None, plot_width=600, plot_height=400, sizing_mode=None, redraw=False, tools="pan, box_zoom, box_select, reset, save"): """ Display using bokeh instead of matplotlib scale allows to increase the vertical scale of display absmax overwrite the value for the largest point, which will not be computed display is scaled so that the largest point is first computed (and stored in absmax), and then the value at absmax/scale is set full screen show will call bk.show() at the end, allowing every declared display to be shown on-screen useless in ipython/jupyter notebook title add a title to the bokeh plot label add a label text to plot xlabel, ylabel axes label (default is self.currentunit - use None to remove) axis used as axis if present, axis length should match experiment length in 2D, should be a pair (xaxis,yaxis) image if True, the function will generate the 2D NMR FID of data, if False (Default), the function present contour plots. mode3D not implemented zoom is a tuple defining the zoom window (left,right) or ((F1_limits),(F2_limits)) defined in the current axis unit (points, ppm, m/z etc ....) mpldic a dictionnary passed as is to the matplotlib plot command dbkdic a dictionnary passed as is to populated the parameters of the bokeh graph dfigdic a dictionnary passed as is to populated the content of the bokeh figure linewidth linewidth for the plots (useful for example when using seaborn) color if 1D is the color of the curve, if 2D FID is the palette name to be used, if 2D contour is the color set to be used by matplotlib. plot_width, plot_height width and height of the plot sizing_mode if provided, resize plot according to the window chosen sizes. e.g. "scale_width", "scale_height", "scale_both" tools a string containing the tools to be available for bokeh interactivity. e.g. "pan, box_zoom, box_select, reset, save" (see bokeh doc for more info) """ #Settings global graphical parameters dbk = {} dbk['tools'] = tools dbk['title'] = title if sizing_mode is not None: dbk['sizing_mode'] = sizing_mode else: dbk['plot_width'] = plot_width dbk['plot_height'] = plot_height if npkd.dim == 1: if not absmax: # absmax is the largest point on spectrum, either given from call, or handled internally if not npkd.absmax: # compute it if absent #print "computing absmax...", npkd.absmax = np.nanmax(np.abs(npkd.buffer)) else: npkd.absmax = absmax mmin = -npkd.absmax / scale mmax = npkd.absmax / scale step = npkd.axis1.itype + 1 z1, z2 = parsezoom(npkd, zoom) while (z2 - z1) // step > BokehMax: step += 2 if axis is None: ax = npkd.axis1.unit_axis() else: ax = axis # fig.set_xscale(npkd.axis1.units[npkd.axis1.currentunit].scale) # set unit scale (log / linear) # if npkd.axis1.units[npkd.axis1.currentunit].reverse: # set reverse mode # ax.invert_xaxis() if xlabel == "_def_": xlabel = npkd.axis1.currentunit if ylabel == "_def_": ylabel = "a.u." if xlabel is not None: dbk['x_axis_label'] = xlabel if ylabel is not None: dbk['y_axis_label'] = ylabel dbk.update(dbkdic) dbk['x_range'] = (npkd.axis1.itoc(z1), npkd.axis1.itoc(z2)) p = bk.figure(**dbk) dfig = {} dfig['x'] = ax[z1:z2:step] dfig['y'] = npkd.buffer[z1:z2:step].clip(mmin, mmax) dfig['legend'] = label dfig['line_width'] = linewidth dfig['color'] = color dfig.update(dfigdic) p.line(**dfig) npkd.bokeh_fig = dfig npkd.bokeh_plot = p elif npkd.dim == 2 and image: # If image is set to True (Default False) - used to display 2D NMR FID as images bout1 = npkd.axis1.itoc(npkd.size1 - 1) bout2 = npkd.axis2.itoc(npkd.size2 - 1) deb1 = npkd.axis1.itoc(0) deb2 = npkd.axis2.itoc(0) dbk['x_range'] = (deb2, bout2) dbk['y_range'] = (deb1, bout1) if xlabel == "_def_": xlabel = npkd.axis2.currentunit if ylabel == "_def_": ylabel = npkd.axis1.currentunit if xlabel is not None: dbk['x_axis_label'] = xlabel if ylabel is not None: dbk['y_axis_label'] = ylabel dbk.update(dbkdic) p = bk.figure(**dbk) dfig = {} dfig['image'] = [npkd.get_buffer().real] if color is None: dfig['palette'] = bokeh.palettes.brewer['OrRd'][ 9][:-1] + bokeh.palettes.brewer['Blues'][9][::-1] else: dfig['palette'] = color #ex. "Magma256" dfig['x'] = deb2 dfig['y'] = deb1 dfig['dw'] = bout2 dfig['dh'] = bout1 dfig['legend'] = label dfig.update(dfigdic) p.image(**dfig) npkd.bokeh_fig = dfig npkd.bokeh_plot = p elif npkd.dim == 2 and not image: # When image is False, contour plots are generated for display. fig, ax = plt.subplots(figsize=( 9, 9 )) #The figure is created as if it was a classical matplotlib figure z1lo, z1up, z2lo, z2up = parsezoom(npkd, zoom) print(z1lo, z1up, z2lo, z2up) dbk['y_axis_type'] = npkd.axis1.units[ npkd.axis1. currentunit].scale # set unit scale (log / linear) for bokeh dbk['y_range'] = (npkd.axis1.itoc(z1lo), npkd.axis1.itoc(z1up)) dbk['x_axis_type'] = npkd.axis2.units[ npkd.axis2. currentunit].scale # set unit scale (log / linear) for bokeh dbk['x_range'] = (npkd.axis2.itoc(z2lo), npkd.axis2.itoc(z2up)) npkd.display(scale=scale, autoscalethresh=autoscalethresh, absmax=absmax, show=False, new_fig=False, axis=axis, zoom=zoom, title=None, figure=ax, color=color, mpldic=mpldic) if npkd.axis1.units[npkd.axis1.currentunit].reverse: ax.invert_yaxis() if npkd.axis2.units[npkd.axis2.currentunit].reverse: ax.invert_xaxis() if xlabel == "_def_": xlabel = npkd.axis2.currentunit if ylabel == "_def_": ylabel = npkd.axis1.currentunit if xlabel is not None: dbk['x_axis_label'] = xlabel if ylabel is not None: dbk['y_axis_label'] = ylabel dbk.update(dbkdic) xs, ys, col = get_contour_data(ax) if redraw: npkd.bokeh_fig['xs'] = xs npkd.bokeh_fig['ys'] = ys else: p = bk.figure(**dbk) xs, ys, col = get_contour_data(ax) dfig = {} dfig['xs'] = xs dfig['ys'] = ys dfig['color'] = col dfig.update(dfigdic) p.multi_line(**dfig) npkd.bokeh_fig = dfig npkd.bokeh_plot = p del fig, ax if show: bk.show(npkd.bokeh_plot) return npkd