4 Plugin regarding general force clamp measurements
6 from libhooke import WX_GOOD, ClickedPoint
8 import libhookecurve as lhc
9 wxversion.select(WX_GOOD)
10 from wx import PostEvent
12 class generalclampCommands(object):
14 def plotmanip_clamp(self, plot, current, customvalue=False):
16 Handles some viewing options for the "force clamp" data format, depending on the state of these configuration variables:
17 (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)
18 (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)
19 (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.
21 NOTE - my implementation of point(3) feels quite awkward - someone smarter than me plz polish that!
25 #not a fclamp curve...
26 if current.curve.experiment != 'clamp':
29 if self.config['fc_interesting'] != 0 and plot.destination==0:
30 lower = int((self.config['fc_interesting'])-1)
31 upper = int((self.config['fc_interesting'])+1)
32 trim = current.curve.trimindexes()[lower:upper]
36 for x in range(trim[0],trim[1]):
37 newtime.append(self.plots[0].vectors[0][0][x])
38 newzpiezo.append(self.plots[0].vectors[0][1][x])
39 newphase.append(self.plots[0].vectors[1][1][x])
40 self.plots[0].vectors[0][0] = newtime
41 self.plots[0].vectors[0][1] = newzpiezo
42 self.plots[0].vectors[1][0] = newtime
43 self.plots[0].vectors[1][1] = newphase
45 if self.config['fc_interesting'] != 0 and plot.destination==1:
46 lower = int((self.config['fc_interesting'])-1)
47 upper = int((self.config['fc_interesting'])+1)
48 trim = current.curve.trimindexes()[lower:upper]
52 for x in range(trim[0],trim[1]):
53 newtime.append(self.plots[1].vectors[0][0][x])
54 newdefl.append(self.plots[1].vectors[0][1][x])
55 newimposed.append(self.plots[1].vectors[1][1][x])
56 self.plots[1].vectors[0][0] = newtime
57 self.plots[1].vectors[0][1] = newdefl
58 self.plots[1].vectors[1][0] = newtime
59 self.plots[1].vectors[1][1] = newimposed
61 if self.config['fc_showphase'] == 0 and plot.destination==0:
62 self.plots[0].remove_set(1)
64 if self.config['fc_showimposed'] == 0 and plot.destination==1:
65 self.plots[1].remove_set(1)
69 def do_time(self,args):
71 Measures the time difference (in seconds) between two points
72 Implemented only for force clamp
76 if self.current.curve.experiment == 'clamp':
77 time=self._delta(set=0)[0]
78 print str(time*1000)+' ms'
80 print 'This command makes no sense for a non-force clamp experiment.'
82 def do_zpiezo(self,args):
84 Measures the zpiezo difference (in nm) between two points
85 Implemented only for force clamp
89 if self.current.curve.experiment == 'clamp':
90 zpiezo=self._delta(set=0)[2]
91 print str(zpiezo*(10**9))+' nm'
93 print 'This command makes no sense for a non-force clamp experiment.'
95 def do_defl(self,args):
97 Measures the deflection difference (in nm) between two points
98 Implemented only for force clamp
99 NOTE: It makes sense only on the time VS defl plot; it is still not masked for the other plot...
103 if self.current.curve.experiment == 'clamp':
104 print "Warning - don't use on the zpiezo plot!"
105 defl=self._delta(set=1)[2]
106 print str(defl*(10**12))+' pN'
108 print 'This command makes no sense for a non-force clamp experiment.'
110 def do_step(self,args):
112 Measures the length and time duration of a time-Z step
116 if self.current.curve.experiment == 'clamp':
117 print 'Click three points in this fashion:'
118 print ' (0)-------(1)'
121 print ' (2)----------'
122 points=self._measure_N_points(N=3,whatset=0)
123 dz=abs(points[2].graph_coords[1]-points[1].graph_coords[1])*(10e+8)
124 dt=abs(points[1].graph_coords[0]-points[0].graph_coords[0])
125 print 'dZ: ',dz,' nm'
129 print 'This command makes no sense for a non-force clamp experiment.'
131 def do_fcfilt(self,args):
133 Filters out featureless force clamp curves of the current playlist.
134 It's very similar to 'flatfilt' for velocity clamp curves.
135 Creates a new playlist only containing non-empty curves.
137 WARNING - Only works if you set an appropriate fc_interesting config variable!
138 WARNING - arguments are NOT optional at the moment!
140 Syntax: fcfilt maxretraction(nm) mindeviation (pN)
142 Suggested values for an (i27)8 experiment with our setup are 200nm and 10-15 pN
145 if self.config['fc_interesting'] == 0:
146 print 'You must specify the phase of interest (using set fc_interesing X) prior to running fcfilt!'
153 maxretraction=int(args[0])
154 threshold=int(args[1])
156 print 'Arguments are not optional for fcfilt. You should pass two numbers:'
157 print '(1) the maximum plausible piezo retraction in NANOMETERS (e.g. the length of the protein)'
158 print "(2) the threshold, in PICONEWTONS. If signal deviates from imposed more than this, it's an event"
162 print 'Processing playlist... go get yourself a cup of coffee.'
167 for item in self.current_list:
170 notflat=self.has_stuff(item,maxretraction,threshold)
171 print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->Has Stuff =',notflat
174 print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->could not be processed'
176 item.features=notflat
178 notflat_list.append(item)
180 if len(notflat_list)==0:
181 print 'Nothing interesting here. Reconsider either your filtering criteria or your experimental data'
184 print 'Found',len(notflat_list),'potentially interesting curves.'
185 print 'Regenerating Playlist...'
187 self.current_list=notflat_list
188 self.current=self.current_list[self.pointer]
191 def has_stuff(self,item,maxretraction,threshold):
193 Decides whether a curve has some features in the interesting phase.
195 - clip the interesting phase portion of the curve.
196 - discard the first 20 milliseconds (this is due to a quirk of our hardware).
197 - look at the zpiezo plot and note down when (if) retratcs more than [maxretraction] nm away from the first point.
198 - clip off any data after this point, with an excess of 100 points (again, an hardware quirk)
199 - if the remainder is less than 100 points, ditch the curve.
200 - now look at the deflection plot and check if there are points more than [threshold] pN over the 'flat zone'.
201 - if you find such points, bingo!
204 item.identify(self.drivers)
206 lower = int((self.config['fc_interesting'])-1)
207 upper = int((self.config['fc_interesting'])+1)
208 trim_idxs = item.curve.trimindexes()[lower:upper]
209 lo=trim_idxs[0]+20 #clipping the first 20 points off...
211 trimmed_zpiezo=item.curve.default_plots()[0].vectors[0][1][lo:hi]
212 trimmed_defl=item.curve.default_plots()[1].vectors[0][1][lo:hi]
213 trimmed_imposed=item.curve.default_plots()[1].vectors[1][1][lo:hi]
214 imposed=trimmed_imposed[21] #just to match the 20-pts clipping...
216 item.curve.close_all()
220 starting_z=trimmed_zpiezo[0]
221 plausible=starting_z-(maxretraction*1e-9)
223 while trimmed_zpiezo[det_trim]>plausible:
225 if det_trim >= len(trimmed_zpiezo): #breaking cycles makes me shiver...
226 det_trim=len(trimmed_zpiezo) #but I cannot think of anything better now.
228 further_trim=det_trim-100
231 trimmed_defl=trimmed_defl[:further_trim]
234 ninetypercent=int(0.9*len(trimmed_defl))
237 for j in trimmed_defl[:ninetypercent]:
239 avg=float(sum/ninetypercent)
240 sweetspot=float(avg+(threshold*1e-12))
241 if trimmed_defl[-1]>sweetspot:
246 del trimmed_defl,trimmed_zpiezo,trimmed_imposed