From d2b868bb350d1ddf8c5d46343c74fdd0114060d1 Mon Sep 17 00:00:00 2001 From: albertogomcas Date: Thu, 11 Mar 2010 12:02:18 +0000 Subject: [PATCH] multifit.py : new plugin, mouse input based generalvclamp.py : separated code from do_slope into _slope allowing use in other funtions hooke.conf: activate multifit plugin by default --- generalvclamp.py | 35 +++-- hooke.conf | 3 +- multifit.py | 330 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+), 15 deletions(-) create mode 100644 multifit.py diff --git a/generalvclamp.py b/generalvclamp.py index 85a4bce..3e534a9 100644 --- a/generalvclamp.py +++ b/generalvclamp.py @@ -253,30 +253,34 @@ class generalvclampCommands: if fitspan == 0: # Gets the Xs of two clicked points as indexes on the current curve vector print 'Click twice to delimit chunk' - clickedpoints=[] points=self._measure_N_points(N=2,whatset=1) - clickedpoints=[points[0].index,points[1].index] - clickedpoints.sort() else: print 'Click once on the leftmost point of the chunk (i.e.usually the peak)' - clickedpoints=[] points=self._measure_N_points(N=1,whatset=1) - clickedpoints=[points[0].index-fitspan,points[0].index] - - # Calls the function linefit_between + + slope=self._slope(points,fitspan) + + # Outputs the relevant slope parameter + print 'Slope:' + print str(slope) + to_dump='slope '+self.current.path+' '+str(slope) + self.outlet.push(to_dump) + + def _slope(self,points,fitspan): + # Calls the function linefit_between parameters=[0,0,[],[]] + try: + clickedpoints=[points[0].index,points[1].index] + clickedpoints.sort() + except: + clickedpoints=[points[0].index-fitspan,points[0].index] + try: parameters=self.linefit_between(clickedpoints[0],clickedpoints[1]) except: print 'Cannot fit. Did you click twice the same point?' return - - # Outputs the relevant slope parameter - print 'Slope:' - print str(parameters[0]) - to_dump='slope '+self.current.path+' '+str(parameters[0]) - self.outlet.push(to_dump) - + # Makes a vector with the fitted parameters and sends it to the GUI xtoplot=parameters[2] ytoplot=[] @@ -307,6 +311,9 @@ class generalvclampCommands: self._send_plot([lineplot]) + return parameters[0] + + def linefit_between(self,index1,index2,whatset=1): ''' Creates two vectors (xtofit,ytofit) slicing out from the diff --git a/hooke.conf b/hooke.conf index 6723440..3a49693 100755 --- a/hooke.conf +++ b/hooke.conf @@ -39,7 +39,8 @@ This section defines which plugins have to be loaded by Hooke. - + + CLI COMMUNICATION + + +class multifitCommands: + + def do_multifit(self,args): + ''' + MULTIFIT + (multifit.py) + Presents curves for manual analysis in a comfortable mouse-only fashion. Obtains + contour length, persistance length, rupture force and slope - loading rate. + WLC is shown in red, FJC in blue. + ------------- + Syntax: + multifit [pl=value] [kl=value] [t=value] [slopew=value] [basew=value] [justone] + + pl=[value] and kl=[value]: Use a fixed persistent length (WLC) or Kuhn length (FJC) for + the fit. If pl is not given, the fit will be a 2-variable fit. + DO NOT put spaces between 'pl', '=' and the value. + The value must be in nanometers. + + t=[value] : Use a user-defined temperature. The value must be in kelvins; + by default it is 293 K. + DO NOT put spaces between 't', '=' and the value. + + slopew and basew : width in points for slope fitting (points to the right of clicked rupture) + and base level fitting(points to the left of clicked top of rupture), default is 15. + DO NOT put spaces between 'slopew' or 'basew', '=' and the value. + + justone : performs the fits over current curve instead of iterating + + see fit command help for more information on the options and fit procedures. + + NOTE: centerzero plot modifier should be activated (set centerzero 1). + ''' + + #NOTE duplicates a lot of code from do_fit in fit.py, a call to it could be used directly + #but it is easier to control the program flow bypassing it + + pl_value=None + kl_value=None + T=self.config['temperature'] + slopew=15 + basew=15 + justone=False + + #FIXME spaces are not allowed between pl or t and value + for arg in args.split(): + #look for a persistent length argument. + if 'pl=' in arg: + pl_expression=arg.split('=') + pl_value=float(pl_expression[1]) #actual value + if 'kl=' in arg: + kl_expression=arg.split('=') + kl_value=float(kl_expression[1]) #actual value + #look for a T argument. + if ('t=' in arg) or ('T=' in arg): + t_expression=arg.split('=') + T=float(t_expression[1]) + #look for a basew argument. + if ('basew=' in arg): + basew_expression=arg.split('=') + basew=int(basew_expression[1]) + #look for a slopew argument. + if ('slopew=' in arg): + slopew_expression=arg.split('=') + slopew=int(slopew_expression[1]) + if('justone' in arg): + justone=True + + counter=0 + savecounter=0 + curveindex=0 + + if not justone: + print 'What curve no. you would like to start? (enter for ignoring)' + skip=raw_input() + + if skip.isdigit()==False: + skip=0 + else: + skip=int(skip)-1 + print 'Skipping '+str(skip)+ ' curves' + else: + skip=0 + #begin presenting curves for analysis + while curveindex curveindex: + curveindex+=1 + continue + + #give periodically the opportunity to stop the analysis + if counter%20==0 and counter>0: + print '\nYou checked '+str(counter)+' curves. Do you want to continue?' + self.current=curve + self.do_plot(0) + if self.YNclick(): + print 'Going on...' + else: + break + else: + self.current=curve + self.do_plot(0) + else: + curve=self.current + self.do_plot(0) + if not justone: + print '\nCurve '+str(curveindex+1)+' of '+str(len(self.current_list)) + print 'Click contact point or left end of the curve to skip' + #FIXME "left half" is a bit ad hoc, and "set correct 1" makes + #the 3/4s point not very reliable. + #Anyway clicking the end should be safe + contact_point=self._measure_N_points(N=1, whatset=1)[0] + contact_point_index=contact_point.index + + retract=self.plots[0].vectors[1][0] + + #some fixing for x data that is negative (depends on driver) + if min(retract)<0: + cppoint=contact_point.graph_coords[0]+abs(min(retract)) + retract=retract+abs(min(retract)) + else: + cppoint=contact_point.graph_coords[0] + threequarters=3*(max(retract)-min(retract))/4 + + + if cppoint < threequarters: + if justone: + break + curveindex+=1 + continue + + self.wlccontact_point=contact_point + self.wlccontact_index=contact_point.index + self.wlccurrent=self.current.path + + print 'Now click two points for the fitting area (one should be the rupture point)' + wlcpoints=self._measure_N_points(N=2,whatset=1) + print 'And one point of the top of the jump' + toppoint=self._measure_N_points(N=1,whatset=1) + + fitpoints=[contact_point]+wlcpoints + #use the currently displayed plot for the fit + displayed_plot=self._get_displayed_plot() + + #use both fit functions + try: + wlcparams, wlcyfit, wlcxfit, wlcfit_errors = self.wlc_fit(fitpoints, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1],pl_value,T, return_errors=True ) + wlcerror=False + except: + print 'WLC fit not possible' + wlcerror=True + + try: + fjcparams, fjcyfit, fjcxfit, fjcfit_errors = self.fjc_fit(fitpoints, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1],kl_value,T, return_errors=True ) + fjcerror=False + except: + print 'FJC fit not possible' + fjcerror=True + + #Measure rupture force + ruptpoint=ClickedPoint() + if wlcpoints[0].graph_coords[1]