1 # Copyright (C) 2008-2010 Alberto Gomez-Casado
2 # Massimo Sandal <devicerandom@gmail.com>
3 # W. Trevor King <wking@drexel.edu>
5 # This file is part of Hooke.
7 # Hooke is free software: you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation, either
10 # version 3 of the License, or (at your option) any later version.
12 # Hooke is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with Hooke. If not, see
19 # <http://www.gnu.org/licenses/>.
21 """Processed plots plugin for force curves.
24 from ..libhooke import WX_GOOD
26 wxversion.select(WX_GOOD)
34 from .. import curve as lhc
37 class procplotsCommands(object):
42 def do_derivplot(self,args):
46 Plots the derivate (actually, the discrete differentiation) of the current force curve
50 dplot=self.derivplot_curves()
51 plot_graph=self.list_of_events['plot_graph']
52 wx.PostEvent(self.frame,plot_graph(plots=[dplot]))
54 def derivplot_curves(self):
56 do_derivplot helper function
58 create derivate plot curves for force curves.
60 dplot=lhc.PlotObject()
63 for vector in self.plots[0].vectors:
64 dplot.vectors.append([])
65 dplot.vectors[-1].append(vector[0][:-1])
66 dplot.vectors[-1].append(np.diff(vector[1]))
69 dplot.units=self.plots[0].units
73 def do_subtplot(self, args):
77 Plots the difference between ret and ext current curve
81 #FIXME: sub_filter and sub_order must be args
83 if len(self.plots[0].vectors) != 2:
84 print 'This command only works on a curve with two different plots.'
87 outplot=self.subtract_curves(sub_order=1)
89 plot_graph=self.list_of_events['plot_graph']
90 wx.PostEvent(self.frame,plot_graph(plots=[outplot]))
92 def subtract_curves(self, sub_order):
94 subtracts the extension from the retraction
96 xext=self.plots[0].vectors[0][0]
97 yext=self.plots[0].vectors[0][1]
98 xret=self.plots[0].vectors[1][0]
99 yret=self.plots[0].vectors[1][1]
101 #we want the same number of points
102 maxpoints_tot=min(len(xext),len(xret))
103 xext=xext[0:maxpoints_tot]
104 yext=yext[0:maxpoints_tot]
105 xret=xret[0:maxpoints_tot]
106 yret=yret[0:maxpoints_tot]
109 ydiff=[yretval-yextval for yretval,yextval in zip(yret,yext)]
110 else: #reverse subtraction (not sure it's useful, but...)
111 ydiff=[yextval-yretval for yextval,yretval in zip(yext,yret)]
113 outplot=copy.deepcopy(self.plots[0])
114 outplot.vectors[0][0], outplot.vectors[1][0] = xext,xret #FIXME: if I use xret, it is not correct!
115 outplot.vectors[1][1]=ydiff
116 outplot.vectors[0][1]=[0 for item in outplot.vectors[1][0]]
121 #-----PLOT MANIPULATORS
122 def plotmanip_median(self, plot, current, customvalue=None):
124 does the median of the y values of a plot
127 median_filter=customvalue
129 median_filter=self.config['medfilt']
134 if float(median_filter)/2 == int(median_filter)/2:
137 nplots=len(plot.vectors)
140 plot.vectors[c][1]=scipy.signal.medfilt(plot.vectors[c][1],median_filter)
146 def plotmanip_correct(self, plot, current, customvalue=None):
148 does the correction for the deflection for a force spectroscopy curve.
150 - the current plot has a deflection() method that returns a vector of values
151 - the deflection() vector is as long as the X of extension + the X of retraction
152 - plot.vectors[0][0] is the X of extension curve
153 - plot.vectors[1][0] is the X of retraction curve
155 FIXME: both this method and the picoforce driver have to be updated, deflection() must return
156 a more senseful data structure!
158 #use only for force spectroscopy experiments!
159 if current.curve.experiment != 'smfs':
162 if customvalue != None:
163 execute_me=customvalue
165 execute_me=self.config['correct']
169 defl_ext,defl_ret=current.curve.deflection()
170 #halflen=len(deflall)/2
172 plot.vectors[0][0]=[(zpoint-deflpoint) for zpoint,deflpoint in zip(plot.vectors[0][0],defl_ext)]
173 plot.vectors[1][0]=[(zpoint-deflpoint) for zpoint,deflpoint in zip(plot.vectors[1][0],defl_ret)]
178 def plotmanip_centerzero(self, plot, current, customvalue=None):
180 Centers the force curve so the median (the free level) corresponds to 0 N
182 - plot.vectors[0][1] is the Y of extension curve
183 - plot.vectors[1][1] is the Y of retraction curve
187 #use only for force spectroscopy experiments!
188 if current.curve.experiment != 'smfs':
191 if customvalue != None:
192 execute_me=customvalue
194 execute_me=self.config['centerzero']
200 #levelapp=float(np.median(plot.vectors[0][1]))
201 levelret=float(np.median(plot.vectors[1][1][-300:-1]))
205 approach=[i-level for i in plot.vectors[0][1]]
206 retract=[i-level for i in plot.vectors[1][1]]
208 plot.vectors[0][1]=approach
209 plot.vectors[1][1]=retract
213 def plotmanip_detriggerize(self, plot, current, customvalue=None):
215 if self.config['detrigger']==0:
219 startvalue=plot.vectors[0][0][0]
221 for index in range(len(plot.vectors[0][0])-1,2,-2):
222 if plot.vectors[0][0][index]>startvalue:
227 plot.vectors[0][0]=plot.vectors[0][0][:cutindex]
228 plot.vectors[0][1]=plot.vectors[0][1][:cutindex]
235 #FFT---------------------------
236 def fft_plot(self, vector):
238 calculates the fast Fourier transform for the selected vector in the plot
240 fftplot=lhc.PlotObject()
243 fftlen=len(vector)/2 #need just 1/2 of length
244 fftplot.vectors[-1].append(np.arange(1,fftlen).tolist())
247 fftplot.vectors[-1].append(abs(np.fft(vector)[1:fftlen]).tolist())
248 except TypeError: #we take care of newer NumPy (1.0.x)
249 fftplot.vectors[-1].append(abs(np.fft.fft(vector)[1:fftlen]).tolist())
252 fftplot.destination=1
258 def do_fft(self,args):
261 (procplots.py plugin)
262 Plots the fast Fourier transform of the selected plot
264 Syntax: fft [top,bottom] [select] [0,1...]
266 By default, fft performs the Fourier transform on all the 0-th data set on the
269 [top,bottom]: which plot is the data set to fft (default: top)
270 [select]: you pick up two points on the plot and fft only the segment between
271 [0,1,...]: which data set on the selected plot you want to fft (default: 0)
275 #whatplot = plot to fft
276 #whatset = set to fft in the plot
277 select=('select' in args)
280 elif 'bottom' in args:
292 points=self._measure_N_points(N=2, whatset=whatset)
293 boundaries=[points[0].index, points[1].index]
295 y_to_fft=self.plots[whatplot].vectors[whatset][1][boundaries[0]:boundaries[1]] #y
297 y_to_fft=self.plots[whatplot].vectors[whatset][1] #y
299 fftplot=self.fft_plot(y_to_fft)
300 fftplot.units=['frequency', 'power']
301 plot_graph=self.list_of_events['plot_graph']
302 wx.PostEvent(self.frame,plot_graph(plots=[fftplot]))