Implemented fcfilt - similar to flatfilt, but for force clamp curves.
authormarcobrucale <devnull@localhost>
Thu, 26 Jun 2008 16:02:18 +0000 (16:02 +0000)
committermarcobrucale <devnull@localhost>
Thu, 26 Jun 2008 16:02:18 +0000 (16:02 +0000)
Cleaned up older commands (e.g. using self._delta instead of self.measure_N_points)

generalclamp.py

index 14974dc7225380678f8064fdaf390e2cd8e50012..24ad22ba005f5345466c1b57914c65b696ac4b71 100644 (file)
 '''
 GENERALCLAMP.py
 
-(c) 2008 Marco Brucale, Massimo Sandal
-
 Plugin regarding general force clamp measurements
 '''
 from libhooke import WX_GOOD, ClickedPoint
-import wxversion
+import wxversion\r
 import libhookecurve as lhc
 wxversion.select(WX_GOOD)
-from wx import PostEvent
-
-class generalclampCommands:
+from wx import PostEvent\r
 
+class generalclampCommands:\r
+\r
     def plotmanip_clamp(self, plot, current, customvalue=False):
         '''
-        Handles some viewing options for the "force clamp" data format, depending on the state of these configuration variables:
-        (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)
-        (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)
+        Handles some viewing options for the "force clamp" data format, depending on the state of these configuration variables:\r
+        (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
+        (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
         (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.
-
-        NOTE - my implementation of point(3) feels quite awkward - someone smarter than me plz polish that!
-
+\r
+        NOTE - my implementation of point(3) feels quite awkward - someone smarter than me plz polish that!\r
+\r
         '''
         
         #not a fclamp curve...
         if current.curve.experiment != 'clamp':
-            return plot
-
-        if self.config['fc_interesting'] != 0 and plot.destination==0:
-            lower = int((self.config['fc_interesting'])-1)
-            upper = int((self.config['fc_interesting'])+1)
-            trim = current.curve.trimindexes()[lower:upper]
-            newtime = []
-            newzpiezo = []
-            newphase = []
-            for x in range(trim[0],trim[1]):
-                newtime.append(self.plots[0].vectors[0][0][x])
-                newzpiezo.append(self.plots[0].vectors[0][1][x])
-                newphase.append(self.plots[0].vectors[1][1][x])
-            self.plots[0].vectors[0][0] = newtime
-            self.plots[0].vectors[0][1] = newzpiezo
-            self.plots[0].vectors[1][0] = newtime
-            self.plots[0].vectors[1][1] = newphase
-
-        if self.config['fc_interesting'] != 0 and plot.destination==1:
-            lower = int((self.config['fc_interesting'])-1)
-            upper = int((self.config['fc_interesting'])+1)
-            trim = current.curve.trimindexes()[lower:upper]
-            newtime = []
-            newdefl = []
-            newimposed = []
-            for x in range(trim[0],trim[1]):
-                newtime.append(self.plots[1].vectors[0][0][x])
-                newdefl.append(self.plots[1].vectors[0][1][x])
-                newimposed.append(self.plots[1].vectors[1][1][x])
-            self.plots[1].vectors[0][0] = newtime
-            self.plots[1].vectors[0][1] = newdefl
-            self.plots[1].vectors[1][0] = newtime
-            self.plots[1].vectors[1][1] = newimposed            
-                        
-        if self.config['fc_showphase'] == 0 and plot.destination==0:
-            self.plots[0].remove_set(1)
-            
-        if self.config['fc_showimposed'] == 0 and plot.destination==1:
-            self.plots[1].remove_set(1)
-                         
+            return plot\r
+\r
+        if self.config['fc_interesting'] != 0 and plot.destination==0:\r
+            lower = int((self.config['fc_interesting'])-1)\r
+            upper = int((self.config['fc_interesting'])+1)\r
+            trim = current.curve.trimindexes()[lower:upper]\r
+            newtime = []\r
+            newzpiezo = []\r
+            newphase = []\r
+            for x in range(trim[0],trim[1]):\r
+                newtime.append(self.plots[0].vectors[0][0][x])\r
+                newzpiezo.append(self.plots[0].vectors[0][1][x])\r
+                newphase.append(self.plots[0].vectors[1][1][x])\r
+            self.plots[0].vectors[0][0] = newtime\r
+            self.plots[0].vectors[0][1] = newzpiezo\r
+            self.plots[0].vectors[1][0] = newtime\r
+            self.plots[0].vectors[1][1] = newphase\r
+\r
+        if self.config['fc_interesting'] != 0 and plot.destination==1:\r
+            lower = int((self.config['fc_interesting'])-1)\r
+            upper = int((self.config['fc_interesting'])+1)\r
+            trim = current.curve.trimindexes()[lower:upper]\r
+            newtime = []\r
+            newdefl = []\r
+            newimposed = []\r
+            for x in range(trim[0],trim[1]):\r
+                newtime.append(self.plots[1].vectors[0][0][x])\r
+                newdefl.append(self.plots[1].vectors[0][1][x])\r
+                newimposed.append(self.plots[1].vectors[1][1][x])\r
+            self.plots[1].vectors[0][0] = newtime\r
+            self.plots[1].vectors[0][1] = newdefl\r
+            self.plots[1].vectors[1][0] = newtime\r
+            self.plots[1].vectors[1][1] = newimposed            \r
+                        \r
+        if self.config['fc_showphase'] == 0 and plot.destination==0:\r
+            self.plots[0].remove_set(1)\r
+            \r
+        if self.config['fc_showimposed'] == 0 and plot.destination==1:\r
+            self.plots[1].remove_set(1)\r
+                         \r
         return plot
       
     def do_time(self,args):
         '''
-        TIME
-        Measure the time difference (in seconds) between two points
+        Measures the time difference (in seconds) between two points
         Implemented only for force clamp
         ----
         Syntax: time
         '''
