6 Plugin regarding general force clamp measurements
8 from libhooke import WX_GOOD, ClickedPoint
10 import libhookecurve as lhc
11 wxversion.select(WX_GOOD)
12 from wx import PostEvent
\r
14 class generalclampCommands:
\r
16 def plotmanip_clamp(self, plot, current, customvalue=False):
18 Handles some viewing options for the "force clamp" data format, depending on the state of these configuration variables:
\r
19 (1) If self.config['fc_showphase'] != 0, the 'phase' data column (i.e. the 2nd) is shown in the 0th graph (else it isn't)
\r
20 (2) If self.config['fc_showimposed'] != 0, the 'imposed deflection' data column (i.e. the 5th) is shown in the 1st graph (else it isn't)
\r
21 (3) If self.config['fc_interesting'] == 0, the entire curve is shown in the graphs; if it has a non-zero value N, only phase N is shown.
23 NOTE - my implementation of point(3) feels quite awkward - someone smarter than me plz polish that!
\r
27 #not a fclamp curve...
28 if current.curve.experiment != 'clamp':
31 if self.config['fc_interesting'] != 0 and plot.destination==0:
\r
32 lower = int((self.config['fc_interesting'])-1)
\r
33 upper = int((self.config['fc_interesting'])+1)
\r
34 trim = current.curve.trimindexes()[lower:upper]
\r
38 for x in range(trim[0],trim[1]):
\r
39 newtime.append(self.plots[0].vectors[0][0][x])
\r
40 newzpiezo.append(self.plots[0].vectors[0][1][x])
\r
41 newphase.append(self.plots[0].vectors[1][1][x])
\r
42 self.plots[0].vectors[0][0] = newtime
\r
43 self.plots[0].vectors[0][1] = newzpiezo
\r
44 self.plots[0].vectors[1][0] = newtime
\r
45 self.plots[0].vectors[1][1] = newphase
\r
47 if self.config['fc_interesting'] != 0 and plot.destination==1:
\r
48 lower = int((self.config['fc_interesting'])-1)
\r
49 upper = int((self.config['fc_interesting'])+1)
\r
50 trim = current.curve.trimindexes()[lower:upper]
\r
54 for x in range(trim[0],trim[1]):
\r
55 newtime.append(self.plots[1].vectors[0][0][x])
\r
56 newdefl.append(self.plots[1].vectors[0][1][x])
\r
57 newimposed.append(self.plots[1].vectors[1][1][x])
\r
58 self.plots[1].vectors[0][0] = newtime
\r
59 self.plots[1].vectors[0][1] = newdefl
\r
60 self.plots[1].vectors[1][0] = newtime
\r
61 self.plots[1].vectors[1][1] = newimposed
\r
63 if self.config['fc_showphase'] == 0 and plot.destination==0:
\r
64 self.plots[0].remove_set(1)
\r
66 if self.config['fc_showimposed'] == 0 and plot.destination==1:
\r
67 self.plots[1].remove_set(1)
\r
71 def do_time(self,args):
73 Measures the time difference (in seconds) between two points
74 Implemented only for force clamp
78 if self.current.curve.experiment == 'clamp':
\r
79 time=self._delta(set=0)[0]
\r
80 print str(time*1000)+' ms'
82 print 'This command makes no sense for a non-force clamp experiment.'
84 def do_zpiezo(self,args):
86 Measures the zpiezo difference (in nm) between two points
87 Implemented only for force clamp
91 if self.current.curve.experiment == 'clamp':
92 zpiezo=self._delta(set=0)[2]
\r
93 print str(zpiezo*(10**9))+' nm'
95 print 'This command makes no sense for a non-force clamp experiment.'
97 def do_defl(self,args):
99 Measures the deflection difference (in nm) between two points
100 Implemented only for force clamp
101 NOTE: It makes sense only on the time VS defl plot; it is still not masked for the other plot...
105 if self.current.curve.experiment == 'clamp':
106 print "Warning - don't use on the zpiezo plot!"
107 defl=self._delta(set=1)[2]
108 print str(defl*(10**12))+' pN'
110 print 'This command makes no sense for a non-force clamp experiment.'
112 def do_step(self,args):
114 Measures the length and time duration of a time-Z step
118 if self.current.curve.experiment == 'clamp':
119 print 'Click three points in this fashion:'
120 print ' (0)-------(1)'
123 print ' (2)----------'
124 points=self._measure_N_points(N=3,whatset=0)
125 dz=abs(points[2].graph_coords[1]-points[1].graph_coords[1])*(10e+8)
126 dt=abs(points[1].graph_coords[0]-points[0].graph_coords[0])
127 print 'dZ: ',dz,' nm'
131 print 'This command makes no sense for a non-force clamp experiment.'
\r
133 def do_fcfilt(self,args):
\r
135 Filters out featureless force clamp curves of the current playlist.
\r
136 It's very similar to 'flatfilt' for velocity clamp curves.
\r
137 Creates a new playlist only containing non-empty curves.
\r
139 WARNING - Only works if you set an appropriate fc_interesting config variable!
\r
140 WARNING - arguments are NOT optional at the moment!
\r
142 Syntax: fcfilt maxretraction(nm) mindeviation (pN)
\r
144 Suggested values for an (i27)8 experiment with our setup are 200nm and 10-15 pN
\r
147 if self.config['fc_interesting'] == 0:
\r
148 print 'You must specify the phase of interest (using set fc_interesing X) prior to running fcfilt!'
\r
153 args=args.split(' ')
\r
155 maxretraction=int(args[0])
\r
156 threshold=int(args[1])
\r
158 print 'Arguments are not optional for fcfilt. You should pass two numbers:'
\r
159 print '(1) the maximum plausible piezo retraction in NANOMETERS (e.g. the length of the protein)'
\r
160 print "(2) the threshold, in PICONEWTONS. If signal deviates from imposed more than this, it's an event"
\r
164 print 'Processing playlist... go get yourself a cup of coffee.'
\r
169 for item in self.current_list:
\r
172 notflat=self.has_stuff(item,maxretraction,threshold)
\r
173 print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->Has Stuff =',notflat
\r
176 print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->could not be processed'
\r
178 item.features=notflat
\r
180 notflat_list.append(item)
\r
182 if len(notflat_list)==0:
\r
183 print 'Nothing interesting here. Reconsider either your filtering criteria or your experimental data'
\r
186 print 'Found',len(notflat_list),'potentially interesting curves.'
\r
187 print 'Regenerating Playlist...'
\r
189 self.current_list=notflat_list
\r
190 self.current=self.current_list[self.pointer]
\r
193 def has_stuff(self,item,maxretraction,threshold):
\r
195 Decides whether a curve has some features in the interesting phase.
\r
197 - clip the interesting phase portion of the curve.
\r
198 - discard the first 20 milliseconds (this is due to a quirk of our hardware).
\r
199 - look at the zpiezo plot and note down when (if) retratcs more than [maxretraction] nm away from the first point.
\r
200 - clip off any data after this point, with an excess of 100 points (again, an hardware quirk)
\r
201 - if the remainder is less than 100 points, ditch the curve.
\r
202 - now look at the deflection plot and check if there are points more than [threshold] pN over the 'flat zone'.
\r
203 - if you find such points, bingo!
\r
206 item.identify(self.drivers)
\r
208 lower = int((self.config['fc_interesting'])-1)
\r
209 upper = int((self.config['fc_interesting'])+1)
\r
210 trim_idxs = item.curve.trimindexes()[lower:upper]
\r
211 lo=trim_idxs[0]+20 #clipping the first 20 points off...
\r
213 trimmed_zpiezo=item.curve.default_plots()[0].vectors[0][1][lo:hi]
\r
214 trimmed_defl=item.curve.default_plots()[1].vectors[0][1][lo:hi]
\r
215 trimmed_imposed=item.curve.default_plots()[1].vectors[1][1][lo:hi]
\r
216 imposed=trimmed_imposed[21] #just to match the 20-pts clipping...
\r
218 item.curve.close_all()
\r
222 starting_z=trimmed_zpiezo[0]
\r
223 plausible=starting_z-(maxretraction*1e-9)
\r
225 while trimmed_zpiezo[det_trim]>plausible:
\r
227 if det_trim >= len(trimmed_zpiezo): #breaking cycles makes me shiver...
\r
228 det_trim=len(trimmed_zpiezo) #but I cannot think of anything better now.
\r
230 further_trim=det_trim-100
\r
231 if further_trim<100:
\r
233 trimmed_defl=trimmed_defl[:further_trim]
\r
235 trimmed_defl.sort()
\r
236 ninetypercent=int(0.9*len(trimmed_defl))
\r
239 for j in trimmed_defl[:ninetypercent]:
\r
241 avg=float(sum/ninetypercent)
\r
242 sweetspot=float(avg+(threshold*1e-12))
\r
243 if trimmed_defl[-1]>sweetspot:
\r
248 del trimmed_defl,trimmed_zpiezo,trimmed_imposed
\r