--- /dev/null
+******************
+Analysis templates
+******************
+
+.. toctree::
+ :maxdepth: 2
+
+Overview
+========
+
+Hooke is a large, flexible beast, and the number of available commands
+can be intimidating. In this section, we'll lay out the procedure for
+analyzing a number of common experiment types. The experiment types
+are arranged in the order that they were developed, citating the first
+known paper in each class. If we've got a citation wrong, please
+submit a bug report (:doc:`bugs`).
+
+
+Velocity clamp force spectroscopy
+=================================
+
+Developed by Rief et al. [#rief1997]_, velocity clamp spectroscopy
+measures domain unfolding forces as the tip is moved away from the
+surface at a constant velocity.
+
+.. todo:: Velocity clamp example plot.
+
+Basic analysis is something like::
+
+ hooke> zero_surface_contact_point --block retract
+ hooke> flat_filter_peaks --block retract --min_points 1
+ hooke> zero_surface_contact_point --block retract
+ ... --ignore_after_last_peak_info_name 'flat filter peaks'
+ hooke> convert_distance_to_force --block retract
+ ... --deflection_column 'surface deflection (m)'
+ hooke> remove_cantilever_from_extension --block retract
+ hooke> flat_peaks_to_polymer_peaks --block retract
+ hooke> polymer_fit_peaks --block retract
+ hooke> block_info --block retract --output data.yaml name 'polymer peak [0-9]*'
+
+The unfolding forces should be grouped by pull velocity, and the resulting
+distributions can be fit to specific unfolding models by comparison with
+monte-carlo simulations (see, for example, sawsim_).
+
+.. [#rief1997] M. Rief, M. Gautel, F. Oesterhelt, J.M. Fernandez,
+ H.E. Gaub.
+ "Reversible Unfolding of Individual Titin Immunoglobulin Domains by AFM."
+ Science, 1997.
+ doi: `10.1126/science.276.5315.1109 <http://dx.doi.org/10.1126/science.276.5315.1109>`_
+
+.. _sawsim: http://www.physics.drexel.edu/~wking/sawsim/
+
+Force clamp spectroscopy
+========================
+
+Developed by Fernandez and Li [#fernandez2004]_, force clamp spectroscopy
+measures the lifetime of a domain's folded state while subject to a constant
+tension.
+
+.. todo:: Force clamp example plot.
+
+.. todo:: Force clamp example analysis.
+
+.. [#fernandez2004] J.M. Fernandez, H. Li.
+ "Force-Clamp Spectroscopy Monitors the Folding Trajectory of a
+ Single Protein."
+ Science, 2004.
+ doi: `10.1126/science.1092497 <http://dx.doi.org/10.1126/science.1092497>`_
+
+Two-color fluorescence coincidence spectroscopy
+===============================================
+
+Developed by Clarke et al. [#clarke2007]_,...
+
+.. todo:: TCCS explanation.
+
+.. todo:: TCCS example plot.
+
+.. todo:: TCCS example analysis.
+
+.. [#clarke2007] R.W. Clarke, A. Orte, D. Klenerman.
+ "Optimized Threshold Selection for Single-Molecule Two-Color
+ Fluorescence Coincidence Spectroscopy."
+ Anal. Chem., 2007.
+ doi: `10.1021/ac062188w <http://dx.doi.org/10.1021/ac062188w>`_
install
tutorial
+ analysis
config
bugs
hacking
+ standards
hooke/hooke
doc
--- /dev/null
+********************
+Standard experiments
+********************
+
+.. toctree::
+ :maxdepth: 2
+
+Overview
+========
+
+Force spectroscopy experiments are generally classified as "force
+clamp", "velocity clamp", etc.. While previous versions of Hooke
+attempted to reproduce such classification, I now believe this
+classification is counter-productive. The type of experiment carried
+out by a given :class:`~hooke.curve.Curve` is determined by the
+sequence of :class:`~hooke.curve.Data` blocks in the curve. For
+example, a classic velocity clamp experiment would look like::
+
+ hooke> curve_info --enable-block_names
+ block names: ['approach', 'pause', 'retract']
+
+And classic force clamp experiment would look like::
+
+ hooke> curve_info --enable-block_names
+ block names: ['approach', 'pause', 'retract', 'force clamp']
+
+However, the situation is complicated by refolding experiments such as::
+
+ hooke> curve_info --enable-block_names
+ block names: ['approach-0', 'pause-0', 'retract-0',
+ 'approach-1', 'pause-1', 'retract-1',
+ 'approach-2', 'pause-2', 'retract-2',
+ ...]
+
+The benefit to classifying curves in Hooke is that each class of
+experiment has a standard analysis procedure (e.g. unfolding force
+extraction for velocity clamp experiments or survival time extraction
+for force clamp experiments). However, the potential convenience of
+Hooke being able to guess a user's desired analysis is outweighed by
+the increased complexity and rigidity that such guessing requires.
+Instead we provide :class:`~hooke.command.Command`\s that can be
+applied to any data block, and leave it up to the user to construct a
+sequence of analysis commands that makes sense. The risk to this
+flexible approach is confusion for both the user and the Hooke
+developer. The remainder of this section lays out a scheme for
+maintaining developer sanity. Users should read over the
+:doc:`analysis` section for an overview of analysis procedures
+that are standardized enough to have written documentation.
+
+Drivers
+=======
+
+.. todo:: Explain driver responsibilities.
+
+Commands
+========
+
+.. todo:: Explain command analysis and storage behaviour.
+
+Results
+=======
+
+.. todo:: Explain procedure for exporting analysis results.
import numpy
from .command_stack import CommandStack
-from . import experiment
class NotRecognized (ValueError):
would consist of the approach data and the retract data. Metadata
would be the temperature, cantilever spring constant, etc.
- Two important :attr:`info` settings are `filetype` and
- `experiment`. These are two strings that can be used by Hooke
- commands/plugins to understand what they are looking at.
-
- * :attr:`info['filetype']` should contain the name of the exact
- filetype defined by the driver (so that filetype-speciofic
- commands can know if they're dealing with the correct filetype).
- * :attr:`info['experiment']` should contain an instance of a
- :class:`hooke.experiment.Experiment` subclass to identify the
- experiment type. For example, various
- :class:`hooke.driver.Driver`\s can read in force-clamp data, but
- Hooke commands could like to know if they're looking at force
- clamp data, regardless of their origin.
-
- Another important attribute is :attr:`command_stack`, which holds
- a :class:`~hooke.command_stack.CommandStack` listing the commands
- that have been applied to the `Curve` since loading.
+ Each :class:`Data` block in :attr:`data` must contain an
+ :attr:`info['name']` setting with a unique (for the parent
+ curve) name identifying the data block. This allows plugins
+ and commands to access individual blocks.
+
+ Each curve maintiains a :class:`~hooke.command_stack.CommandStack`
+ (:attr:`command_stack`) listing the commands that have been
+ applied to the `Curve` since loading.
The data-type is pickleable, to ensure we can move it between
processes with :class:`multiprocessing.Queue`\s.
The input `info` :class:`dict` may contain attributes read
from the :class:`~hooke.playlist.FilePlaylist`.
- The `info` :class:`dict` must contain values for the keys:
- 'filetype' and 'experiment'. See :class:`hooke.curve.Curve`
- for details.
+ See :class:`hooke.curve.Curve` for details.
"""
raise NotImplementedError
self.filedata = open(filename,'r')
self.data = list(self.filedata)
self.filedata.close()
-
- self.filetype = 'generic'
- self.experiment = ''
-
self.filename=filename
def close_all(self):
self.lines=list(self.filedata.readlines())
self.filedata.close()
- self.filetype='hdf5'
- self.experiment='smfs'
-
def close_all(self):
self.filedata.close()
import numpy
from .. import curve as curve
-from .. import experiment as experiment
from ..util.util import Closing as Closing
from . import Driver as Driver
ret.info['name'] = 'force clamp'
# assume 1 ms timestep
ret[:,0] = numpy.arange(0, 1e-3*data.shape[0], 1e-3, dtype=ret.dtype)
-
- file_info['filetype'] = self.name
- file_info['experiment'] = experiment.ForceClamp()
+
return ([ret,], file_info)
import numpy
from .. import curve as curve
-from .. import experiment as experiment
from ..util.util import Closing as Closing
from ..util.si import join_data_label, split_data_label
from . import Driver as Driver
def _zip_translate_params(self, params, chan_info):
info = {
'raw info':params,
- 'filetype':self.name,
#'time':self._time_from_TODO(raw_info[]),
}
- # TODO: distinguish between force clamp and velocity clamp
- # experiments. Note that the JPK file format is flexible
- # enough to support mixed experiments (i.e. both force clamp
- # and velocity clamp segments in a single experiment), but I
- # have no idea what sort of analysis such experiments would
- # require ;).
- info['experiment'] = experiment.VelocityClamp()
force_unit = chan_info['channel']['vDeflection']['conversion-set']['conversion']['force']['scaling']['unit']['unit']
assert force_unit == 'N', force_unit
force_base = chan_info['channel']['vDeflection']['conversion-set']['conversion']['force']['base-calibration-slot']
self.bluedata=self.filebluedata.read()
self.filebluedata.close()
- self.filetype = 'mcs'
- self.experiment = 'smfluo'
-
def close_all(self):
self.filedata.close()
self.filebluedata.close()
self.lines = list(self.filedata.readlines())
self.filedata.close()
- self.filetype = 'mfp1d'
- self.experiment = 'smfs'
-
def _load_from_file(self, filename, extract_note=False):
data = None
f = open(filename, 'rb')
self.lines = list(self.filedata.readlines())
self.filedata.close()
- self.filetype='mfp1dexport'
- self.experiment='smfs'
-
def close_all(self):
self.filedata.close()
import numpy
from .. import curve as curve
-from .. import experiment as experiment
from . import Driver as Driver
from .igorbinarywave import loadibw
def read(self, path, info=None):
data,bin_info,wave_info = loadibw(path)
blocks,info = self._translate_ibw(data, bin_info, wave_info)
- info['filetype'] = self.name
- info['experiment'] = experiment.VelocityClamp()
return (blocks, info)
def _translate_ibw(self, data, bin_info, wave_info):
import numpy
from .. import curve as curve # this module defines data containers.
-from .. import experiment as experiment # this module defines expt. types
from . import Driver as Driver # this is the Driver base class
info = self._read_header_path(path)
self._check_version(info)
data = self._read_data_path(path, info)
- info['filetype'] = self.name
- info['experiment'] = experiment.VelocityClamp()
return (data, info)
def _read_header_path(self, path):
# The following are relative imports. See PEP 328 for details
# http://www.python.org/dev/peps/pep-0328/
from .. import curve as curve # this module defines data containers.
-from .. import experiment as experiment # this module defines expt. types
from ..config import Setting # configurable setting class
from . import Driver as Driver # this is the Driver base class
f.close() # remember to close the file
data = curve.Data()
- info = {'filetype':'tutorial', 'experiment':experiment.Experiment()}
+ info = {}
return (data, info)
import numpy
from .. import curve as curve
-from .. import experiment as experiment
from ..config import Setting
from . import Driver as Driver
unlabeled_approach_data, params, 'approach')
retract = self._scale_block(
unlabeled_retract_data, params, 'retract')
- info = {'filetype':self.name, 'experiment':experiment.VelocityClamp()}
+ info = {}
return ([approach, retract], info)
def _paths(self, path):
+++ /dev/null
-# Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
-#
-# This file is part of Hooke.
-#
-# Hooke is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# Hooke is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
-# Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with Hooke. If not, see
-# <http://www.gnu.org/licenses/>.
-
-"""Define :class:`Experiment` and assorted subclasses.
-
-This allows :class:`hooke.plugin.Plugin`\s to specify the types of
-experiments they can handle.
-"""
-
-from .util.singleton import Singleton
-
-
-class Experiment (Singleton):
- """Base class for experiment classification.
- """
- pass
-
-class ForceClamp (Experiment):
- """Constant force force spectroscopy [#fernandez2004]_.
-
- .. [#fernandez2004] J.M. Fernandez, H. Li.
- "Force-Clamp Spectroscopy Monitors the Folding Trajectory of a
- Single Protein."
- Science, 2004.
- doi: `10.1126/science.1092497 <http://dx.doi.org/10.1126/science.1092497>`_
- """
- pass
-
-class VelocityClamp (Experiment):
- """Constant piezo velocity force spectroscopy [#rief1997]_.
-
- .. [#rief1997] M. Rief, M. Gautel, F. Oesterhelt, J.M. Fernandez,
- H.E. Gaub.
- "Reversible Unfolding of Individual Titin Immunoglobulin Domains by AFM."
- Science, 1997.
- doi: `10.1126/science.276.5315.1109 <http://dx.doi.org/10.1126/science.276.5315.1109>`_
- """
- pass
-
-class TwoColorCoincidenceDetection (Experiment):
- """Two-color fluorescence coincidence spectroscopy [#clarke2007]_.
-
- .. [#clarke2007] R.W. Clarke, A. Orte, D. Klenerman.
- "Optimized Threshold Selection for Single-Molecule Two-Color
- Fluorescence Coincidence Spectroscopy."
- Anal. Chem., 2007.
- doi: `10.1021/ac062188w <http://dx.doi.org/10.1021/ac062188w>`_
- """
- pass
from ..command import Command, Argument, Success, Failure
from ..config import Setting
-from ..experiment import VelocityClamp
from ..util.fit import PoorFit
from ..util.peak import find_peaks, find_peaks_arguments, Peak, _kwargs
from . import Plugin, argument_to_setting
deflection arrays.
"""
curve = params['curve']
- if not isinstance(curve.info['experiment'], VelocityClamp):
- raise Failure('%s operates on VelocityClamp experiments, not %s'
- % (self.name, curve.info['experiment']))
data = None
for block in curve.data:
if block.info['name'].startswith('retract'):
Argument(name='all', type='bool', default=False, count=1,
help='Get all curve information.'),
]
- self.fields = ['name', 'path', 'experiment', 'driver', 'filetype',
- 'note', 'command stack', 'blocks', 'block names',
- 'block sizes']
+ self.fields = ['name', 'path', 'driver', 'note', 'command stack',
+ 'blocks', 'block names', 'block sizes']
for field in self.fields:
args.append(Argument(
name=field, type='bool', default=False, count=1,
def _get_path(self, curve):
return curve.path
- def _get_experiment(self, curve):
- return curve.info.get('experiment', None)
-
def _get_driver(self, curve):
return curve.driver
- def _get_filetype(self, curve):
- return curve.info.get('filetype', None)
-
def _get_note(self, curve):
return curve.info.get('note', None)
See Also
--------
-:mod:`~hooke.plugin.convfilt` for a convolution-based filter for
-:class:`~hooke.experiment.VelocityClamp` experiments.
+:mod:`~hooke.plugin.convfilt` for a convolution-based filter.
"""
import copy
from ..command import Argument, Success, Failure, UncaughtException
from ..config import Setting
from ..curve import Data
-from ..experiment import VelocityClamp
from ..util.fit import PoorFit
from ..util.peak import (find_peaks, peaks_to_mask,
find_peaks_arguments, Peak, _kwargs)
deflection arrays.
"""
curve = self._curve(hooke=hooke, params=params)
- if not isinstance(curve.info['experiment'], VelocityClamp):
- raise Failure('%s operates on VelocityClamp experiments, not %s'
- % (self.name, curve.info['experiment']))
for key,value in params.items():
if value == None and key in self.plugin.config:
# Use configured default value.