hooke.py
authorillysam <devnull@localhost>
Fri, 19 Feb 2010 21:07:57 +0000 (21:07 +0000)
committerillysam <devnull@localhost>
Fri, 19 Feb 2010 21:07:57 +0000 (21:07 +0000)
- added ApplyPlotmanipulators()
- added configuration support to _delta()
- added linewidth option to UpdatePlot()
- 'fixed' GetDisplayedPlot()

hooke configspec.ini
- added curvetools plugin

hooke.ini
- added curvetools plugin
- added multidistance plugin
- removed plot plugin (do_replot() was moved to procplots.py)

curve.py
- added linewidth

playlist.py
- fixed the way the filename is retrieved from the playlist file

plugin.py
- added option section
- removed option key
- added comments

prettyformat.py
- fixed pretty_format() for 0 and NaN

results.py
- added class ResultsMultiDistance()
- fixed set_multipliers()

autopeak.ini/autopeak.py
- renamed 'peak_color' option to 'color'
- removed options: peak_show and peak_size (now in flatfilts.py-do_peaks())
- renamed x_values/y_values to retraction.x/retraction.y, respectively
- removed flatten plotmanipulator option (now in convfilt)

export.ini/export.py
- added append option

flatfilts.ini/flatfilts.py
- added apply_plotmanipulators option
- added configuration support to has_peaks()
- removed exec_has_peaks() as it is no longer necessary

generalvclamp.ini/generalvclamp.py
- added options: color, size to [distance]
- renamed 'show_points' to 'show' in [distance]
- added options: color, show, size to [force]
- added options: color, show, size to [forcebase]
- added options: point_color, point_show, point_size, slope_color, slope_linewidth, slope_show to [slope]
- added configuration support to do_distance(), do_force()

procplots.ini/procplots.py
- added option centerzero
- moved do_replot() form plot.py to procplots.py

results.py
- fixed do_show_results() to work with configuration options

20 files changed:
config/hooke configspec.ini
config/hooke.ini
hooke.py
lib/curve.py
lib/libhooke.py
lib/playlist.py
lib/plugin.py
lib/prettyformat.py
lib/results.py
plugins/autopeak.ini
plugins/autopeak.py
plugins/export.ini
plugins/export.py
plugins/flatfilts.ini
plugins/flatfilts.py
plugins/generalvclamp.ini
plugins/generalvclamp.py
plugins/procplots.ini
plugins/procplots.py
plugins/results.py

index 3bb1cdae060a683a1801b28c8d9cea3d2c41e183..f1cd81e6ffcd2d329cb5dbf8126069094bc1ed00 100644 (file)
@@ -27,6 +27,7 @@ active = string(default = Default)
 \r
 [plugins]\r
 autopeak = boolean(default = True)\r
+curvetools = boolean(default = True)\r
 export = boolean(default = True)\r
 fit = boolean(default = True)\r
 flatfilts = boolean(default = True)\r
index b80375379a8898d2211fba04899605c88b4a598d..6f96553d90f452632eb57e7203e18950ed5888fd 100644 (file)
@@ -39,12 +39,13 @@ default = Default
 #this section defines which plugins have to be loaded by Hooke\r
 [plugins]\r
 autopeak = True\r
+curvetools = True\r
 export = True\r
 fit = True\r
 flatfilts = True\r
 generalvclamp = True\r
+multidistance = True\r
 playlist = True\r
-plot = True\r
 procplots = True\r
 results = True\r
 \r
index 8be70d1926ea05fb4cbc8b269b2b0a73be987395..7c7a31105231853f72466a7eea7e303b0d64cb19 100644 (file)
--- a/hooke.py
+++ b/hooke.py
@@ -156,6 +156,8 @@ class HookeFrame(wx.Frame):
         self.plotmanipulators = []\r
         #self.plugins contains: {the name of the plugin: [caption, function]}\r
         self.plugins = {}\r
+        #self.results_str contains the type of results we want to display\r
+        self.results_str = 'wlc'\r
 \r
         #tell FrameManager to manage this frame\r
         self._mgr = aui.AuiManager()\r
@@ -440,11 +442,22 @@ class HookeFrame(wx.Frame):
 \r
     def AppliesPlotmanipulator(self, name):\r
         '''\r
-        returns True if the plotmanipulator 'name' is applied, False otherwise\r
+        Returns True if the plotmanipulator 'name' is applied, False otherwise\r
         name does not contain 'plotmanip_', just the name of the plotmanipulator (e.g. 'flatten')\r
         '''\r
         return self.GetBoolFromConfig('core', 'plotmanipulators', name)\r
 \r
+    def ApplyPlotmanipulators(self, plot, plot_file):\r
+        '''\r
+        Apply all active plotmanipulators.\r
+        '''\r
+        if plot is not None and plot_file is not None:\r
+            manipulated_plot = copy.deepcopy(plot)\r
+            for plotmanipulator in self.plotmanipulators:\r
+                if self.GetBoolFromConfig('core', 'plotmanipulators', plotmanipulator.name):\r
+                    manipulated_plot = plotmanipulator.method(manipulated_plot, plot_file)\r
+            return manipulated_plot\r
+\r
     def CreateApplicationIcon(self):\r
         iconFile = 'resources' + os.sep + 'microscope.ico'\r
         icon = wx.Icon(iconFile, wx.BITMAP_TYPE_ICO)\r
@@ -613,8 +626,8 @@ class HookeFrame(wx.Frame):
 \r
     def GetDisplayedPlot(self):\r
         plot = copy.deepcopy(self.displayed_plot)\r
-        plot.curves = []\r
-        plot.curves = copy.deepcopy(plot.curves)\r
+        #plot.curves = []\r
+        #plot.curves = copy.deepcopy(plot.curves)\r
         return plot\r
 \r
     def GetDisplayedPlotCorrected(self):\r
@@ -926,9 +939,10 @@ class HookeFrame(wx.Frame):
     def OnResultsCheck(self, index, flag):\r
         #TODO: fix for multiple results\r
         results = self.GetActivePlot().results\r
-        fit_function_str = self.GetStringFromConfig('results', 'show_results', 'fit_function')\r
-        results[fit_function_str].results[index].visible = flag\r
-        self.UpdatePlot()\r
+        if results.has_key(self.results_str):\r
+            results[self.results_str].results[index].visible = flag\r
+            results[self.results_str].update()\r
+            self.UpdatePlot()\r
 \r
     def OnSavePerspective(self, event):\r
 \r
@@ -1047,35 +1061,6 @@ class HookeFrame(wx.Frame):
             self.panelFolders.Fit()\r
         self._mgr.Update()\r
 \r