-        if self.current.curve.experiment == 'clamp':
-            print 'Click two points.'
-            time=self._delta(set=0)[0]
+        if self.current.curve.experiment == 'clamp':\r
+            time=self._delta(set=0)[0]\r
             print str(time*1000)+' ms'
         else:
             print 'This command makes no sense for a non-force clamp experiment.'
             
     def do_zpiezo(self,args):
         '''
-        ZPIEZO
-        Measure the zpiezo difference (in nm) between two points
+        Measures the zpiezo difference (in nm) between two points
         Implemented only for force clamp
         ----
         Syntax: zpiezo
         '''
         if self.current.curve.experiment == 'clamp':
-            print 'Click two points.'
-            points=self._measure_N_points(N=2)
-            zpiezo=abs(points[0].graph_coords[1]-points[1].graph_coords[1])
+            zpiezo=self._delta(set=0)[2]\r
             print str(zpiezo*(10**9))+' nm'
-            to_dump='zpiezo '+self.current.path+' '+str(zpiezo*(10**9))+' nm'
-            self.outlet.push(to_dump)
         else:
             print 'This command makes no sense for a non-force clamp experiment.'
             
     def do_defl(self,args):
         '''
-        DEFL
-        Measure the deflection difference (in nm) between two points
+        Measures the deflection difference (in nm) between two points
         Implemented only for force clamp
         NOTE: It makes sense only on the time VS defl plot; it is still not masked for the other plot...
         -----
         Syntax: defl
         '''
         if self.current.curve.experiment == 'clamp':
-            print 'Click two points.'
-            points=self._measure_N_points(N=2)
-            defl=abs(points[0].graph_coords[1]-points[1].graph_coords[1])
+            print "Warning - don't use on the zpiezo plot!"
+            defl=self._delta(set=1)[2]
             print str(defl*(10**12))+' pN'
