3 """Plugin regarding general force clamp measurements
6 from hooke.libhooke import WX_GOOD, ClickedPoint
9 wxversion.select(WX_GOOD)
10 from wx import PostEvent
12 from .. import curve as lhc
15 class generalclampCommands(object):
17 def plotmanip_clamp(self, plot, current, customvalue=False):
19 Handles some viewing options for the "force clamp" data format, depending on the state of these configuration variables:
20 (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)
21 (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)
22 (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.
24 NOTE - my implementation of point(3) feels quite awkward - someone smarter than me plz polish that!
28 #not a fclamp curve...
29 if current.curve.experiment != 'clamp':
32 if self.config['fc_interesting'] != 0 and plot.destination==0:
33 lower = int((self.config['fc_interesting'])-1)
34 upper = int((self.config['fc_interesting'])+1)
35 trim = current.curve.trimindexes()[lower:upper]
39 for x in range(trim[0],trim[1]):
40 newtime.append(self.plots[0].vectors[0][0][x])
41 newzpiezo.append(self.plots[0].vectors[0][1][x])
42 newphase.append(self.plots[0].vectors[1][1][x])
43 self.plots[0].vectors[0][0] = newtime
44 self.plots[0].vectors[0][1] = newzpiezo
45 self.plots[0].vectors[1][0] = newtime
46 self.plots[0].vectors[1][1] = newphase
48 if self.config['fc_interesting'] != 0 and plot.destination==1:
49 lower = int((self.config['fc_interesting'])-1)
50 upper = int((self.config['fc_interesting'])+1)
51 trim = current.curve.trimindexes()[lower:upper]
55 for x in range(trim[0],trim[1]):
56 newtime.append(self.plots[1].vectors[0][0][x])
57 newdefl.append(self.plots[1].vectors[0][1][x])
58 newimposed.append(self.plots[1].vectors[1][1][x])
59 self.plots[1].vectors[0][0] = newtime
60 self.plots[1].vectors[0][1] = newdefl
61 self.plots[1].vectors[1][0] = newtime
62 self.plots[1].vectors[1][1] = newimposed
64 if self.config['fc_showphase'] == 0 and plot.destination==0:
65 self.plots[0].remove_set(1)
67 if self.config['fc_showimposed'] == 0 and plot.destination==1:
68 self.plots[1].remove_set(1)
72 def do_time(self,args):
74 Measures the time difference (in seconds) between two points
75 Implemented only for force clamp
79 if self.current.curve.experiment == 'clamp':
80 time=self._delta(set=0)[0]
81 print str(time*1000)+' ms'
83 print 'This command makes no sense for a non-force clamp experiment.'
85 def do_zpiezo(self,args):
87 Measures the zpiezo difference (in nm) between two points
88 Implemented only for force clamp
92 if self.current.curve.experiment == 'clamp':
93 zpiezo=self._delta(set=0)[2]
94 print str(zpiezo*(10**9))+' nm'
96 print 'This command makes no sense for a non-force clamp experiment.'
98 def do_defl(self,args):
100 Measures the deflection difference (in nm) between two points
101 Implemented only for force clamp
102 NOTE: It makes sense only on the time VS defl plot; it is still not masked for the other plot...
106 if self.current.curve.experiment == 'clamp':
107 print "Warning - don't use on the zpiezo plot!"
108 defl=self._delta(set=1)[2]
109 print str(defl*(10**12))+' pN'
111 print 'This command makes no sense for a non-force clamp experiment.'
113 def do_step(self,args):
115 Measures the length and time duration of a time-Z step
119 if self.current.curve.experiment == 'clamp':
120 print 'Click three points in this fashion:'
121 print ' (0)-------(1)'
124 print ' (2)----------'
125 points=self._measure_N_points(N=3,whatset=0)
126 dz=abs(points[2].graph_coords[1]-points[1].graph_coords[1])*(10e+8)
127 dt=abs(points[1].graph_coords[0]-points[0].graph_coords[0])
128 print 'dZ: ',dz,' nm'
132 print 'This command makes no sense for a non-force clamp experiment.'
134 def do_fcfilt(self,args):
136 Filters out featureless force clamp curves of the current playlist.
137 It's very similar to 'flatfilt' for velocity clamp curves.
138 Creates a new playlist only containing non-empty curves.
140 WARNING - Only works if you set an appropriate fc_interesting config variable!
141 WARNING - arguments are NOT optional at the moment!
143 Syntax: fcfilt maxretraction(nm) mindeviation (pN)
145 Suggested values for an (i27)8 experiment with our setup are 200nm and 10-15 pN
148 if self.config['fc_interesting'] == 0:
149 print 'You must specify the phase of interest (using set fc_interesing X) prior to running fcfilt!'
156 maxretraction=int(args[0])
157 threshold=int(args[1])
159 print 'Arguments are not optional for fcfilt. You should pass two numbers:'
160 print '(1) the maximum plausible piezo retraction in NANOMETERS (e.g. the length of the protein)'
161 print "(2) the threshold, in PICONEWTONS. If signal deviates from imposed more than this, it's an event"
165 print 'Processing playlist... go get yourself a cup of coffee.'
170 for item in self.current_list:
173 notflat=self.has_stuff(item,maxretraction,threshold)
174 print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->Has Stuff =',notflat
177 print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->could not be processed'
179 item.features=notflat
181 notflat_list.append(item)
183 if len(notflat_list)==0:
184 print 'Nothing interesting here. Reconsider either your filtering criteria or your experimental data'
187 print 'Found',len(notflat_list),'potentially interesting curves.'
188 print 'Regenerating playlist...'
190 self.current_list=notflat_list
191 self.current=self.current_list[self.pointer]
194 def has_stuff(self,item,maxretraction,threshold):
196 Decides whether a curve has some features in the interesting phase.
198 - clip the interesting phase portion of the curve.
199 - discard the first 20 milliseconds (this is due to a quirk of our hardware).
200 - look at the zpiezo plot and note down when (if) retratcs more than [maxretraction] nm away from the first point.
201 - clip off any data after this point, with an excess of 100 points (again, an hardware quirk)
202 - if the remainder is less than 100 points, ditch the curve.
203 - now look at the deflection plot and check if there are points more than [threshold] pN over the 'flat zone'.
204 - if you find such points, bingo!
207 item.identify(self.drivers)
209 lower = int((self.config['fc_interesting'])-1)
210 upper = int((self.config['fc_interesting'])+1)
211 trim_idxs = item.curve.trimindexes()[lower:upper]
212 lo=trim_idxs[0]+20 #clipping the first 20 points off...
214 trimmed_zpiezo=item.curve.default_plots()[0].vectors[0][1][lo:hi]
215 trimmed_defl=item.curve.default_plots()[1].vectors[0][1][lo:hi]
216 trimmed_imposed=item.curve.default_plots()[1].vectors[1][1][lo:hi]
217 imposed=trimmed_imposed[21] #just to match the 20-pts clipping...
219 item.curve.close_all()
223 starting_z=trimmed_zpiezo[0]
224 plausible=starting_z-(maxretraction*1e-9)
226 while trimmed_zpiezo[det_trim]>plausible:
228 if det_trim >= len(trimmed_zpiezo): #breaking cycles makes me shiver...
229 det_trim=len(trimmed_zpiezo) #but I cannot think of anything better now.
231 further_trim=det_trim-100
234 trimmed_defl=trimmed_defl[:further_trim]
237 ninetypercent=int(0.9*len(trimmed_defl))
240 for j in trimmed_defl[:ninetypercent]:
242 avg=float(sum/ninetypercent)
243 sweetspot=float(avg+(threshold*1e-12))
244 if trimmed_defl[-1]>sweetspot:
249 del trimmed_defl,trimmed_zpiezo,trimmed_imposed