-    def _measure_N_points(self, N, message='', whatset=lh.RETRACTION):\r
-        '''\r
-        General helper function for N-points measurements\r
-        By default, measurements are done on the retraction\r
-        '''\r
-        if message != '':\r
-            dialog = wx.MessageDialog(None, message, 'Info', wx.OK)\r
-            dialog.ShowModal()\r
-\r
-        figure = self.GetActiveFigure()\r
-\r
-        xvector = self.displayed_plot.curves[whatset].x\r
-        yvector = self.displayed_plot.curves[whatset].y\r
-\r
-        clicked_points = figure.ginput(N, timeout=-1, show_clicks=True)\r
-\r
-        points = []\r
-        for clicked_point in clicked_points:\r
-            point = lh.ClickedPoint()\r
-            point.absolute_coords = clicked_point[0], clicked_point[1]\r
-            point.dest = 0\r
-            #TODO: make this optional?\r
-            #so far, the clicked point is taken, not the corresponding data point\r
-            point.find_graph_coords(xvector, yvector)\r
-            point.is_line_edge = True\r
-            point.is_marker = True\r
-            points.append(point)\r
-        return points\r
-\r
     def _clickize(self, xvector, yvector, index):\r
         '''\r
         returns a ClickedPoint() object from an index and vectors of x, y coordinates\r
@@ -1086,10 +1071,25 @@ class HookeFrame(wx.Frame):
         point.find_graph_coords(xvector, yvector)\r
         return point\r
 \r
-    def _delta(self, color='black', message='Click 2 points', show=True, whatset=1):\r
+    def _delta(self, message='Click 2 points', plugin=None):\r
         '''\r
         calculates the difference between two clicked points\r
         '''\r
+        if plugin is None:\r
+            color = 'black'\r
+            show_points = True\r
+            size = 20\r
+            whatset = lh.RETRACTION\r
+        else:\r
+            color = self.GetColorFromConfig(plugin.name, plugin.section, plugin.prefix + 'color')\r
+            show_points = self.GetBoolFromConfig(plugin.name, plugin.section, plugin.prefix + 'show_points')\r
+            size = self.GetIntFromConfig(plugin.name, plugin.section, plugin.prefix + 'size')\r
+            whatset_str = self.GetStringFromConfig(plugin.name, plugin.section, plugin.prefix + 'whatset')\r
+            if whatset_str == 'extension':\r
+                whatset = lh.EXTENSION\r
+            if whatset_str == 'retraction':\r
+                whatset = lh.RETRACTION\r
+\r
         clicked_points = self._measure_N_points(N=2, message=message, whatset=whatset)\r
         dx = abs(clicked_points[0].graph_coords[0] - clicked_points[1].graph_coords[0])\r
         dy = abs(clicked_points[0].graph_coords[1] - clicked_points[1].graph_coords[1])\r
@@ -1101,14 +1101,14 @@ class HookeFrame(wx.Frame):
         unity = curve.units.y\r
 \r
         #TODO: move this to clicked_points?\r
-        if show:\r
+        if show_points:\r
             for point in clicked_points:\r
                 points = copy.deepcopy(curve)\r
                 points.x = point.graph_coords[0]\r
                 points.y = point.graph_coords[1]\r
 \r
                 points.color = color\r
-                points.size = 20\r
+                points.size = size\r
                 points.style = 'scatter'\r
                 plot.curves.append(points)\r
 \r
@@ -1116,6 +1116,35 @@ class HookeFrame(wx.Frame):
 \r
         return dx, unitx, dy, unity\r
 \r
+    def _measure_N_points(self, N, message='', whatset=lh.RETRACTION):\r
+        '''\r
+        General helper function for N-points measurements\r
+        By default, measurements are done on the retraction\r
+        '''\r
+        if message != '':\r
+            dialog = wx.MessageDialog(None, message, 'Info', wx.OK)\r
+            dialog.ShowModal()\r
+\r
+        figure = self.GetActiveFigure()\r
+\r
+        xvector = self.displayed_plot.curves[whatset].x\r
+        yvector = self.displayed_plot.curves[whatset].y\r
+\r
+        clicked_points = figure.ginput(N, timeout=-1, show_clicks=True)\r
+\r
+        points = []\r
+        for clicked_point in clicked_points:\r
+            point = lh.ClickedPoint()\r
+            point.absolute_coords = clicked_point[0], clicked_point[1]\r
+            point.dest = 0\r
+            #TODO: make this optional?\r
+            #so far, the clicked point is taken, not the corresponding data point\r
+            point.find_graph_coords(xvector, yvector)\r
+            point.is_line_edge = True\r
+            point.is_marker = True\r
+            points.append(point)\r
+        return points\r
+\r
     def do_plotmanipulators(self):\r
         '''\r
         Please select the plotmanipulators you would like to use\r
@@ -1215,7 +1244,7 @@ class HookeFrame(wx.Frame):
                 axes_list[destination].set_xlabel(curve.units.x)\r
                 axes_list[destination].set_ylabel(curve.units.y)\r
                 if curve.style == 'plot':\r
-                    axes_list[destination].plot(curve.x, curve.y, color=curve.color, label=curve.label, zorder=1)\r
+                    axes_list[destination].plot(curve.x, curve.y, color=curve.color, label=curve.label, lw=curve.linewidth, zorder=1)\r
                 if curve.style == 'scatter':\r
                     axes_list[destination].scatter(curve.x, curve.y, color=curve.color, label=curve.label, s=curve.size, zorder=2)\r
 \r
@@ -1226,10 +1255,8 @@ class HookeFrame(wx.Frame):
             self.displayed_plot = copy.deepcopy(active_file.plot)\r
             #add raw curves to plot\r
             self.displayed_plot.raw_curves = copy.deepcopy(self.displayed_plot.curves)\r
-            #apply all active plotmanipulators and add the 'manipulated' data\r
-            for plotmanipulator in self.plotmanipulators:\r
-                if self.GetBoolFromConfig('core', 'plotmanipulators', plotmanipulator.name):\r
-                    self.displayed_plot = plotmanipulator.method(self.displayed_plot, active_file)\r
+            #apply all active plotmanipulators\r
+            self.displayed_plot = self.ApplyPlotmanipulators(self.displayed_plot, active_file)\r
             #add corrected curves to plot\r
             self.displayed_plot.corrected_curves = copy.deepcopy(self.displayed_plot.curves)\r
         else:\r
@@ -1256,17 +1283,14 @@ class HookeFrame(wx.Frame):
         figure.subplots_adjust(hspace=0.3)\r
 \r
         #TODO: add multiple results support to fit in curve.results:\r
-        #get the fit_function results to display\r
-        fit_function_str = self.GetStringFromConfig('results', 'show_results', 'fit_function')\r
+        #display results\r
         self.panelResults.ClearResults()\r
-        plot = self.GetActivePlot()\r
-        if plot is not None:\r
-            if plot.results.has_key(fit_function_str):\r
-                for curve in plot.results[fit_function_str].results:\r
-                    add_to_plot(curve)\r
-                self.panelResults.DisplayResults(plot.results[fit_function_str])\r
-            else:\r
-                self.panelResults.ClearResults()\r
+        if self.displayed_plot.results.has_key(self.results_str):\r
+            for curve in self.displayed_plot.results[self.results_str].results:\r
+                add_to_plot(curve)\r
+            self.panelResults.DisplayResults(self.displayed_plot.results[self.results_str])\r
+        else:\r
+            self.panelResults.ClearResults()\r
 \r
         figure.canvas.draw()\r
 \r
index 176d7bfdf267c0575eb710342f1a128fdacdda60..0d81a966daf68e2336db81fc14f92f6b2c2db9b4 100644 (file)
@@ -16,6 +16,7 @@ class Curve(object):
         self.color = 'blue'\r
         self.destination = Destination()\r
         self.label = ''\r
+        self.linewidth = 1\r
         self.size = 0.5\r
         self.style = 'plot'\r
         self.title = ''\r
index f69f2d20d25a2915458bfcd1035900164168fcc3..11d8565545f5b84cbc52d3efb43f54fcab9327e6 100644 (file)
@@ -74,9 +74,8 @@ class ClickedPoint(object):
 
         self.index=dists.index(min(dists))
         self.graph_coords=(xvector[self.index], yvector[self.index])
-#-----------------------------------------
-#CSV-HELPING FUNCTIONS
 
+#CSV-HELPING FUNCTIONS
 def transposed2(lists, defval=0):
     '''
     transposes a list of lists, i.e. from [[a,b,c],[x,y,z]] to [[a,x],[b,y],[c,z]] without losing
index c82e697dfe1a634606be6434029186f12434ffb9..92b9629b46b5aecf128de85a099300f956019e12 100644 (file)
@@ -24,7 +24,7 @@ class Playlist(object):
         self.figure = None\r
         self.files = []\r
         self.generics_dict = {}\r
-        self.hidden_attributes = ['curve', 'data', 'driver', 'fits', 'name', 'plots']\r
+        self.hidden_attributes = ['curve', 'data', 'driver', 'fits', 'name', 'plot', 'plots']\r
         self.index = -1\r
         self.name = None\r
         self.path = None\r
@@ -75,7 +75,7 @@ class Playlist(object):
 \r
     def load(self, filename):\r
         '''\r
-        loads a playlist file\r
+        Loads a playlist file\r
         '''\r
         self.filename = filename\r
         self.path, self.name = os.path.split(filename)\r
@@ -91,9 +91,9 @@ class Playlist(object):
             #rebuild a data structure from the xml attributes\r
             #the next two lines are here for backwards compatibility, newer playlist files use 'filename' instead of 'path'\r
             if element.hasAttribute('path'):\r
-                filename = lib.libhooke.get_file_path(element.getAttribute('path'))\r
+                filename = element.getAttribute('path')\r
             if element.hasAttribute('filename'):\r
-                filename = lib.libhooke.get_file_path(element.getAttribute('filename'))\r
+                filename = element.getAttribute('filename')\r
             if os.path.isfile(filename):\r
                 data_file = lib.file.File(filename)\r
                 self.files.append(data_file)\r
index a4641a6037cbc4d407cd1680c6d26a3953a025a3..24364cb7d4b22711cf03285a4a387d3f6a00a63c 100644 (file)
@@ -11,8 +11,19 @@ This program is released under the GNU General Public License version 2.
 '''\r
 \r
 class Plugin(object):\r
+    '''\r
+    Plugin is a class that is used to facilitate accessing\r
+    configuration parameters in a ConfigObj from different plugins.\r
+    '''\r
 \r
     def __init__(self):\r