-            to_dump='deflection '+self.current.path+' '+str(defl*(10**12))+' pN'
-            self.outlet.push(to_dump)
         else:
             print 'This command makes no sense for a non-force clamp experiment.'
             
     def do_step(self,args):
         '''
-        STEP
-        
         Measures the length and time duration of a time-Z step
         -----
         Syntax: step
@@ -141,8 +126,124 @@ class generalclampCommands:
             dt=abs(points[1].graph_coords[0]-points[0].graph_coords[0])
             print 'dZ: ',dz,' nm'
             print 'dT: ',dt,' s'
-            to_dump='step '+self.current.path+' '+'dZ: '+str(dz)+' nm'+' dT: '+str(dt)+' s'
-            self.outlet.push(to_dump)
             
         else:
-            print 'This command makes no sense for a non-force clamp experiment.'
\ No newline at end of file
+            print 'This command makes no sense for a non-force clamp experiment.'\r
+\r
+    def do_fcfilt(self,args):\r
+        '''\r
+        Filters out featureless force clamp curves of the current playlist.\r
+        It's very similar to 'flatfilt' for velocity clamp curves.\r
+        Creates a new playlist only containing non-empty curves.\r
+\r
+        WARNING - Only works if you set an appropriate fc_interesting config variable!\r
+        WARNING - arguments are NOT optional at the moment!\r
+\r
+        Syntax: fcfilt maxretraction(nm) mindeviation (pN)\r
+\r
+        Suggested values for an (i27)8 experiment with our setup are 200nm and 10-15 pN\r
+        '''\r
+\r
+        if self.config['fc_interesting'] == 0:\r
+            print 'You must specify the phase of interest (using set fc_interesing X) prior to running fcfilt!'\r
+            return\r
+        \r
+        maxretraction=0\r
+        threshold=0\r
+        args=args.split(' ')\r
+        if len(args)==2:\r
+            maxretraction=int(args[0])\r
+            threshold=int(args[1])\r
+        else:\r
+            print 'Arguments are not optional for fcfilt. You should pass two numbers:'\r
+            print '(1) the maximum plausible piezo retraction in NANOMETERS (e.g. the length of the protein)'\r
+            print "(2) the threshold, in PICONEWTONS. If signal deviates from imposed more than this, it's an event"\r
+            return\r
+        \r
+\r
+        print 'Processing playlist... go get yourself a cup of coffee.'\r
+        notflat_list=[]\r
+\r
+        c=0\r
+\r
+        for item in self.current_list:\r
+            c+=1\r
+            try:\r
+                notflat=self.has_stuff(item,maxretraction,threshold)\r
+                print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->Has Stuff =',notflat\r
+            except:\r
+                notflat=False\r
+                print 'Curve',item.path,'is',c,'of',len(self.current_list),'--->could not be processed'\r
+            if notflat:\r
+                item.features=notflat\r
+                item.curve=None\r
+                notflat_list.append(item)\r
+\r
+        if len(notflat_list)==0:\r
+            print 'Nothing interesting here. Reconsider either your filtering criteria or your experimental data'\r
+            return\r
+        else:\r
+            print 'Found',len(notflat_list),'potentially interesting curves.'\r
+            print 'Regenerating Playlist...'\r
+            self.pointer=0\r
+            self.current_list=notflat_list\r
+            self.current=self.current_list[self.pointer]\r
+            self.do_plot(0)\r
+\r
+    def has_stuff(self,item,maxretraction,threshold):\r
+        '''\r
+        Decides whether a curve has some features in the interesting phase.\r
+        Algorithm:\r
+            - clip the interesting phase portion of the curve.\r
+            - discard the first 20 milliseconds (this is due to a quirk of our hardware).\r
+            - look at the zpiezo plot and note down when (if) retratcs more than [maxretraction] nm away from the first point.\r
+            - clip off any data after this point, with an excess of 100 points (again, an hardware quirk)\r
+            - if the remainder is less than 100 points, ditch the curve.\r
+            - now look at the deflection plot and check if there are points more than [threshold] pN over the 'flat zone'.\r
+            - if you find such points, bingo!            \r
+        '''\r
+\r
+        item.identify(self.drivers)\r
+   \r
+        lower = int((self.config['fc_interesting'])-1)\r
+        upper = int((self.config['fc_interesting'])+1)\r
+        trim_idxs = item.curve.trimindexes()[lower:upper]\r
+        lo=trim_idxs[0]+20                                                  #clipping the first 20 points off...\r
+        hi=trim_idxs[1]\r
+        trimmed_zpiezo=item.curve.default_plots()[0].vectors[0][1][lo:hi]\r
+        trimmed_defl=item.curve.default_plots()[1].vectors[0][1][lo:hi]\r
+        trimmed_imposed=item.curve.default_plots()[1].vectors[1][1][lo:hi]\r
+        imposed=trimmed_imposed[21]                                         #just to match the 20-pts clipping...\r
+        \r
+        item.curve.close_all()\r
+        del item.curve\r
+        del item\r
+\r
+        starting_z=trimmed_zpiezo[0]\r
+        plausible=starting_z-(maxretraction*1e-9)\r
+        det_trim=0\r
+        while trimmed_zpiezo[det_trim]>plausible:\r
+            det_trim+=1\r
+            if det_trim >= len(trimmed_zpiezo):                              #breaking cycles makes me shiver...\r
+                det_trim=len(trimmed_zpiezo)                                 #but I cannot think of anything better now.\r
+                break\r
+        further_trim=det_trim-100\r
+        if further_trim<100:\r
+            return False\r
+        trimmed_defl=trimmed_defl[:further_trim]\r
+\r
+        trimmed_defl.sort()\r
+        ninetypercent=int(0.9*len(trimmed_defl))\r
+        j=0\r
+        sum=0\r
+        for j in trimmed_defl[:ninetypercent]:\r
+            sum+=j\r
+        avg=float(sum/ninetypercent)\r
+        sweetspot=float(avg+(threshold*1e-12))\r
+        if trimmed_defl[-1]>sweetspot:\r
+            flag=True\r
+        else:\r
+            flag=False\r
+\r
+        return flag            \r
+        
\ No newline at end of file