Fix: genlist can now import files without extension
[hooke.git] / autopeak.py
index 8638cc2273b0f5a0f2d2169cdefe3e35a4d68546..8a7baafe9fb876c25886e7ad28d6144040365d77 100644 (file)
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 
 from libhooke import WX_GOOD, ClickedPoint
 import wxversion
@@ -22,7 +23,7 @@ class autopeakCommands:
         (autopeak.py)
         Automatically performs a number of analyses on the peaks of the given curve.
         Currently it automatically:
-        - fits peaks with WLC function
+        - fits peaks with WLC or FJC function (depending on how the fit_function variable is set)
         - measures peak maximum forces with a baseline
         - measures slope in proximity of peak maximum
         Requires flatten plotmanipulator , fit.py plugin , flatfilts.py plugin with convfilt
@@ -52,6 +53,8 @@ class autopeakCommands:
         
         usepoints : fit interval by number of points instead than by nanometers
         
+        noflatten : does not use the "flatten" plot manipulator
+        
         When you first issue the command, it will ask for the filename. If you are giving the filename
         of an existing file, autopeak will resume it and append measurements to it. If you are giving
         a new filename, it will create the file and append to it until you close Hooke.
@@ -59,18 +62,25 @@ class autopeakCommands:
         
         Useful variables (to set with SET command):
         ---
-        temperature= temperature of the system for wlc fit (in K)
+        fit_function = type of function to use for elasticity. If "wlc" worm-like chain is used, if "fjc" freely jointed
+                       chain is used
+        
+        temperature= temperature of the system for wlc/fjc fit (in K)
         
         auto_slope_span = number of points on which measure the slope, for slope
         
-        auto_fit_nm = number of nm to fit before the peak maximum, for WLC (if usepoints false)
-        auto_fit_points = number of points to fit before the peak maximum, for WLC (if usepoints true)
+        auto_fit_nm = number of nm to fit before the peak maximum, for WLC/FJC (if usepoints false)
+        auto_fit_points = number of points to fit before the peak maximum, for WLC/FJC (if usepoints true)
         
-        baseline_clicks = 0: automatic baseline
-                          1: decide baseline with a single click and length defined in auto_left_baseline
-                          2: let user click points of baseline
+        baseline_clicks = -1: no baseline, f=0 at the contact point (whether hand-picked or automatically found)
+                           0: automatic baseline
+                           1: decide baseline with a single click and length defined in auto_left_baseline
+                           2: let user click points of baseline
         auto_left_baseline = length in nm to use as baseline from the right point (if baseline_clicks=0 , 1)
         auto_right_baseline = distance in nm of peak-most baseline point from last peak (if baseline_clicks = 0)