-        self.key = ''\r
         self.name = ''\r
+        #if the calling plugin uses a prefix, this can be added to the name\r
+        #e.g. autopeak.ini: [[peak_color]]\r
+        #flatfilts.ini [[color]]\r
+        #are both used to set the color of the peak plot (scatter plot)\r
+        #in order to access 'peak_color' rather than 'color', the prefix needs to\r
+        #be set to 'peak_'\r
+        #if the names are identical, set prefix to ''\r
         self.prefix = ''\r
+        self.section = ''\r
index b346115a40d2efae330838ad387d99c9a77097f7..7297e66e4154fa4429e86ac9aed5482c8aeaf639 100644 (file)
@@ -19,22 +19,24 @@ import math
 from numpy import isnan\r
 \r
 def pretty_format(fValue, sUnit='', iDecimals=-1, iMultiplier=1, bLeadingSpaces=False):\r
-    if fValue != 0:\r
-        iLeadingSpaces = 0\r
-        if bLeadingSpaces:\r
-            iLeadingSpaces = 5\r
-        if iMultiplier == 1:\r
-            iMultiplier=get_multiplier(fValue)\r
-        sUnitString = ''\r
-        if sUnit != '':\r
-            sUnitString = ' ' + get_prefix(iMultiplier) + sUnit\r
-        if iDecimals >= 0:\r
-            formatString = '% ' + repr(iLeadingSpaces + iDecimals) + '.' + repr(iDecimals) + 'f'\r
-            return formatString % (fValue / iMultiplier) + sUnitString\r
-        else:\r
-            return str(fValue / iMultiplier) + sUnitString\r
-    else:\r
+    if fValue == 0:\r
         return '0'\r
+    if isnan(fValue):\r
+        return 'NaN'\r
+\r
+    iLeadingSpaces = 0\r
+    if bLeadingSpaces:\r
+        iLeadingSpaces = 5\r
+    if iMultiplier == 1:\r
+        iMultiplier=get_multiplier(fValue)\r
+    sUnitString = ''\r
+    if sUnit != '':\r
+        sUnitString = ' ' + get_prefix(iMultiplier) + sUnit\r
+    if iDecimals >= 0:\r
+        formatString = '% ' + repr(iLeadingSpaces + iDecimals) + '.' + repr(iDecimals) + 'f'\r
+        return formatString % (fValue / iMultiplier) + sUnitString\r
+    else:\r
+        return str(fValue / iMultiplier) + sUnitString\r
     return str(fValue / iMultiplier) + ' ' + get_prefix(fValue / iMultiplier) + sUnit\r
 \r
 def get_multiplier(fValue):\r
index 7535ac96b99596af00e4b84dcd19bd7442bf2a74..644fc85ea224acdc0ddafab5821ad09961b17152 100644 (file)
@@ -10,6 +10,8 @@ Copyright 2009 by Dr. Rolf Schmidt (Concordia University, Canada)
 This program is released under the GNU General Public License version 2.\r
 '''\r
 \r
+from numpy import nan\r
+\r
 import prettyformat\r
 import lib.curve\r
 \r
@@ -127,16 +129,18 @@ class Results(object):
 \r
     def set_multipliers(self, index=0):\r
         if self.has_results():\r
-            if index >= 0 and index < len(self.results):\r
-                for column in self.columns:\r
-                    #result will contain the results dictionary at 'index'\r
-                    result = self.results[index][0]\r
-                    #in position 0 of the result we find the value\r
-                    self.multipliers[column] = prettyformat.get_multiplier(result[column][0])\r
-                self.has_multipliers = True\r
+            for column in self.columns:\r
+                #result will contain the results dictionary at 'index'\r
+                result = self.results[index].result\r
+                #in position 0 of the result we find the value\r
+                self.multipliers[column] = prettyformat.get_multiplier(result[column])\r
+            self.has_multipliers = True\r
         else:\r
             self.has_multipliers = False\r
 \r
+    def update(self):\r
+        pass\r
+\r
 \r
 class ResultsFJC(Results):\r
     def __init__(self):\r
@@ -153,21 +157,42 @@ class ResultsFJC(Results):
 \r
     def set_multipliers(self, index=0):\r
         if self.has_results():\r
-            if index >= 0 and index < len(self.results):\r
-                for column in self.columns:\r
-                    #result will contain the results dictionary at 'index'\r
-                    result = self.results[index].result\r
-                    #in position 0 of the result we find the value\r
-                    if column == 'sigma contour length':\r
-                        self.multipliers[column] = self.multipliers['Contour length']\r
-                    elif column == 'sigma Kuhn length':\r
-                        self.multipliers[column] = self.multipliers['Kuhn length']\r
-                    else:\r
-                        self.multipliers[column] = prettyformat.get_multiplier(result[column])\r
-                self.has_multipliers = True\r
+            for column in self.columns:\r
+                #result will contain the results dictionary at 'index'\r
+                result = self.results[index].result\r
+                #in position 0 of the result we find the value\r
+                if column == 'sigma contour length':\r
+                    self.multipliers[column] = self.multipliers['Contour length']\r
+                elif column == 'sigma Kuhn length':\r
+                    self.multipliers[column] = self.multipliers['Kuhn length']\r
+                else:\r
+                    self.multipliers[column] = prettyformat.get_multiplier(result[column])\r
+            self.has_multipliers = True\r
         else:\r
             self.has_multipliers = False\r
 \r
+class ResultsMultiDistance(Results):\r
+    def __init__(self):\r
+        Results.__init__(self)\r
+        self.columns = ['Distance']\r
+        self.units['Distance'] = 'm'\r
+        self.set_decimals(2)\r
+\r
+    def update(self):\r
+        if (self.results) > 0:\r
+            for result in self.results:\r
+                if result.visible:\r
+                    reference_peak = result.x\r
+                    break\r
+\r
+            for result in self.results:\r
+                if result.visible:\r
+                    result.result['Distance'] = reference_peak - result.x\r
+                    reference_peak = result.x\r
+                else:\r
+                    result.result['Distance'] = nan\r
+\r
+\r
 class ResultsWLC(Results):\r
     def __init__(self):\r
         Results.__init__(self)\r
@@ -183,17 +208,16 @@ class ResultsWLC(Results):
 \r
     def set_multipliers(self, index=0):\r
         if self.has_results():\r
-            if index >= 0 and index < len(self.results):\r
-                for column in self.columns:\r
-                    #result will contain the results dictionary at 'index'\r
-                    result = self.results[index].result\r
-                    #in position 0 of the result we find the value\r
-                    if column == 'sigma contour length':\r
-                        self.multipliers[column] = self.multipliers['Contour length']\r
-                    elif column == 'sigma persistence length':\r
-                        self.multipliers[column] = self.multipliers['Persistence length']\r
-                    else:\r
-                        self.multipliers[column] = prettyformat.get_multiplier(result[column])\r
-                self.has_multipliers = True\r
+            for column in self.columns:\r
+                #result will contain the results dictionary at 'index'\r
+                result = self.results[index].result\r
+                #in position 0 of the result we find the value\r
+                if column == 'sigma contour length':\r
+                    self.multipliers[column] = self.multipliers['Contour length']\r
+                elif column == 'sigma persistence length':\r
+                    self.multipliers[column] = self.multipliers['Persistence length']\r
+                else:\r
+                    self.multipliers[column] = prettyformat.get_multiplier(result[column])\r
+            self.has_multipliers = True\r
         else:\r
             self.has_multipliers = False\r
index d2c5b23c99735706933fb005ed0d1396a3faf195..88fb6c0edee823885bbf4fecd1cc4cec9454d37e 100644 (file)
         type = enum\r
         value = contact point\r
     \r
+    [[color]]\r
+        default = black\r
+        type = color\r
+        value = "(255,0,128)"\r
+    \r
     [[fit_function]]\r
         default = wlc\r
         elements = wlc, fjc, fjcPEG\r
         type = boolean\r
         value = False\r
     \r
-    [[peak_color]]\r
-        default = black\r
-        type = color\r
-        value = "(255,128,0)"\r
-    \r
-    [[peak_show]]\r
-        default = False\r
-        type = boolean\r
-        value = False\r
-    \r
-    [[peak_size]]\r
-        default = 20\r
-        maximum = 10000\r
-        minimum = 1\r
-        type = integer\r
-        value = 50\r
-    \r
     [[persistence_length]]\r
         default = 0.35e-9\r
         minimum = 0\r
index 6e6d5a2aef06a48be7c640b850f34b9e63a47913..2951ca49de20a70c5f33a905c9afed261db0f164 100644 (file)
@@ -21,7 +21,6 @@ from numpy import mean, RankWarning
 import warnings
 warnings.simplefilter('ignore', RankWarning)
 
-#import config
 import lib.plugin
 import lib.results
 
@@ -69,49 +68,47 @@ 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.
-
-
-        Useful variables (to set with SET command):
-        ---
-        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/FJC (if usepoints false)
-        auto_fit_points = number of points to fit before the peak maximum, for WLC/FJC (if usepoints true)
-
-        baseline_clicks = contact point: no baseline, f=0 at the contact point (whether hand-picked or automatically found)
-                          automatic:     automatic baseline
-                          1 point:       decide baseline with a single click and length defined in auto_left_baseline
-                          2 points:      let user click points of baseline
-        auto_left_baseline = length in nm to use as baseline from the right point (if baseline_clicks = automatic , 1 point)
-        auto_right_baseline = distance in nm of peak-most baseline point from last peak (if baseline_clicks = automatic)
-
-        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)
+        Configuration
+        -------------
+        apply_plotmanipulators:
+            - all (all selected plotmanipulators will be applied)
+            - flatten (only the flatten plotmanipulator will be applied)
+            - none (no plotmanipulators will be applied)
+        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/FJC (if usepoints false)
+        auto_fit_points: number of points to fit before the peak maximum, for WLC/FJC (if usepoints true)
+
+        baseline_clicks:
+            contact point: no baseline, f=0 at the contact point (whether hand-picked or automatically found)
+            automatic:     automatic baseline
+            1 point:       decide baseline with a single click and length defined in auto_left_baseline
+            2 points:      let user click points of baseline
+        auto_left_baseline: length in nm to use as baseline from the right point (if baseline_clicks = automatic , 1 point)
+        auto_right_baseline: distance in nm of peak-most baseline point from last peak (if baseline_clicks = automatic)
+
+        auto_max_p: Maximum persistence length (if using WLC) or Kuhn length (if using FJC)
+                    outside of which the peak is automatically discarded (in nm)
+        auto_min_p: Minimum persistence length (if using WLC) or Kuhn length (if using FJC)
+                    outside of which the peak is automatically discarded (in nm)
         '''
 
