Example #1
0
    def find_contact_point2(self, debug=False):
        """
        TO BE DEVELOPED IN THE FUTURE
        Finds the contact point on the curve.
            
        FIXME: should be moved, probably to generalvclamp.py
        """

        # raw_plot=self.current.curve.default_plots()[0]
        raw_plot = self.plots[0]
        """xext=self.plots[0].vectors[0][0]
        yext=self.plots[0].vectors[0][1]
        xret2=self.plots[0].vectors[1][0]
        yret=self.plots[0].vectors[1][1]
        """
        xext = raw_plot.vectors[0][0]
        yext = raw_plot.vectors[0][1]
        xret2 = raw_plot.vectors[1][0]
        yret = raw_plot.vectors[1][1]

        first_point = [xext[0], yext[0]]
        last_point = [xext[-1], yext[-1]]

        # regr=scipy.polyfit(first_point, last_point,1)[0:2]
        diffx = abs(first_point[0] - last_point[0])
        diffy = abs(first_point[1] - last_point[1])

        # using polyfit results in numerical errors. good old algebra.
        a = diffy / diffx
        b = first_point[1] - (a * first_point[0])
        baseline = scipy.polyval((a, b), xext)

        ysub = [item - basitem for item, basitem in zip(yext, baseline)]

        contact = ysub.index(min(ysub))

        return xext, ysub, contact

        # now, exploit a ClickedPoint instance to calculate index...
        dummy = ClickedPoint()
        dummy.absolute_coords = (x_intercept, y_intercept)
        dummy.find_graph_coords(xret2, yret)

        if debug:
            return dummy.index, regr, regr_contact
        else:
            return dummy.index
Example #2
0
    def do_fit(self, args):
        """
        FIT
        (fit.py plugin)
        Fits an entropic elasticity function to a given chunk of the curve.

        First you have to click a contact point.
        Then you have to click the two edges of the data you want to fit.
        
        Fit quality compares the distance to the fit with the thermal noise (a good fit should be close to 1)
        
        The fit function depends on the fit_function variable. You can set it with the command
        "set fit_function wlc" or  "set fit_function fjc" depending on the function you prefer.
        
        For WLC, the function is the simple polynomial worm-like chain as proposed by 
        C.Bustamante, J.F.Marko, E.D.Siggia and S.Smith (Science. 1994 
        Sep 9;265(5178):1599-600.)
        
        For FJC, ref: 
        C.Ray and B.B. Akhremitchev; http://www.chem.duke.edu/~boris/research/force_spectroscopy/fit_efjc.pdf
        
        For eFJC, ref:
        F Oesterhelt, M Rief and H E Gaub, New Journal of Physics 1 (1999) 6.1–6.11 (section 4.2)
        NOTE: use fixed pl for better results.

        Arguments:
        pl=[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.
        
        noauto : allows for clicking the contact point by 
                 hand (otherwise it is automatically estimated) the first time.
                 If subsequent measurements are made, the same contact point
                 clicked is used
        
        reclick : redefines by hand the contact point, if noauto has been used before
                  but the user is unsatisfied of the previously choosen contact point.
        ---------
        Syntax: fit [pl=(value)] [t=value] [noauto]
        """
        pl_value = None
        T = self.config["temperature"]
        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
            # look for a T argument. FIXME: spaces are not allowed between 'pl' and value
            if ("t=" in arg[0:2]) or ("T=" in arg[0:2]):
                t_expression = arg.split("=")
                T = float(t_expression[1])

        # use the currently displayed plot for the fit
        displayed_plot = self._get_displayed_plot()

        # handle contact point arguments correctly
        if "reclick" in args.split():
            print "Click contact point"
            contact_point = self._measure_N_points(N=1, whatset=1)[0]
            contact_point_index = contact_point.index
            self.wlccontact_point = contact_point
            self.wlccontact_index = contact_point.index
            self.wlccurrent = self.current.path
        elif "noauto" in args.split():
            if self.wlccontact_index == None or self.wlccurrent != self.current.path:
                print "Click contact point"
                contact_point = self._measure_N_points(N=1, whatset=1)[0]
                contact_point_index = contact_point.index
                self.wlccontact_point = contact_point
                self.wlccontact_index = contact_point.index
                self.wlccurrent = self.current.path
            else:
                contact_point = self.wlccontact_point
                contact_point_index = self.wlccontact_index
        else:
            cindex = self.find_contact_point()
            contact_point = ClickedPoint()
            contact_point.absolute_coords = displayed_plot.vectors[1][0][cindex], displayed_plot.vectors[1][1][cindex]
            contact_point.find_graph_coords(displayed_plot.vectors[1][0], displayed_plot.vectors[1][1])
            contact_point.is_marker = True

        print "Click edges of chunk"
        points = self._measure_N_points(N=2, whatset=1)
        points = [contact_point] + points

        try:
            if self.config["fit_function"] == "wlc":
                params, yfit, xfit, fit_errors, qstd = self.wlc_fit(
                    points, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1], pl_value, T, return_errors=True
                )
                name_of_charlength = "Persistent length"
            elif self.config["fit_function"] == "fjc":
                params, yfit, xfit, fit_errors, qstd = self.fjc_fit(
                    points, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1], pl_value, T, return_errors=True
                )
                name_of_charlength = "Kuhn length"
            elif self.config["fit_function"] == "efjc":
                params, yfit, xfit, fit_errors, qstd = self.efjc_fit(
                    points, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1], pl_value, T, return_errors=True
                )
                name_of_charlength = "Kuhn length (e)"
            else:
                print "No recognized fit function defined!"
                print "Set your fit function to wlc, fjc or efjc."
                return

        except:
            print "Fit not possible. Probably wrong interval -did you click two *different* points?"
            return

        # FIXME: print "Kuhn length" for FJC
        print "Fit function:", self.config["fit_function"]
        print "Contour length: %.2f nm" % (params[0] * (1.0e9))
        to_dump = "contour " + self.current.path + " %.2f nm" % (params[0] * (1.0e9))
        self.outlet.push(to_dump)
        if len(params) == 2:  # if we did choose 2-value fit
            print name_of_charlength + ": %.2f nm" % (params[1] * (1.0e9))
            to_dump = "persistent " + self.current.path + " %.2f nm" % (params[1] * (1.0e9))
            self.outlet.push(to_dump)

        if fit_errors:
            fit_nm = [i * (10 ** 9) for i in fit_errors]
            print "Standard deviation (contour length) %.2f" % fit_nm[0]
            if len(fit_nm) > 1:
                print "Standard deviation (" + name_of_charlength + ") %.2f" % fit_nm[1]

        print "Fit quality: %.3f " % (qstd / np.std(displayed_plot.vectors[1][1][-20:-1]))

        # add the clicked points in the final PlotObject
        clickvector_x, clickvector_y = [], []
        for item in points:
            clickvector_x.append(item.graph_coords[0])
            clickvector_y.append(item.graph_coords[1])

        # create a custom PlotObject to gracefully plot the fit along the curves

        fitplot = copy.deepcopy(displayed_plot)
        fitplot.add_set(xfit, yfit)
        fitplot.add_set(clickvector_x, clickvector_y)

        # FIXME: this colour/styles stuff must be solved at the root!
        if fitplot.styles == []:
            fitplot.styles = [None, None, None, "scatter"]
        else:
            fitplot.styles += [None, "scatter"]

        if fitplot.colors == []:
            fitplot.colors = [None, None, None, None]
        else:
            fitplot.colors += [None, None]

        self._send_plot([fitplot])