+        
+        auto_min_p ; auto_max_p = Minimum and maximum persistence length (if using WLC) or Kuhn length (if using FJC)
+                                outside of which the peak is automatically discarded (in nm)
         '''
         
         #MACROS.
@@ -109,11 +119,12 @@ class autopeakCommands:
             self.wlccurrent=self.current.path
             return contact_point, contact_point_index
         
-        def find_current_peaks():
+        def find_current_peaks(noflatten):
             #Find peaks.
             defplot=self.current.curve.default_plots()[0]
-            flatten=self._find_plotmanip('flatten') #Extract flatten plotmanip
-            defplot=flatten(defplot, self.current, customvalue=1) #Flatten curve before feeding it to has_peaks
+            if not noflatten:
+                flatten=self._find_plotmanip('flatten') #Extract flatten plotmanip
+                defplot=flatten(defplot, self.current, customvalue=1) #Flatten curve before feeding it to has_peaks
             peak_location,peak_size=self.has_peaks(defplot, self.convfilt_config['mindeviation'])
             return peak_location, peak_size
     
@@ -124,6 +135,7 @@ class autopeakCommands:
         slope_span=int(self.config['auto_slope_span'])
         delta_force=10
         rebase=False #if true=we select rebase
+        noflatten=False #if true=we avoid flattening
         
         #initialize output data vectors
         c_lengths=[]
@@ -148,6 +160,9 @@ class autopeakCommands:
         if 'rebase' in args or (self.basecurrent != self.current.path):
             rebase=True 
         
+        if 'noflatten' in args:
+            noflatten=True
+        
         #--Custom persistent length / custom temperature
         for arg in args.split():
             #look for a persistent length argument.
@@ -176,7 +191,11 @@ class autopeakCommands:
         #--END COMMAND LINE PARSING--
         
         
-        peak_location, peak_size = find_current_peaks()
+        peak_location, peak_size = find_current_peaks(noflatten)
+        
+        if len(peak_location) == 0:
+            print 'No peaks to fit.'
+            return
         
         fitplot=copy.deepcopy(displayed_plot)
         
@@ -205,6 +224,12 @@ class autopeakCommands:
         to_average=displayed_plot.vectors[1][1][boundaries[0]:boundaries[1]] #y points to average
         avg=np.mean(to_average)
         
+        clicks=self.config['baseline_clicks']
+        if clicks==-1:
+            try:
+                avg=displayed_plot.vectors[1][1][contact_point_index]
+            except:
+                avg=displayed_plot.vectors[1][1][cindex]
         
         for peak in peak_location:
             #WLC FITTING
@@ -220,9 +245,17 @@ class autopeakCommands:
             if abs(peak_point.index-other_fit_point.index) < 2:
                 continue
             
-            params, yfit, xfit, fit_errors = self.wlc_fit(points, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1], pl_value, T, return_errors=True)
-            
+            if self.config['fit_function']=='wlc':
                 
+                params, yfit, xfit, fit_errors = self.wlc_fit(points, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1], pl_value, T, return_errors=True)
+            elif self.config['fit_function']=='fjc':
+                params, yfit, xfit, fit_errors = self.fjc_fit(points, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1], pl_value, T, return_errors=True)
+            else:
+                print 'Unknown fit function'
+                print 'Please set fit_function as wlc or fjc'
+                return
+            
+            
             #Measure forces
             delta_to_measure=displayed_plot.vectors[1][1][peak-delta_force:peak+delta_force]
             y=min(delta_to_measure)
@@ -244,8 +277,10 @@ class autopeakCommands:
                 fitplot.add_set(xfit,yfit)
                 if len(fitplot.styles)==0:
                     fitplot.styles=[]
+                    fitplot.colors=[]
                 else:
                     fitplot.styles.append(None)
+                    fitplot.colors.append(None)
             else: #2-value fit
                 p_leng=params[1]*(1.0e+9)
                 #check if persistent length makes sense. otherwise, discard peak.
@@ -261,6 +296,7 @@ class autopeakCommands:
                     fitplot.add_set(xfit,yfit)
                     if len(fitplot.styles)==0:
                         fitplot.styles=[]
+                        fitplot.colors=[]
                     else:
                         fitplot.styles.append(None)
                         fitplot.colors.append(None)
@@ -271,12 +307,13 @@ class autopeakCommands:
         #add basepoints to fitplot
         fitplot.add_set([self.basepoints[0].graph_coords[0],self.basepoints[1].graph_coords[0]],[self.basepoints[0].graph_coords[1],self.basepoints[1].graph_coords[1]]) 
         fitplot.styles.append('scatter')
-        
+        fitplot.colors.append(None)
         
         #Show wlc fits and peak locations
         self._send_plot([fitplot])
         #self.do_peaks('')
         
+        print 'Using fit function: ',self.config['fit_function']
         print 'Measurements for all peaks detected:'
         print 'contour (nm)', c_lengths
         print 'sigma contour (nm)',sigma_c_lengths
@@ -285,26 +322,33 @@ class autopeakCommands:
         print 'forces (pN)',forces
         print 'slopes (N/m)',slopes
         
-        #Ask the user what peaks to ignore from analysis.
-        print 'Peaks to ignore (0,1...n from contact point,return to take all)'
-        print 'N to discard measurement'
-        exclude_raw=raw_input('Input:')
-        if exclude_raw=='N':
-            print 'Discarded.'
-            return
-        if not exclude_raw=='':
-            exclude=exclude_raw.split(',')
-            try:
-                exclude=[int(item) for item in exclude]
-                for i in exclude:
-                    c_lengths[i]=None
-                    p_lengths[i]=None
-                    forces[i]=None
-                    slopes[i]=None
-                    sigma_c_lengths[i]=None
-                    sigma_p_lengths[i]=None
-            except:
-                 print 'Bad input, taking all...'
+        controller=False
+        while controller==False:
+         #Ask the user what peaks to ignore from analysis.
+         print 'Peaks to ignore (0,1...n from contact point,return to take all)'
+         print 'N to discard measurement'
+         exclude_raw=raw_input('Input:')
+         if exclude_raw=='N':
+             print 'Discarded.'
+             return
+         if exclude_raw=='':
+             controller=True
+         if not exclude_raw=='':
+             exclude=exclude_raw.split(',')
+             try:
+                 exclude=[int(item) for item in exclude]
+                 for i in exclude:
+                     c_lengths[i]=None
+                     p_lengths[i]=None
+                     forces[i]=None
+                     slopes[i]=None
+                     sigma_c_lengths[i]=None
+                     sigma_p_lengths[i]=None
+                      controller=True
+             except:
+                 print 'Bad input.'
+                  controller=False
+
         #Clean data vectors from ignored peaks        
         #FIXME:code duplication
         c_lengths=[item for item in c_lengths if item != None]