-        #default fit etc. variables
+        #default variables
         auto_fit_nm = self.GetFloatFromConfig('autopeak', 'auto_fit_nm')
         auto_left_baseline = self.GetFloatFromConfig('autopeak', 'auto_left_baseline')
         auto_max_p = self.GetFloatFromConfig('autopeak', 'auto_max_p')
         auto_min_p = self.GetFloatFromConfig('autopeak', 'auto_min_p')
         auto_right_baseline = self.GetFloatFromConfig('autopeak', 'auto_right_baseline')
         baseline_clicks = self.GetStringFromConfig('autopeak', 'baseline_clicks')
+        color = self.GetColorFromConfig('autopeak', 'color')
         fit_function = self.GetStringFromConfig('autopeak', 'fit_function')
         fit_points = self.GetIntFromConfig('autopeak', 'auto_fit_points')
         noauto = self.GetBoolFromConfig('autopeak', 'noauto')
-        #noflatten: if true we do not flatten the curve
-        noflatten = self.GetBoolFromConfig('autopeak', 'noflatten')
-        peak_show = self.GetBoolFromConfig('autopeak', 'peak_show')
         persistence_length = self.GetFloatFromConfig('autopeak', 'persistence_length')
         #rebase: redefine the baseline
         rebase = self.GetBoolFromConfig('autopeak', 'rebase')
@@ -154,24 +151,19 @@ class autopeakCommands:
         forces = []
         slopes = []
 
-        #pick up plot
+        #pick up plot and filename
         if plot is None:
-            plot = copy.deepcopy(self.GetActivePlot())
+            plot = self.GetDisplayedPlotCorrected()
         filename = self.GetActiveFile().name
 
-        #apply all active plotmanipulators and add the 'manipulated' data
-        for plotmanipulator in self.plotmanipulators:
-            if self.GetBoolFromConfig('core', 'plotmanipulators', plotmanipulator.name):
-                if plotmanipulator.name == 'flatten':
-                    if not noflatten:
-                        plot = plotmanipulator.method(plot, self.GetActiveFile())
-                else:
-                    plot = plotmanipulator.method(plot, self.GetActiveFile())
-
+        TODO: add convfilt option?
         #--Using points instead of nm interval
         if not usepoints:
             fit_points = None
 
+        extension = plot.curves[lh.EXTENSION]
+        retraction = plot.curves[lh.RETRACTION]
+
         #--Contact point arguments
         if reclick:
             contact_point, contact_point_index = self.pickup_contact_point(filename=filename)
@@ -184,10 +176,10 @@ class autopeakCommands:
         else:
             #Automatically find contact point
             cindex = self.find_contact_point(plot)
-            contact_point = self._clickize(plot.curves[lh.RETRACTION].x, plot.curves[lh.EXTENSION].y, cindex)
+            contact_point = self._clickize(retraction.x, extension.y, cindex)
 
         #peak_size comes from convolution curve
-        peak_location, peak_size = self.find_current_peaks(plot=plot, noflatten=noflatten)
+        peak_location, peak_size = self.has_peaks(plot)
 
         if len(peak_location) == 0:
             self.AppendToOutput('No peaks to fit.')
@@ -196,39 +188,37 @@ class autopeakCommands:
         #Pick up force baseline
         if baseline_clicks == 'contact point':
             try:
-                avg = plot.curves[lh.RETRACTION].y[contact_point_index]
+                avg = retraction.y[contact_point_index]
             except:
-                avg = plot.curves[lh.RETRACTION].y[cindex]
+                avg = retraction.y[cindex]
 
         if rebase or (self.basecurrent != filename) or self.basepoints is None:
             if baseline_clicks == 'automatic':
                 self.basepoints = []
-                base_index_0 = peak_location[-1] + self.fit_interval_nm(peak_location[-1], plot.curves[lh.RETRACTION].x, auto_right_baseline, False)
-                self.basepoints.append(self._clickize(plot.curves[lh.RETRACTION].x, plot.curves[lh.RETRACTION].y, base_index_0))
-                base_index_1 = self.basepoints[0].index + self.fit_interval_nm(self.basepoints[0].index, plot.curves[lh.RETRACTION].x, auto_left_baseline, False)
-                self.basepoints.append(self._clickize(plot.curves[lh.RETRACTION].x, plot.curves[lh.RETRACTION].y, base_index_1))
+                base_index_0 = peak_location[-1] + self.fit_interval_nm(peak_location[-1], retraction.x, auto_right_baseline, False)
+                self.basepoints.append(self._clickize(retraction.x, retraction.y, base_index_0))
+                base_index_1 = self.basepoints[0].index + self.fit_interval_nm(self.basepoints[0].index, retraction.x, auto_left_baseline, False)
+                self.basepoints.append(self._clickize(retraction.x, retraction.y, base_index_1))
             if baseline_clicks == '1 point':
                 self.basepoints=self._measure_N_points(N=1, message='Click on 1 point to select the baseline.', whatset=whatset)
-                base_index_1 = self.basepoints[0].index + self.fit_interval_nm(self.basepoints[0].index, plot.curves[lh.RETRACTION].x, auto_left_baseline, False)
-                self.basepoints.append(self._clickize(plot.curves[lh.RETRACTION].x, plot.curves[lh.RETRACTION].y, base_index_1))
+                base_index_1 = self.basepoints[0].index + self.fit_interval_nm(self.basepoints[0].index, retraction.x, auto_left_baseline, False)
+                self.basepoints.append(self._clickize(retraction.x, retraction.y, base_index_1))
             if baseline_clicks == '2 points':
                 self.basepoints=self._measure_N_points(N=2, message='Click on 2 points to select the baseline.', whatset=whatset)
         if baseline_clicks != 'contact point':
             boundaries=[self.basepoints[0].index, self.basepoints[1].index]
             boundaries.sort()
-            to_average = plot.curves[lh.RETRACTION].y[boundaries[0]:boundaries[1]] #y points to average
+            to_average = retraction.y[boundaries[0]:boundaries[1]] #y points to average
             avg = mean(to_average)
             self.basecurrent = filename
 
-        x_values = plot.curves[lh.RETRACTION].x
-        y_values = plot.curves[lh.RETRACTION].y
         for index, peak in enumerate(peak_location):
             #WLC FITTING
             #define fit interval
             if not usepoints:
-                fit_points = self.fit_interval_nm(peak, plot.curves[lh.RETRACTION].x, auto_fit_nm, True)
-            peak_point = self._clickize(x_values, y_values, peak)
-            other_fit_point=self._clickize(x_values, y_values, peak - fit_points)
+                fit_points = self.fit_interval_nm(peak, retraction.x, auto_fit_nm, True)
+            peak_point = self._clickize(retraction.x, retraction.y, peak)
+            other_fit_point=self._clickize(retraction.x, retraction.y, peak - fit_points)
 
             #points for the fit
             points = [contact_point, peak_point, other_fit_point]
@@ -237,18 +227,20 @@ class autopeakCommands:
                 continue
 
             if fit_function == 'wlc':
-                params, yfit, xfit, fit_errors = self.wlc_fit(points, x_values, y_values, pl_value, T, return_errors=True)
+                params, yfit, xfit, fit_errors = self.wlc_fit(points, retraction.x, retraction.y, pl_value, T, return_errors=True)
             elif fit_function == 'fjc':
-                params, yfit, xfit, fit_errors = self.fjc_fit(points, x_values, y_values, pl_value, T, return_errors=True)
+                params, yfit, xfit, fit_errors = self.fjc_fit(points, retraction.x, retraction.y, pl_value, T, return_errors=True)
             elif fit_function == 'fjcPEG':
-                params, yfit, xfit, fit_errors = self.fjcPEG_fit(points, x_values, y_values, pl_value, T, return_errors=True)
+                params, yfit, xfit, fit_errors = self.fjcPEG_fit(points, retraction.x, retraction.y, pl_value, T, return_errors=True)
+
+            self.results_str = fit_function
 
             #Measure forces
-            delta_to_measure = y_values[peak - delta_force:peak + delta_force]
+            delta_to_measure = retraction.y[peak - delta_force:peak + delta_force]
             y = min(delta_to_measure)
             #save force values (pN)
             #Measure slopes
-            slope = self.linefit_between(peak - slope_span, peak, whatset=lh.RETRACTION)[0]
+            slope = self.linefit_between(peak - slope_span, peak, whatset=whatset)[0]
 
             #check fitted data and, if right, add peak to the measurement
             fit_result = lib.results.Result()
@@ -289,10 +281,11 @@ class autopeakCommands:
                     fit_result.result = {}
 
             if len(fit_result.result) > 0:
+                fit_result.color = color
                 fit_result.label = fit_function + '_' + str(index)
-                fit_result.title = plot.curves[lh.RETRACTION].title
-                fit_result.units.x = plot.curves[lh.RETRACTION].units.x
-                fit_result.units.y = plot.curves[lh.RETRACTION].units.y
+                fit_result.title = retraction.title
+                fit_result.units.x = retraction.units.x
+                fit_result.units.y = retraction.units.y
                 fit_result.visible = True
                 fit_result.x = xfit
                 fit_result.y = yfit
@@ -302,57 +295,9 @@ class autopeakCommands:
             fit_results.set_multipliers(0)
             plot = self.GetActivePlot()
             plot.results[fit_function] = fit_results
-            if peak_show:
-                plugin = lib.plugin.Plugin()
-                plugin.name = 'autopeak'
-                plugin.section = 'autopeak'
-                plugin.prefix = 'peak_'
-                self.do_peaks(plugin=plugin, peak_location=peak_location, peak_size=peak_size)
-            else:
-                self.UpdatePlot()
-
+            self.UpdatePlot()
         else:
             self.AppendToOutput('No peaks found.')
 
         #TODO:
         #self.do_note('autopeak')
-
-    def find_current_peaks(self, plot=None, noflatten=True):
-        if not noflatten:
-            plot_temp = self.plotmanip_flatten(plot, self.GetActiveFile(), customvalue=1)
-        peak_location, peak_size = self.has_peaks(plot_temp)
-        return peak_location, peak_size
-
-    def fit_interval_nm(self, start_index, x_vect, nm, backwards):
-        '''
-        Calculates the number of points to fit, given a fit interval in nm
-        start_index: index of point
-        plot: plot to use
-        backwards: if true, finds a point backwards.
-        '''
-
-        c = 0
-        i = start_index
-        maxlen=len(x_vect)
-        while abs(x_vect[i] - x_vect[start_index]) * (10**9) < nm:
-            if i == 0 or i == maxlen-1: #we reached boundaries of vector!
-                return c
-            if backwards:
-                i -= 1
-            else:
-                i += 1
-            c += 1
-        return c
-
-    def pickup_contact_point(self, filename=''):
-        '''
-        macro to pick up the contact point by clicking
-        '''
-        contact_point = self._measure_N_points(N=1, message='Please click on the contact point.')[0]
-        contact_point_index = contact_point.index
-        self.wlccontact_point = contact_point
-        self.wlccontact_index = contact_point.index
-        self.wlccurrent = filename
-        return contact_point, contact_point_index
-
-
index da8db6806a19aa4a9d8dbdb05d6b05c8c5bda8a2..a46f0bb8c2bd3fa1636ac2dd40e222f40aeba73d 100644 (file)
         value = _\r
 \r
 [results]\r
+    [[append]]\r
+        default = True\r
+        type = boolean\r
+        value = True\r
+    \r
     [[filename]]\r
         default = fit export.txt\r
         type = filename\r
@@ -56,5 +61,3 @@
         default = ","\r
         type = string\r
         value = ", "\r
-\r
-        \r
index a111c0d8bc46f3eef39c1c6069502bcc8a796b12..171f9430dd500beede280e6b18fc7b0f1c8b0def 100644 (file)
@@ -27,14 +27,9 @@ class exportCommands(object):
     def _plug_init(self):
         pass
 
-    def do_fits(self):#, ext='', folder='', prefix='', separator=''):
+    def do_fits(self):
         '''
-        Exports all approach and retraction files in a playlist and
-        all fitting results (if available) in a columnar ASCII format.
-        Please make sure that the number of points in the fit is smaller
-        or equal to the number of points in the approach/retraction.
-        For the time being, exports only one set of results (e.g. WLC
-        or FJC, not both).
+        Exports all fitting results (if available) in a columnar ASCII format.
         '''
 
         ext = self.GetStringFromConfig('export', 'fits', 'ext')
@@ -47,7 +42,6 @@ class exportCommands(object):
         active_file = self.GetActiveFile()
         plot = self.GetDisplayedPlot()
 
-        #TODO: fix for multiple results
         #add empty columns before adding new results if necessary
         if plot is not None:
             for results_str, results in plot.results.items():
@@ -88,18 +82,22 @@ class exportCommands(object):
         #add string for Other
 
         active_file = self.GetActiveFile()
-        plot = self.GetActivePlot()
-        extension = plot.curves[lh.EXTENSION]
-        retraction = plot.curves[lh.RETRACTION]
+        #create the header from the raw plot (i.e. only the force curve)
+        plot = self.GetDisplayedPlotRaw()
 
         output = []
         header_str = ''
         for index, curve in enumerate(plot.curves):
+            #TODO: only add labels for original curves (i.e. excluding anything added after the fact)
             header_str += curve.label + '_x (' + curve.units.x + ')' + separator + curve.label + '_y (' + curve.units.y + ')'
             if index < len(plot.curves) - 1:
                 header_str += separator
         output.append(header_str)
-        #TODO: add units
+
+        #export the displayed plot
+        plot = self.GetDisplayedPlot()
+        extension = plot.curves[lh.EXTENSION]
+        retraction = plot.curves[lh.RETRACTION]
         for index, row in enumerate(extension.x):
             output.append(separator.join([str(extension.x[index]), str(extension.y[index]), str(retraction.x[index]), str(retraction.y[index])]))
 
@@ -171,11 +169,15 @@ class exportCommands(object):
                 output_file.close
         progress_dialog.Destroy()
 
-    def do_results(self, filename='', separator=''):
+    def do_results(self, append=None, filename='', separator=''):
         '''
-        EXPORTFITS
         Exports all visible fit results in a playlist into a delimited text file
+        append: set append to True if you want to append to an existing results file
+        filename: the filename and path of the results file
+        separator: the separator between columns
         '''
+        if not append:
+            append = self.GetStringFromConfig('export', 'results', 'append')
         if filename == '':
             filename = self.GetStringFromConfig('export', 'results', 'filename')
         if separator == '':
@@ -203,7 +205,11 @@ class exportCommands(object):
                             output_str = ''.join([output_str, line_str, '\n'])
         if output_str != '':
             output_str = ''.join(['Analysis started ', time.asctime(), '\n', output_str])
-            output_file = open(filename, 'w')
+
+            if append and os.path.isfile(filename):
+               output_file = open(filename,'a')
+           else:
+               output_file = open(filename, 'w')
             output_file.write(output_str)
             output_file.close
         else:
