From 2dcaca882db0eae6d81fcbbc18c0b96fe92a00e7 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 10 Aug 2010 16:32:31 -0400 Subject: [PATCH] Add TranslateFlatPeaksCommand. This completes a simple velocity clamp force analysis approach. Consider: ./bin/hooke -c 'load_playlist test/data/test' -c 'zero_block_surface_contact_point --block 1' -c 'add_flattened_extension_array --block 1 --max_degree 1 --input_deflection_column "surface deflection (m)"' -c 'add_block_force_array --block 1 --input_deflection_column "flattened deflection (m)"' -c 'add_block_cantilever_adjusted_extension_array --block 1' -c 'flat_filter_peaks --min_points 1' -c 'flat_peaks_to_polymer_peaks --block 1' -c 'polymer_fit_peaks --block 1' --command-no-exit Still to come: * Better contact point fitting or flattening, since the above method currently does a pretty bad job with the actual WLCs. Perhaps a WLC-based zeroing could lead a second fitting iteration. * A way to apply grouped commands like this to each curve in a playlist. * Saving dicts in the playlist format or changing formats so the WLC fitting parameters are accessible for further analysis (e.g. with sawsim: http://dx.doi.org/10.1016/j.ijbiomac.2009.12.001 ). --- hooke/plugin/flatfilt.py | 2 +- hooke/plugin/polymer_fit.py | 80 ++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/hooke/plugin/flatfilt.py b/hooke/plugin/flatfilt.py index a1857fb..ed08a34 100644 --- a/hooke/plugin/flatfilt.py +++ b/hooke/plugin/flatfilt.py @@ -108,7 +108,7 @@ Name of the column (without units) to use as the peak-maske deflection output. Argument(name='peak info name', type='string', default='flat filter peaks', help=""" -Name for storing the distance offset in the `.info` dictionary. +Name for storing the list of peaks in the `.info` dictionary. """.strip()), ]) self._commands = [FlatPeaksCommand(self), FlatFilterCommand(self)] diff --git a/hooke/plugin/polymer_fit.py b/hooke/plugin/polymer_fit.py index 43ed44b..88058a6 100644 --- a/hooke/plugin/polymer_fit.py +++ b/hooke/plugin/polymer_fit.py @@ -40,6 +40,7 @@ from ..curve import Data from ..plugin import Plugin, argument_to_setting from ..util.callback import is_iterable from ..util.fit import PoorFit, ModelFitter +from ..util.peak import Peak from ..util.si import join_data_label, split_data_label from .curve import CurveArgument from .vclamp import scale @@ -920,6 +921,7 @@ Name of the column to use as the deflection input. ]) self._commands = [ PolymerFitCommand(self), PolymerFitPeaksCommand(self), + TranslateFlatPeaksCommand(self), ] def dependencies(self): @@ -1110,9 +1112,9 @@ approach/retract force curve, `0` selects the approaching curve and `1` selects the retracting curve. """.strip()), Argument(name='peak info name', type='string', - default='flat filter peaks', + default='polymer peaks', help=""" -Name for storing the distance offset in the `.info` dictionary. +Name for the list of peaks in the `.info` dictionary. """.strip()), Argument(name='peak index', type='int', count=-1, default=None, help=""" @@ -1141,6 +1143,80 @@ Index of the selected peak in the list of peaks. Use `None` to fit all peaks. if not isinstance(ret, Success): raise ret + +class TranslateFlatPeaksCommand (Command): + """Translate flat filter peaks into polymer peaks for fitting. + + Use :class:`~hooke.plugin.flatfilt.FlatPeaksCommand` creates a + list of peaks for regions with large derivatives. For velocity + clamp measurements, these regions are usually the rebound phase + after a protein domain unfolds, the cantilever detaches, etc. + Because these features occur after the polymer loading phase, we + need to shift the selected regions back to align them with the + polymer loading regions. + """ + def __init__(self, plugin): + plugin_arguments = [a for a in plugin._arguments + if a.name in ['input distance column', + 'input deflection column']] + arguments = [ + CurveArgument, + Argument(name='block', aliases=['set'], type='int', default=0, + help=""" +Data block for which the fit should be calculated. For an +approach/retract force curve, `0` selects the approaching curve and +`1` selects the retracting curve. +""".strip()), + ] + plugin_arguments + [ + Argument(name='input peak info name', type='string', + default='flat filter peaks', + help=""" +Name for the input peaks in the `.info` dictionary. +""".strip()), + Argument(name='output peak info name', type='string', + default='polymer peaks', + help=""" +Name for the ouptput peaks in the `.info` dictionary. +""".strip()), + Argument(name='end offset', type='int', default=-1, + help=""" +Number of points between the end of a new peak and the start of the old. +""".strip()), + Argument(name='start fraction', type='float', default=0.2, + help=""" +Place the start of the new peak at `start_fraction` from the end of +the previous old peak to the end of the new peak. Because the first +new peak will have no previous old peak, it uses a distance of zero +instead. +""".strip()), + ] + super(TranslateFlatPeaksCommand, self).__init__( + name='flat peaks to polymer peaks', + arguments=arguments, + help=self.__doc__, plugin=plugin) + + def _run(self, hooke, inqueue, outqueue, params): + data = params['curve'].data[params['block']] + z_data = data[:,data.info['columns'].index( + params['input distance column'])] + d_data = data[:,data.info['columns'].index( + params['input deflection column'])] + previous_old_stop = numpy.absolute(z_data).argmin() + new = [] + for i,peak in enumerate(data.info[params['input peak info name']]): + next_old_start = peak.index + stop = next_old_start + params['end offset'] + z_start = z_data[previous_old_stop] + params['start fraction']*( + z_data[stop] - z_data[previous_old_stop]) + start = numpy.absolute(z_data - z_start).argmin() + p = Peak('polymer peak %d' % i, + index=start, + values=d_data[start:stop]) + new.append(p) + previous_old_stop = peak.post_index() + data.info[params['output peak info name']] = new + + # TODO: # def dist2fit(self): # '''Calculates the average distance from data to fit, scaled by -- 2.26.2