index 3a6f604e93f7d0e681f12dbab643b9cdd62581f9..3a0168b9b123bfb79faf2b5dd48cb923512d840c 100644 (file)
@@ -1,4 +1,10 @@
 [convfilt]\r
+    [[apply_plotmanipulators]]\r
+        default = all\r
+        elements = all, flatten, none\r
+        type = enum\r
+        value = all\r
+    \r
     [[blindwindow]]\r
         default = 20\r
         maximum = 10000\r
@@ -86,7 +92,7 @@
     [[color]]\r
         default = black\r
         type = color\r
-        value = "(255,0,128)"\r
+        value = "(128,128,128)"\r
     \r
     [[size]]\r
         default = 20\r
index 9ce8a935ea65f94e8a3ab08d82f26f8a23995e73..d1814e1261df57a70a7fead22a37117715af1120 100644 (file)
@@ -129,35 +129,46 @@ class flatfiltsCommands:
     #-----Convolution-based peak recognition and filtering.
     #Requires the peakspot.py library
 
-    def has_peaks(self, plot=None):
+    def has_peaks(self, plot=None, plugin=None):
         '''
         Finds peak position in a force curve.
         FIXME: should be moved to peakspot.py
+        #TODO: should this really be moved? this is obviously tied into flatfilts/convfilt
+        #flatfilts.py is where 'has_peaks' belongs
         '''
 
-        blindwindow = self.GetFloatFromConfig('flatfilts', 'convfilt', 'blindwindow')
-        #need to convert the string that contains the list into a list
-        convolution = eval(self.GetStringFromConfig('flatfilts', 'convfilt', 'convolution'))
-        maxcut = self.GetFloatFromConfig('flatfilts', 'convfilt', 'maxcut')
-        mindeviation = self.GetFloatFromConfig('flatfilts', 'convfilt', 'mindeviation')
-        positive = self.GetBoolFromConfig('flatfilts', 'convfilt', 'positive')
-        seedouble = self.GetIntFromConfig('flatfilts', 'convfilt', 'seedouble')
-        stable = self.GetFloatFromConfig('flatfilts', 'convfilt', 'stable')
+        if plugin is None:
+            blindwindow = self.GetFloatFromConfig('flatfilts', 'convfilt', 'blindwindow')
+            #need to convert the string that contains the list into a list
+            convolution = eval(self.GetStringFromConfig('flatfilts', 'convfilt', 'convolution'))
+            maxcut = self.GetFloatFromConfig('flatfilts', 'convfilt', 'maxcut')
+            mindeviation = self.GetFloatFromConfig('flatfilts', 'convfilt', 'mindeviation')
+            positive = self.GetBoolFromConfig('flatfilts', 'convfilt', 'positive')
+            seedouble = self.GetIntFromConfig('flatfilts', 'convfilt', 'seedouble')
+            stable = self.GetFloatFromConfig('flatfilts', 'convfilt', 'stable')
+        else:
+            blindwindow = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'blindwindow')
+            #need to convert the string that contains the list into a list
+            convolution = eval(self.GetStringFromConfig(plugin.name, plugin.section, plugin.prefix + 'convolution'))
+            maxcut = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'maxcut')
+            mindeviation = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'mindeviation')
+            positive = self.GetBoolFromConfig(plugin.name, plugin.section, plugin.prefix + 'positive')
+            seedouble = self.GetIntFromConfig(plugin.name, plugin.section, plugin.prefix + 'seedouble')
+            stable = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'stable')
 
         if plot is None:
-            plot = self.GetActivePlot()
+            plot = self.GetDisplayedPlotCorrected()
 
-        xret = plot.curves[lh.RETRACTION].x
-        yret = plot.curves[lh.RETRACTION].y
+        retraction = plot.curves[lh.RETRACTION]
         #Calculate convolution
-        convoluted = lps.conv_dx(yret, convolution)
+        convoluted = lps.conv_dx(retraction.y, convolution)
 
         #surely cut everything before the contact point
         cut_index = self.find_contact_point(plot)
         #cut even more, before the blind window
-        start_x = xret[cut_index]
+        start_x = retraction.x[cut_index]
         blind_index = 0
-        for value in xret[cut_index:]:
+        for value in retraction.x[cut_index:]:
             if abs((value) - (start_x)) > blindwindow * (10 ** -9):
                 break
             blind_index += 1
@@ -169,32 +180,15 @@ class flatfiltsCommands:
         #take the maximum
         for i in range(len(peak_location)):
             peak = peak_location[i]
-            maxpk = min(yret[peak - 10:peak + 10])
-            index_maxpk = yret[peak - 10:peak + 10].index(maxpk) + (peak - 10)
+            maxpk = min(retraction.y[peak - 10:peak + 10])
+            index_maxpk = retraction.y[peak - 10:peak + 10].index(maxpk) + (peak - 10)
             peak_location[i] = index_maxpk
 
         return peak_location, peak_size
 
-    def exec_has_peaks(self, item):
-        '''
-        encapsulates has_peaks for the purpose of correctly treating the curve objects in the convfilt loop,
-        to avoid memory leaks
-        '''
-        #TODO: things have changed, check for the memory leak again
-
-        if self.HasPlotmanipulator('plotmanip_flatten'):
-            #If flatten is present, use it for better recognition of peaks...
-            flat_plot = self.plotmanip_flatten(item.plot, item, customvalue=1)
-
-        peak_location, peak_size = self.has_peaks(flat_plot)
-
-        return peak_location, peak_size
-
     def do_peaks(self, plugin=None, peak_location=None, peak_size=None):
         '''
-        PEAKS
-        (flatfilts.py)
-        Test command for convolution filter / test.
+        Test command for convolution filter.
         ----
         Syntax: peaks [deviations]
         absolute deviation = number of times the convolution signal is above the noise absolute deviation.
@@ -222,17 +216,15 @@ class flatfiltsCommands:
             self.AppendToOutput('Found ' + str(len(peak_location)) + peak_str)
 
         if peak_location:
-            xplotted_ret = plot.curves[lh.RETRACTION].x
-            yplotted_ret = plot.curves[lh.RETRACTION].y
-            xgood = [xplotted_ret[index] for index in peak_location]
-            ygood = [yplotted_ret[index] for index in peak_location]
+            retraction = plot.curves[lh.RETRACTION]
 
             peaks = lib.curve.Curve()
             peaks.color = color
             peaks.size = size
             peaks.style = 'scatter'
-            peaks.x = xgood
-            peaks.y = ygood
+            peaks.title = 'Peaks'
+            peaks.x = [retraction.x[index] for index in peak_location]
+            peaks.y = [retraction.y[index] for index in peak_location]
 
             plot.curves.append(peaks)
 
@@ -240,26 +232,17 @@ class flatfiltsCommands:
 
     def do_convfilt(self):
         '''
-        CONVFILT
-        (flatfilts.py)
         Filters out flat (featureless) files of the current playlist,
         creating a playlist containing only the files with potential
         features.
         ------------
-        Syntax:
-        convfilt [min_npks min_deviation]
-
-        min_npks = minmum number of peaks
-        (to set the default, see convfilt.conf file; CONVCONF and SETCONF commands)
-
-        min_deviation = minimum signal/noise ratio *in the convolution*
-        (to set the default, see convfilt.conf file; CONVCONF and SETCONF commands)
-
-        If called without arguments, it uses default values.
+        min_npks: minmum number of peaks
+        min_deviation: minimum signal/noise ratio *in the convolution*
         '''
 
         self.AppendToOutput('Processing playlist...')
         self.AppendToOutput('(Please wait)')
+        apply_plotmanipulators = self.GetStringFromConfig('flatfilts', 'convfilt', 'apply_plotmanipulators')
         minpeaks = self.GetIntFromConfig('flatfilts', 'convfilt', 'minpeaks')
         features = []
         playlist = self.GetActivePlaylist()
@@ -271,7 +254,8 @@ class flatfiltsCommands:
             file_index += 1
             try:
                 current_file.identify(self.drivers)
-                peak_location, peak_size = self.exec_has_peaks(copy.deepcopy(current_file))
+                plot = self.ApplyPlotmanipulators(current_file.plot, current_file)
+                peak_location, peak_size = self.has_peaks(plot)
                 number_of_peaks = len(peak_location)
                 if number_of_peaks != 1:
                     if number_of_peaks > 0:
@@ -293,10 +277,7 @@ class flatfiltsCommands:
                 current_file.peak_size = peak_size
                 features.append(file_index - 1)
 
-        #Warn that no flattening had been done.
-        if not self.HasPlotmanipulator('plotmanip_flatten'):
-            self.AppendToOutput('Flatten manipulator was not found. Processing was done without flattening.')
-            self.AppendToOutput('Try to enable it in the configuration file for better results.')
+        #TODO: warn when flatten is not applied?
         if not features:
             self.AppendToOutput('Found nothing interesting. Check the playlist, could be a bug or criteria could be too stringent.')
         else:
index 3d930e9e60a73039bd33adb3c06fe4ab97f2bfbb..5968d03d36b20efb1bf076cdb3899dda3cb2711b 100644 (file)
@@ -1,9 +1,21 @@
 [distance]\r
-    [[show_points]]\r
+    [[color]]\r
+        default = black\r
+        type = color\r
+        value = "(128,0,128)"\r
+    \r
+    [[show]]\r
         default = True\r
         type = boolean\r
         value = True\r
     \r
+    [[size]]\r
+        default = 20\r
+        maximum = 10000\r
+        minimum = 1\r
+        type = integer\r
+        value = 100\r
+    \r
     [[whatset]]\r
         default = retraction\r
         elements = extension, retraction\r
         value = retraction\r
 \r
 [force]\r
+    [[color]]\r
+        default = black\r
+        type = color\r
+        value = "(0,255,0)"\r
+    \r
+    [[show]]\r
+        default = True\r
+        type = boolean\r
+        value = False\r
+    \r
+    [[size]]\r
+        default = 20\r
+        maximum = 10000\r
+        minimum = 1\r
+        type = integer\r
+        value = 100\r
+    \r
     [[whatset]]\r
         default = retraction\r
         elements = extension, retraction\r
         value = retraction\r
 \r
 [forcebase]\r
+    [[baseline]]\r
+        type = none\r
+        value = 1\r
+    \r
+    [[color]]\r
+        default = black\r
+        type = color\r
+        value = "(255,0,128)"\r
+    \r
     [[max]]\r
         default = False\r
         type = boolean\r
         type = boolean\r
         value = False\r
     \r
+    [[show]]\r
+        default = True\r
+        type = boolean\r
+        value = True\r
+    \r
+    [[size]]\r
+        default = 20\r
+        maximum = 10000\r
+        minimum = 1\r
+        type = integer\r
+        value = 50\r
+    \r
     [[whatset]]\r
         default = retraction\r
         elements = extension, retraction\r
         type = enum\r
         value = retraction\r
-    \r
-    [[baseline]]\r
-        type = none\r
-        value = 1\r
 \r
 [generalvclamp]\r
     [[flatten]]\r
         minimum = 0\r
         type = integer\r
         value = 60\r
+    \r
+    [[point_color]]\r
+        default = black\r
+        type = color\r
+        value = "(0,255,0)"\r
+    \r
+    [[point_show]]\r
+        default = False\r
+        type = boolean\r
+        value = False\r
+    \r
+    [[point_size]]\r
+        default = 20\r
+        maximum = 10000\r
+        minimum = 1\r
+        type = integer\r
+        value = 10\r
+    \r
+    [[slope_color]]\r
+        default = black\r
+        type = color\r
+        value = "(255,0,128)"\r
+    \r
+    [[slope_linewidth]]\r
+        default = 1\r
+        maximum = 10000\r
+        minimum = 1\r
+        type = integer\r
+        value = 2\r
+    \r
+    [[slope_show]]\r
+        default = True\r
+        type = boolean\r
+        value = True\r
+    \r
+    [[whatset]]\r
+        default = retraction\r
+        elements = extension, retraction\r
+        type = enum\r
+        value = retraction\r
index 9f9713601ac68e73cc69cb953040334c3553df58..942588016906c58e902eb524460ca41288623a9c 100644 (file)
@@ -15,6 +15,7 @@ import lib.libhooke as lh
 import wxversion
 wxversion.select(lh.WX_GOOD)
 
+from copy import deepcopy
 import numpy as np
 import scipy as sp
 
@@ -42,20 +43,15 @@ class generalvclampCommands:
         -----------------
         Syntax: distance
         '''
-        show_points = self.GetBoolFromConfig('generalvclamp', 'distance', 'show_points')
-        whatset_str = self.GetStringFromConfig('generalvclamp', 'distance', 'whatset')
-        whatset = 'retraction'
-        if whatset_str == 'extension':
-            whatset = lh.EXTENSION
-        if whatset_str == 'retraction':
-            whatset = lh.RETRACTION
-
         active_file = self.GetActiveFile()
         plot = self.GetActivePlot()
         if active_file.driver.experiment == 'clamp':
             self.AppendToOutput('You wanted to use zpiezo perhaps?')
             return
-        dx, unitx, dy, unity = self._delta(message='Click 2 points to measure the distance.', show=show_points, whatset=whatset)
+        plugin = lib.plugin.Plugin()
+        plugin.name = 'generalvclamp'
+        plugin.section = 'distance'
+        dx, unitx, dy, unity = self._delta(message='Click 2 points to measure the distance.', plugin=plugin)
         #TODO: pretty format
         self.AppendToOutput(str(dx * (10 ** 9)) + ' nm')
 
@@ -67,19 +63,15 @@ class generalvclampCommands:
         ---------------
         Syntax: force
         '''
-        whatset_str = self.GetStringFromConfig('generalvclamp', 'force', 'whatset')
-        whatset = 'retraction'
-        if whatset_str == 'extension':
-            whatset = lh.EXTENSION
-        if whatset_str == 'retraction':
-            whatset = lh.RETRACTION
-
         active_file = self.GetActiveFile()
         plot = self.GetActivePlot()
         if active_file.driver.experiment == 'clamp':
             self.AppendToOutput('This command makes no sense for a force clamp experiment.')
             return
-        dx, unitx, dy, unity = self._delta(whatset=whatset, message='Click 2 points to measure the force.')
+        plugin = lib.plugin.Plugin()
+        plugin.name = 'generalvclamp'
+        plugin.section = 'force'
+        dx, unitx, dy, unity = self._delta(message='Click 2 points to measure the force.', plugin=plugin)
         #TODO: pretty format
         self.AppendToOutput(str(dy * (10 ** 12)) + ' pN')
 
@@ -98,33 +90,48 @@ class generalvclampCommands:
                 max: Instead of asking for a point to measure, asks for two points and use
                      the maximum peak in between
         '''
+        color =  self.GetColorFromConfig('generalvclamp', 'forcebase', 'color')
         maxpoint = self.GetBoolFromConfig('generalvclamp', 'forcebase', 'max')
         rebase = self.GetBoolFromConfig('generalvclamp', 'forcebase', 'rebase')
+        show_points = self.GetBoolFromConfig('generalvclamp', 'forcebase', 'show_points')
+        size = self.GetIntFromConfig('generalvclamp', 'forcebase', 'size')
         whatset_str = self.GetStringFromConfig('generalvclamp', 'forcebase', 'whatset')
         whatset = 'retraction'
         if whatset_str == 'extension':
             whatset = lh.EXTENSION
         if whatset_str == 'retraction':
             whatset = lh.RETRACTION
+
         plot = self.GetDisplayedPlotCorrected()
 
+        clicked_points = []
+
         filename = self.GetActiveFile().name
         if rebase or (self.basecurrent != filename):
             self.basepoints = self._measure_N_points(N=2, message='Click on 2 points to select the baseline.', whatset=whatset)
             self.basecurrent = filename
+            clicked_points = self.basepoints
 
+        #TODO: maxpoint does not seem to be picking up the 'real' minimum (at least not with test.hkp/default.000)
         if maxpoint:
             boundpoints = []
             points = self._measure_N_points(N=2, message='Click 2 points to select the range for maximum detection.', whatset=whatset)
             boundpoints = [points[0].index, points[1].index]
             boundpoints.sort()
+            clicked_points += points
             try:
-                y = min(plot.curves[whatset].y[boundpoints[0]:boundpoints[1]])
+                vector_x = plot.curves[whatset].x[boundpoints[0]:boundpoints[1]]
+                vector_y = plot.curves[whatset].y[boundpoints[0]:boundpoints[1]]
+                y = min(vector_y)
+                index = vector_y.index(y)
+                clicked_points += [self._clickize(vector_x, vector_y, index)]
             except ValueError:
                 self.AppendToOutput('Chosen interval not valid. Try picking it again. Did you pick the same point as begin and end of the interval?')
+                return
         else:
             points = self._measure_N_points(N=1, message='Click on the point to measure.', whatset=whatset)
             y = points[0].graph_coords[1]
+            clicked_points += [points[0]]
 
         boundaries = [self.basepoints[0].index, self.basepoints[1].index]
         boundaries.sort()
@@ -132,12 +139,26 @@ class generalvclampCommands:
 
         avg = np.mean(to_average)
         forcebase = abs(y - avg)
+
+        if show_points:
+            curve = plot.curves[whatset]
+            for point in clicked_points:
+                points = deepcopy(curve)
+                points.x = point.graph_coords[0]
+                points.y = point.graph_coords[1]
+
+                points.color = color
+                points.size = size
+                points.style = 'scatter'
+                plot.curves.append(points)
+
+        self.UpdatePlot(plot)
         #TODO: pretty format
         self.AppendToOutput(str(forcebase * (10 ** 12)) + ' pN')
-\r
+
     def plotmanip_multiplier(self, plot, current, customvalue=False):
         '''
-        Multiplies all the Y values of an SMFS curve by a value stored in the 'force_multiplier'\r
+        Multiplies all the Y values of an SMFS curve by a value stored in the 'force_multiplier'
         configuration variable. Useful for calibrations and other stuff.
         '''
 
@@ -147,12 +168,12 @@ class generalvclampCommands:
 
         force_multiplier = self.GetFloatFromConfig('generalvclamp', 'force_multiplier')
         if force_multiplier == 1:
-            return plot\r
+            return plot
 
         plot.curves[lh.EXTENSION].y = [element * force_multiplier for element in plot.curves[lh.EXTENSION].y]
         plot.curves[lh.RETRACTION].y = [element * force_multiplier for element in plot.curves[lh.RETRACTION].y]
-\r
-        return plot\r
+
+        return plot
 
     def plotmanip_flatten(self, plot, current, customvalue=0):
         '''
@@ -237,24 +258,36 @@ class generalvclampCommands:
         '''
 
         fitspan = self.GetIntFromConfig('generalvclamp', 'slope', 'fitspan')
+        point_color = self.GetColorFromConfig('generalvclamp', 'slope', 'point_color')
+        point_show = self.GetBoolFromConfig('generalvclamp', 'slope', 'point_show')
+        point_size = self.GetIntFromConfig('generalvclamp', 'slope', 'point_size')
+        slope_color = self.GetColorFromConfig('generalvclamp', 'slope', 'slope_color')
+        slope_linewidth = self.GetIntFromConfig('generalvclamp', 'slope', 'slope_linewidth')
+        slope_show = self.GetBoolFromConfig('generalvclamp', 'slope', 'slope_show')
+        whatset_str = self.GetStringFromConfig('generalvclamp', 'forcebase', 'whatset')
+        whatset = 'retraction'
+        if whatset_str == 'extension':
+            whatset = lh.EXTENSION
+        if whatset_str == 'retraction':
+            whatset = lh.RETRACTION
+
         # Decides between the two forms of user input
         #TODO: add an option 'mode' with options 'chunk' and 'point'
-        #TODO: add 'whatset' as option, too
         if fitspan == 0:
             # Gets the Xs of two clicked points as indexes on the curve curve vector
             clickedpoints = []
-            points = self._measure_N_points(N=2, message='Click 2 points to select the chunk.', whatset=1)
+            points = self._measure_N_points(N=2, message='Click 2 points to select the chunk.', whatset=whatset)
             clickedpoints = [points[0].index, points[1].index]
             clickedpoints.sort()
         else:
             clickedpoints = []
-            points = self._measure_N_points(N=1, message='Click on the leftmost point of the chunk (i.e.usually the peak).', whatset=1)
+            points = self._measure_N_points(N=1, message='Click on the leftmost point of the chunk (i.e.usually the peak).', whatset=whatset)
             clickedpoints = [points[0].index - fitspan, points[0].index]
 
         # Calls the function linefit_between
         parameters = [0, 0, [], []]
         try:
-            parameters = self.linefit_between(clickedpoints[0], clickedpoints[1])
+            parameters = self.linefit_between(clickedpoints[0], clickedpoints[1], whatset=whatset)
         except:
             self.AppendToOutput('Cannot fit. Did you click the same point twice?')
             return
@@ -279,25 +312,27 @@ class generalvclampCommands:
             clickvector_x.append(item.graph_coords[0])
             clickvector_y.append(item.graph_coords[1])
 
-        #add the slope to the plot
-        slope = lib.curve.Curve()
-        slope.color = 'red'
-        slope.label = 'slope'
-        slope.style = 'plot'
-        slope.x = xtoplot
-        slope.y = ytoplot
-
-        #add the clicked points to the plot
-        points = lib.curve.Curve()
-        points.color = 'black'
-        points.label = 'points'
-        points.size = 10
-        points.style = 'scatter'
-        points.x = clickvector_x
-        points.y = clickvector_y
-
-        plot.curves.append(slope)
-        plot.curves.append(points)
+        if slope_show:
+            #add the slope to the plot
+            slope = lib.curve.Curve()
+            slope.color = slope_color
+            slope.label = 'slope'
+            slope.linewidth = slope_linewidth
+            slope.style = 'plot'
+            slope.x = xtoplot
+            slope.y = ytoplot
+            plot.curves.append(slope)
+
+        if point_show:
+            #add the clicked points to the plot
+            points = lib.curve.Curve()
+            points.color = point_color
+            points.label = 'points'
+            points.size = point_size
+            points.style = 'scatter'
+            points.x = clickvector_x
+            points.y = clickvector_y
+            plot.curves.append(points)
 
         self.UpdatePlot(plot)
 
index 842abb9e73f03a73e15a0a4661069f31a6fdfb72..90c11e1dc97f3175500a08dd0ea7654fe9c962ef 100644 (file)
         value = both\r
 \r
 [procplots]\r
+    [[centerzero]]\r
+        default = True\r
+        type = boolean\r
+        value = True\r
+    \r
+    [[correct]]\r
+        default = True\r
+        type = boolean\r
+        value = True\r
+    \r
     [[median]]\r
         default = 0\r
         maximum = 100\r
         minimum = 0\r
         type = integer\r
         value = 7\r
-    \r
-    [[correct]]\r
-        default = True\r
-        type = boolean\r
-        value = True\r
index b7dd12c6c3f4f8eb9f962bcb3ff5ebc19a1f7700..748c96c58097aaf5fb6062fee100345156a3c3aa 100644 (file)
@@ -72,11 +72,7 @@ class procplotsCommands:
 
     def do_derivplot(self):
         '''
-        DERIVPLOT
-        (procplots.py plugin)
-        Plots the discrete differentiation of the currently displayed force curve retraction
-        ---------
-        Syntax: derivplot
+        Plots the discrete differentiation of the currently displayed force curve.
         '''
         column = self.GetIntFromConfig('procplots', 'derivplot', 'column')
         row = self.GetIntFromConfig('procplots', 'derivplot', 'row')
@@ -107,6 +103,12 @@ class procplotsCommands:
 
         self.UpdatePlot(plot)
 
+    def do_replot(self):
+        '''
+        Replots the current force curve from scratch eliminating any secondary plots.
+        '''
+        self.UpdatePlot()
+
     def do_subtplot(self):
         '''
         SUBTPLOT
@@ -198,7 +200,7 @@ class procplotsCommands:
         #use only for force spectroscopy experiments!
         if current.driver.experiment != 'smfs':
             return plot
-    
+
         if not customvalue:
             customvalue = self.GetBoolFromConfig('procplots', 'centerzero')
         if not customvalue:
@@ -206,16 +208,14 @@ class procplotsCommands:
 
         levelapp = float(median(plot.curves[lh.EXTENSION].y))
         levelret = float(median(plot.curves[lh.RETRACTION].y))
-    
-        level = (levelapp + levelret)/2    
-    
+
+        level = (levelapp + levelret)/2
+
         plot.curves[lh.EXTENSION].y = [i-level for i in plot.curves[lh.EXTENSION].y]
         plot.curves[lh.RETRACTION].y = [i-level for i in plot.curves[lh.RETRACTION].y]
-        
-#        plot.vectors[0][1]=approach    
-#        plot.vectors[1][1]=retract    
+
         return plot
-    
+
 #FFT---------------------------
     def fft_plot(self, curve, boundaries=[0, -1]):
         '''
index 10851bc71d6dfe9ce9ec11e7532ad47d6cd8c050..e7b67ceec10ee2042741c091dc880cf2688faffb 100644 (file)
@@ -30,6 +30,7 @@ class resultsCommands(object):
 
     def do_show_results(self):
         '''
-        Select which fitting results should be displayed on the plot.
+        Select which type of result should be displayed on the plot.
         '''
+        self.results_str = self.GetStringFromConfig('results', 'show_results', 'result_type')
         self.UpdatePlot()