--- /dev/null
+genrst = 'python generate-hooke-txt.py'
--- /dev/null
+"""
+This is a generic SCons script for running Sphinx (http://sphinx.pocoo.org).
+
+Type 'scons -h' for help. This prints the available build targets on your
+system, and the configuration options you can set.
+
+If you set the 'cache' option, the option settings are cached into a file
+called '.sconsrc-sphinx' in the current directory. When running
+subsequently, this file is reread. A file with this name is also read from
+your home directory, if it exists, so you can put global settings there.
+
+The script looks into your 'conf.py' file for information about the
+project. This is used in various places (e.g., to print the introductory
+message, and create package files).
+
+Here's some examples. To build HTML docs:
+
+ scons html
+
+To create a package containing HTML and PDF docs, remembering the 'install'
+setting:
+
+ scons install=html,pdf cache=True package
+
+To clean up everything:
+
+ scons -c all
+"""
+
+# Script info.
+__author__ = "Glenn Hutchings"
+__email__ = "zondo42@googlemail.com"
+__url__ = "http://bitbucket.org/zondo/sphinx-scons"
+__license__ = "BSD"
+__version__ = "0.4"
+
+import sys, os
+
+# Build targets.
+targets = (
+ ("html", "make standalone HTML files"),
+ ("dirhtml", "make HTML files named index.html in directories"),
+ ("pickle", "make pickle files"),
+ ("json", "make JSON files"),
+ ("htmlhelp", "make HTML files and a HTML help project"),
+ ("qthelp", "make HTML files and a qthelp project"),
+ ("devhelp", "make HTML files and a GNOME DevHelp project"),
+ ("epub", "make HTML files and an EPUB file for bookreaders"),
+ ("latex", "make LaTeX sources"),
+ ("text", "make text file for each RST file"),
+ ("pdf", "make PDF file from LaTeX sources"),
+ ("ps", "make PostScript file from LaTeX sources"),
+ ("dvi", "make DVI file from LaTeX sources"),
+ ("changes", "make an overview over all changed/added/deprecated items"),
+ ("linkcheck", "check all external links for integrity"),
+ ("doctest", "run all doctests embedded in the documentation if enabled"),
+ ("source", "run a command to generate the reStructuredText source"),
+)
+
+# LaTeX builders.
+latex_builders = {"pdf": "PDF", "ps": "PostScript", "dvi": "DVI"}
+
+# List of target names.
+targetnames = [name for name, desc in targets]
+
+# Configuration cache filename.
+cachefile = ".sconsrc-sphinx"
+
+# User cache file.
+homedir = os.path.expanduser('~')
+usercache = os.path.join(homedir, cachefile)
+
+# Configuration options.
+config = Variables([usercache, cachefile], ARGUMENTS)
+
+config.AddVariables(
+ EnumVariable("default", "default build target", "html", targetnames),
+ PathVariable("config", "sphinx configuration file", "conf.py"),
+ PathVariable("srcdir", "source directory", ".",
+ PathVariable.PathIsDir),
+ PathVariable("builddir", "build directory", "build",
+ PathVariable.PathIsDirCreate),
+ PathVariable("doctrees", "place to put doctrees", None,
+ PathVariable.PathAccept),
+ EnumVariable("paper", "LaTeX paper size", None,
+ ["a4", "letter"], ignorecase = False),
+ ("tags", "comma-separated list of 'only' tags", None),
+ ("builder", "program to run to build things", "sphinx-build"),
+ ("opts", "extra builder options to use", None),
+ ListVariable("install", "targets to install", ["html"], targetnames),
+ PathVariable("instdir", "installation directory", "/usr/local/doc",
+ PathVariable.PathAccept),
+ EnumVariable("pkgtype", "package type to build with 'scons package'",
+ "zip", ["zip", "targz", "tarbz2"], ignorecase = False),
+ BoolVariable("cache", "whether to cache settings in %s" % cachefile, False),
+ BoolVariable("debug", "debugging flag", False),
+ ("genrst", "Command to regenerate reStructuredText source", None),
+)
+
+# Create a new environment, inheriting PATH to find builder program. Also
+# force LaTeX instead of TeX, since the .tex file won't exist at the right
+# time to check which one to use.
+env = Environment(ENV = {"PATH" : os.environ["PATH"]},
+ TEX = "latex", PDFTEX = "pdflatex",
+ tools = ['default', 'packaging'],
+ variables = config)
+
+# Get configuration values from environment.
+sphinxconf = env["config"]
+builder = env["builder"]
+default = env["default"]
+
+srcdir = env["srcdir"]
+builddir = env["builddir"]
+doctrees = env.get("doctrees", os.path.join(builddir, "doctrees"))
+
+cache = env["cache"]
+debug = env["debug"]
+
+options = env.get("opts", None)
+paper = env.get("paper", None)
+tags = env.get("tags", None)
+genrst = env.get("genrst", None)
+
+instdir = env["instdir"]
+install = env["install"]
+pkgtype = env["pkgtype"]
+
+# Dump internals if debugging.
+if debug:
+ print "Environment:"
+ print env.Dump()
+
+# Get parameters from Sphinx config file.
+sphinxparams = {}
+execfile(sphinxconf, sphinxparams)
+
+project = sphinxparams["project"]
+release = sphinxparams["release"]
+copyright = sphinxparams["copyright"]
+
+try:
+ texfilename = sphinxparams["latex_documents"][0][1]
+except KeyError:
+ texfilename = None
+
+name2tag = lambda name: name.replace(" ", "-").strip("()")
+project_tag = name2tag(project)
+release_tag = name2tag(release)
+package_tag = project_tag.lower() + "-" + release_tag.lower()
+
+# Build project description string.
+description = "%(project)s, release %(release)s, " \
+ "copyright %(copyright)s" % locals()
+
+Help(description + "\n\n")
+help_format = " %-10s %s\n"
+
+# Print banner if required.
+if not any(map(GetOption, ("silent", "clean", "help"))):
+ print
+ print "This is", description
+ print
+
+# Build sphinx command-line options.
+opts = []
+
+if tags:
+ opts.extend(["-t %s" % tag for tag in tags.split(",")])
+
+if paper:
+ opts.append("-D latex_paper_size=%s" % paper)
+
+if options:
+ opts.append(options)
+
+options = " ".join(opts)
+
+# Build Sphinx command template.
+sphinxcmd = """
+%(builder)s -b %(name)s -d %(doctrees)s %(options)s %(srcdir)s %(targetdir)s
+""".strip()
+
+# Set up LaTeX input builder if required.
+if texfilename:
+ latexdir = Dir("latex", builddir)
+ texinput = File(texfilename, latexdir)
+ env.SideEffect(texinput, "latex")
+ env.NoClean(texinput)
+
+# Add build targets.
+Help("Build targets:\n\n")
+
+if genrst != None:
+ source = env.Command('source', [], genrst)
+ env.AlwaysBuild(source)
+ env.Depends(srcdir, source)
+else:
+ Alias('source', srcdir)
+
+for name, desc in targets:
+ target = Dir(name, builddir)
+ targetdir = str(target)
+
+ if name == 'source':
+ pass
+ elif name not in latex_builders:
+ # Standard Sphinx target.
+ env.Command(name, sphinxconf,
+ sphinxcmd % locals(), chdir = True)
+ env.AlwaysBuild(name)
+ env.Alias(target, name)
+ elif texinput:
+ # Target built from LaTeX sources.
+ try:
+ buildfunc = getattr(env, latex_builders[name])
+ except AttributeError:
+ continue
+
+ filename = project_tag + "." + name
+ outfile = File(filename, latexdir)
+
+ buildfunc(outfile, texinput)
+
+ # Copy built file to separate directory.
+ target = File(filename, target)
+ env.Command(target, outfile, Move(target, outfile), chdir = True)
+
+ env.Alias(name, target)
+ else:
+ continue
+
+ env.Clean(name, [target])
+ env.Clean('all', target)
+
+ if name == default: desc += " (default)"
+ Help(help_format % (name, desc))
+
+Clean('all', doctrees)
+Default(default)
+
+# Add installation targets and collect package sources.
+Help("\nOther targets:\n\n")
+
+Help(help_format % ("install", "install documentation"))
+projectdir = os.path.join(instdir, project_tag)
+sources = []
+
+for name in install:
+ source = Dir(name, builddir)
+ sources.append(source)
+
+ inst = env.Install(projectdir, source)
+ env.Alias('install', inst)
+
+ for node in env.Glob(os.path.join(str(source), '*')):
+ filename = str(node).replace(builddir + os.path.sep, "")
+ dirname = os.path.dirname(filename)
+ dest = os.path.join(projectdir, dirname)
+ inst = env.Install(dest, node)
+ env.Alias('install', inst)
+
+# Add uninstall target.
+env.Command('uninstall', None, Delete(projectdir), chdir = True)
+Help(help_format % ("uninstall", "uninstall documentation"))
+
+## Add package builder.
+#packageroot = "-".join([project_tag, release_tag])
+#archive, package = env.Package(NAME = project_tag, VERSION = release,
+# PACKAGEROOT = packageroot,
+# PACKAGETYPE = pkgtype,
+# source = sources)
+#
+#env.AlwaysBuild(archive)
+#env.AddPostAction(archive, Delete(packageroot))
+#Help(help_format % ("package", "build documentation package"))
+#
+#env.Clean('all', archive)
+
+# Add config settings to help.
+Help("\nConfiguration variables:")
+for line in config.GenerateHelpText(env).split("\n"):
+ Help("\n " + line)
+
+# Save local configuration if required.
+if cache:
+ config.Update(env)
+ config.Save(cachefile, env)
+++ /dev/null
-Starting Hooke
-==============
-
-Open a terminal, go to the directory Hooke is installed and type
- python bin/hooke
-(You may need to give the full path for Python on Windows systems).
-If everything is OK, Hooke displays a nice splashscreen and starts.
-
-Once Hooke is launched from the terminal window, you see a text like
-the following:
-
- Starting Hooke.
- Imported plugin fit
- Imported plugin procplots
- Imported plugin flatfilts
- Imported plugin generalclamp
- Imported plugin generalvclamp
- Imported plugin massanalysis
- Imported plugin macro
- Imported driver picoforce
- Imported driver hemingclamp
- Imported driver csvdriver
- Imported driver tutorialdriver
-
- Warning: Invalid work directory.
- This is Hooke, version 0.8.0 Seinei
- (c) Massimo Sandal, 2006.
- Released under the GNU General Public License Version 2.
- Hooke is Free software.
- ----
- hooke:
-
-Hooke tells you that plugins and drivers have been loaded, and now
-you’re ready to go. You’re now at the Hooke command line. In the
-meantime, a splashscreen and a window with a dummy force curve should
-appear . At the command line, type "help" or "?" to obtain a list of
-available commands.
-
-hooke: ?
-Documented commands (type help <topic>):
-========================================
-addtolist debug exit genlist ls notelog previous set
-cd derivplot export getlist n p printlist size
-contact dir flatfilt jump next plateau pwd subtplot
-current distance force loadlist note plot savelist wlc
-Undocumented commands:
-======================
-help
-
-hooke:
-
-
-Begin your analysis
-===================
-
-Create a playlist
------------------
-
-To start analyzing your curves, you first have to build a playlist. The
-playlist is just an index of the force curve files you want to
-analyze. Imagine it as a music playlist (that’s why it is called a
-playlist), but made of data files instead of MP3s (or FLACs :p).
-
-Suppose you have 100 PicoForce curve files in your curves directory,
-starting from mycurve.000 and ending in mycurve.100 and you want to
-analyze them all.
-
-You then can cd to the directory
-
- hooke: cd c:\curves
-
-Type pwd to check the directory is correct
-
- hooke: pwd
- c:\curves
- hooke:
-
-You can list the files in the directory using ls or dir (they’re synonims)
-
- hooke: ls
- [’mycurve.000’, ’mycurve.001’, ...]
-
-Now you are ready to generate the playlist. The command to use is genlist
-
- hooke: genlist mycurve.*
-
-You can also generate a playlist containing all what you find in the
-directory by typing:
-
- hooke: genlist c:\curves
-
-If you want to select what curves to see, based on the filename, you
-can use wildcards.
-
- For example:
-
- hooke: genlist mycurve.05*
-
-will take only curves from mycurve.050 to mycurve.059.
-
-Saving and loading playlists
-----------------------------
-
-Note that by using genlist you just generate the playlist in the local
-session. To save your playlist to a file, thus avoiding to regenerate
-it, type:
-
- hooke: savelist mylist
-
-The list will be saved, in this example, in the file mylist.hkp. Hooke
-will add the extension .hkp to the playlist if you forget to. The .hkp
-file is an XML file you can read and edit with any text editor
-(i.e. Wordpad), if needed. If you want to load it, just issue loadlist
-mylist.hkp or loadlist mylist, Hooke will handle the missing .hkp
-extension. This will load the saved playlist, as if you just generated
-it.
-
-Generating the playlist, you should see the plot of the first curve
-appearing. If, generating the playlist, you are including by chance a
-non-force curve file that Hooke cannot open, it should be (more or
-less) silently ignored. If it gives some error, or it does not plot
-anything, try to navigate forward, and see if the next curve is
-plotted; it is possible you spotted a corrupted file. Navigate the
-playlist
-
-Navigating playlists
---------------------
-
-Now you can navigate through your playlist using the command next and
-previous or, more easily, their aliases n and p. You don’t need to
-type n every time to run along a list of curves. If you press Return
-to an empty prompt, Hooke will repeat the last command you issued
-explicitly.
-
-You can also navigate through the command history by using the up and
-down arrows.
-
-When arriving to the last curve of your playlist, pressing n will just
-come back to the first. Analogously, pressing p when at the first
-curve will jump to the last.
-
-You can also jump to a given curve, this way:
-
- hooke: jump c:\curves\mycurve.123
-
-but be careful to tell Hooke the full path to that curve, otherwise it
-will not find it.
-
-
-Taking notes
-============
-
-You can take notes about the curves you are looking at. Just type note
-followed by the text you want to append to that curve. Hooke will save
-the text in your current playlis and in an external log file. The
-output will look like this:
-
- Notes taken at Sun Sep 17 20:42:07 2006
- /home/cyclopia/work/tris/20060620a.041 | This is a note
- /home/cyclopia/work/tris/20060620a.207 | This is another note
- /home/cyclopia/work/tris/20060620a.286 | This is a third one
-
-The first time you type note in a session, Hooke will ask you for a
-filename of the log.
-
-Usually curves you annotated are useful later. You can copy the curves
-you annotated in a different directory by using the copylog command,
-
- hooke: copylog c:\nicecurves
-
-which will copy all curves you have annotated in the c:\nicecurves
-directory. Take care that the directory already exists before doing
-that.
-
-
-Exporting curves
-================
-
-You can export Hooke curves as images and as text columns. To export
-as images, issue the export command followed by the
-filename. Supported formats are PNG (raster) and EPS (Encapsulated
-Postscript, vector). The export format is determined by the filename
-extension, so export foo.png and export foo.eps will save a PNG and
-EPS file respectively.
-
-To export as text, use the txt command, followed by the filename. The
-output is a text file containing columns (first two are X and Y of
-extension, last two are X and Y of retraction).
-
-
-Interacting with the plot
-=========================
-
-Measuring distances and forces
-------------------------------
-
-You can easily zoom in the plot by dragging a rectangle on it with the
-left mouse button. To zoom out, click the right mouse
-button. Sometimes by zooming in and out too much, you can lose the
-picture (this is probably a small bug in Matplotlib). Just type plot
-at the command line and the curve will be refreshed.
-
-You can measure distances and forces directly in the plot. Just issue
-the command distance. You will be asked to click two points: do
-it. When you click a point, a blue dot should appear. When you click
-the second point, the distance (in nanometers) will apper on the
-command line. force works in the same way. You can use delta if you
-prefer, which gives meaningful values for every kind of graph (not
-only force curves). If you want to know the coordinates of a single
-point, use point.
-
-Hooke automatically adjusts the position of the clicked point at the
-nearest point in the graph, so you will be always measuring distances
-and forces between points in the graph.
-
-The commands force and distance are present in the generalvclamp.py
-plugin.
-
-Worm like chain fitting
------------------------
-
-You can measure by hand the parameters relative to a force peak using
-a worm-like chain fitting with the wlc command. The command by default
-automatically finds the contact point, asks for two points delimiting
-the portion to fit, and performs a two-variable fit, with contour
-length and persistence length as output, with relative errors. If
-desired, one can use the noauto option to manually click the contact
-point, and/or the pl=[number] options to impose a specific persistence
-length (in nanometers). Please see the help of the wlc command from
-the Hooke command line for details.
-
-Variables
----------
-
-You can set environment variables to influence the behaviour of
-Hooke. The command to use is set.
-
-You can alter permanently the behaviour of Hooke by setting these
-variables in the file conf/hooke.conf. This is a very simple XML file,
-just change the values of the variables with an ASCII text editor (not
-Word or a word processor - on Windows, Wordpad should work). Be
-careful with the correct XML syntax (which you should grasp very
-easily looking at the default configuration file) otherwise Hooke will
-crash on the next startup.
-
-See VariableList for help on individual variables.
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# sphinx-scons documentation build configuration file, created by
+# sphinx-quickstart on Thu Mar 12 10:37:15 2009.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath('..'))
+
+import hooke
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.txt' #'.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Hooke'
+copyright = u'2006-2010, Massimo Sandal et al.'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = hooke.version(2)
+# The full version, including alpha/beta/rc tags.
+release = hooke.version(5)
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+html_title = project + " documentation"
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+#html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'sphinx-sconsdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'hooke.tex', ur'Hooke Documentation',
+ ur'W. Trevor King', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
--- /dev/null
+*****************
+Configuring Hooke
+*****************
+
+Hooke initializes a number of variables by reading configuration
+files.
+
+Syntax
+------
+
+Hooke uses Python's configparser_ library to read the config files.
+The format is similar to MS Windows' INI (initialization) format::
+
+ [My Section]
+ foo = bar
+ baz = 5
+
+.. _configparser: http://docs.python.org/library/configparser.html
+
+Examples
+--------
+
+Run::
+
+ $ hooke --example-config-file
+
+To print a well commented example config file to stdout.
+
+
+Finding configuration files
+---------------------------
+
+The default search path follows the `Filesystem Hierarchy
+Standard`_, and so will probably need adjustment for non-*nix systems.
+The default path list is
+
+* /usr/share/hooke/hooke.cfg
+* /etc/hooke/hooke.cfg
+* ~/.hooke.cfg
+
+but alternatives can be specified from the command line launching
+Hooke.
+
+_ ..Filesystem Hierarchy Standard: http://www.pathname.com/fhs/
--- /dev/null
+****************************
+Producing this documentation
+****************************
+
+This documentation is written in reStructuredText_, and produced using
+Sphinx_ and the numpydoc_ extension. The documentation source should
+be fairly readable without processing, but to compile the
+documentation, change to the ``doc/`` directory and run::
+
+ $ scons
+
+For which you'll need to install Sphinx, numpydoc, and SCons_::
+
+ $ easy_install Sphinx
+ $ easy_install numpydoc
+
+.. _Sphinx: http://sphinx.pocoo.org/
+.. _numpydoc: http://pypi.python.org/pypi/numpydoc
+.. _SCons: http://www.scons.org/
+
+See the reStructuredText quick reference and the `NumPy/SciPy
+documentation guide`_ for an introduction to the documentation
+syntax.
+
+.. _reStructuredText:
+ http://docutils.sourceforge.net/docs/user/rst/quickref.html
+.. _NumPy/SciPy documentation guide:
+ http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines
--- /dev/null
+#!/usr/bin/python
+#
+# COPYRIGHT
+
+"""Auto-generate reStructuredText of the hooke module tree for Sphinx.
+
+This script is adapted from one written for `Bugs Everywhere`_.
+
+.. _Bugs Everywhere: http://bugseverywhere.org/
+"""
+
+import sys
+import os, os.path
+
+
+sys.path.insert(0, os.path.abspath('..'))
+
+
+def title(modname):
+ t = ':mod:`%s`' % modname
+ delim = '*'*len(t)
+ return '\n'.join([delim, t, delim, '', ''])
+
+def automodule(modname):
+ return '\n'.join([
+ '.. automodule:: %s' % modname,
+ ' :members:',
+ ' :undoc-members:',
+ '', ''])
+
+def toctree(children):
+ if len(children) == 0:
+ return ''
+ return '\n'.join([
+ '.. toctree::',
+ ' :maxdepth: 2',
+ '',
+ ] + [
+ ' %s.txt' % c for c in sorted(children)
+ ] + ['', ''])
+
+def make_module_txt(modname, children):
+ filename = os.path.join('hooke', '%s.txt' % modname)
+ if not os.path.exists('hooke'):
+ os.mkdir('hooke')
+ if os.path.exists(filename):
+ return None # don't overwrite potentially hand-written files.
+ f = file(filename, 'w')
+ f.write(title(modname))
+ f.write(automodule(modname))
+ f.write(toctree(children))
+ f.close()
+
+
+
+class Tree(list):
+ """A traversable tree structure.
+
+ Examples
+ --------
+
+ Construct::
+
+ +-b---d-g
+ a-+ +-e
+ +-c-+-f-h-i
+
+ with
+
+ >>> i = Tree(); i.n = "i"
+ >>> h = Tree([i]); h.n = "h"
+ >>> f = Tree([h]); f.n = "f"
+ >>> e = Tree(); e.n = "e"
+ >>> c = Tree([f,e]); c.n = "c"
+ >>> g = Tree(); g.n = "g"
+ >>> d = Tree([g]); d.n = "d"
+ >>> b = Tree([d]); b.n = "b"
+ >>> a = Tree(); a.n = "a"
+ >>> a.append(c)
+ >>> a.append(b)
+
+ Get the longest branch length with
+
+ >>> a.branch_len()
+ 5
+
+ Sort the tree recursively. Here we sort longest branch length
+ first.
+
+ >>> a.sort(key=lambda node : -node.branch_len())
+ >>> "".join([node.n for node in a.traverse()])
+ 'acfhiebdg'
+
+ And here we sort shortest branch length first.
+
+ >>> a.sort(key=lambda node : node.branch_len())
+ >>> "".join([node.n for node in a.traverse()])
+ 'abdgcefhi'
+
+ We can also do breadth-first traverses.
+
+ >>> "".join([node.n for node in a.traverse(depth_first=False)])
+ 'abcdefghi'
+
+ Serialize the tree with depth marking branches.
+
+ >>> for depth,node in a.thread():
+ ... print "%*s" % (2*depth+1, node.n)
+ a
+ b
+ d
+ g
+ c
+ e
+ f
+ h
+ i
+
+ Flattening the thread disables depth increases except at
+ branch splits.
+
+ >>> for depth,node in a.thread(flatten=True):
+ ... print "%*s" % (2*depth+1, node.n)
+ a
+ b
+ d
+ g
+ c
+ e
+ f
+ h
+ i
+
+ We can also check if a node is contained in a tree.
+
+ >>> a.has_descendant(g)
+ True
+ >>> c.has_descendant(g)
+ False
+ >>> a.has_descendant(a)
+ False
+ >>> a.has_descendant(a, match_self=True)
+ True
+ """
+ def __cmp__(self, other):
+ return cmp(id(self), id(other))
+
+ def __eq__(self, other):
+ return self.__cmp__(other) == 0
+
+ def __ne__(self, other):
+ return self.__cmp__(other) != 0
+
+ def branch_len(self):
+ """Return the largest number of nodes from root to leaf (inclusive).
+
+ For the tree::
+
+ +-b---d-g
+ a-+ +-e
+ +-c-+-f-h-i
+
+ this method returns 5.
+
+ Notes
+ -----
+ Exhaustive search every time == *slow*.
+
+ Use only on small trees, or reimplement by overriding
+ child-addition methods to allow accurate caching.
+ """
+ if len(self) == 0:
+ return 1
+ else:
+ return 1 + max([child.branch_len() for child in self])
+
+ def sort(self, *args, **kwargs):
+ """Sort the tree recursively.
+
+ This method extends :meth:`list.sort` to Trees.
+
+ Notes
+ -----
+ This method can be slow, e.g. on a :meth:`branch_len` sort,
+ since a node at depth `N` from the root has it's
+ :meth:`branch_len` method called `N` times.
+ """
+ list.sort(self, *args, **kwargs)
+ for child in self:
+ child.sort(*args, **kwargs)
+
+ def traverse(self, depth_first=True):
+ """Generate all the nodes in a tree, starting with the root node.
+
+ Parameters
+ ----------
+ depth_first : bool
+ Depth first by default, but you can set `depth_first` to
+ `False` for breadth first ordering. Siblings are returned
+ in the order they are stored, so you might want to
+ :meth:`sort` your tree first.
+ """
+ if depth_first == True:
+ yield self
+ for child in self:
+ for descendant in child.traverse():
+ yield descendant
+ else: # breadth first, Wikipedia algorithm
+ # http://en.wikipedia.org/wiki/Breadth-first_search
+ queue = [self]
+ while len(queue) > 0:
+ node = queue.pop(0)
+ yield node
+ queue.extend(node)
+
+ def thread(self, flatten=False):
+ """Generate a (depth, node) tuple for every node in the tree.
+
+ When `flatten` is `False`, the depth of any node is one
+ greater than the depth of its parent. That way the
+ inheritance is explicit, but you can end up with highly
+ indented threads.
+
+ When `flatten` is `True`, the depth of any node is only
+ greater than the depth of its parent when there is a branch,
+ and the node is not the last child. This can lead to ancestry
+ ambiguity, but keeps the total indentation down. For example::
+
+ +-b +-b-c
+ a-+-c and a-+
+ +-d-e-f +-d-e-f
+
+ would both produce (after sorting by :meth:`branch_len`)::
+
+ (0, a)
+ (1, b)
+ (1, c)
+ (0, d)
+ (0, e)
+ (0, f)
+
+ """
+ stack = [] # ancestry of the current node
+ if flatten == True:
+ depthDict = {}
+
+ for node in self.traverse(depth_first=True):
+ while len(stack) > 0 \
+ and id(node) not in [id(c) for c in stack[-1]]:
+ stack.pop(-1)
+ if flatten == False:
+ depth = len(stack)
+ else:
+ if len(stack) == 0:
+ depth = 0
+ else:
+ parent = stack[-1]
+ depth = depthDict[id(parent)]
+ if len(parent) > 1 and node != parent[-1]:
+ depth += 1
+ depthDict[id(node)] = depth
+ yield (depth,node)
+ stack.append(node)
+
+ def has_descendant(self, descendant, depth_first=True, match_self=False):
+ """Check if a node is contained in a tree.
+
+ Parameters
+ ----------
+ descendant : Tree
+ The potential descendant.
+ depth_first : bool
+ The search order. Set this if you feel depth/breadth would
+ be a faster search.
+ match_self : bool
+ Set to `True` for::
+
+ x.has_descendant(x, match_self=True) -> True
+ """
+ if descendant == self:
+ return match_self
+ for d in self.traverse(depth_first):
+ if descendant == d:
+ return True
+ return False
+
+
+def python_tree(root_path='hooke', root_modname='hooke'):
+ tree = Tree()
+ tree.path = root_path
+ tree.parent = None
+ stack = [tree]
+ while len(stack) > 0:
+ f = stack.pop(0)
+ if f.path.endswith('.py'):
+ f.name = os.path.basename(f.path)[:-len('.py')]
+ elif os.path.isdir(f.path) \
+ and os.path.exists(os.path.join(f.path, '__init__.py')):
+ f.name = os.path.basename(f.path)
+ f.is_module = True
+ for child in os.listdir(f.path):
+ if child == '__init__.py':
+ continue
+ c = Tree()
+ c.path = os.path.join(f.path, child)
+ c.parent = f
+ stack.append(c)
+ else:
+ continue
+ if f.parent == None:
+ f.modname = root_modname
+ else:
+ f.modname = f.parent.modname + '.' + f.name
+ f.parent.append(f)
+ return tree
+
+if __name__ == '__main__':
+ pt = python_tree(root_path='../hooke', root_modname='hooke')
+ for node in pt.traverse():
+ make_module_txt(node.modname, [c.modname for c in node])
--- /dev/null
+*************
+Hacking Hooke
+*************
+
+
+Architecture
+============
+
+To clean up the internals, were going to go crazy on the
+object-oriented front, and try to keep the core functionality free of
+any dependencies other than the `Python Standard Library`_ and `Numpy`_
+/ `Scipy`_.
+
+.. _Python Standard Library: http://docs.python.org/library/
+.. _Numpy: http://numpy.scipy.org/
+.. _Scipy: http://www.scipy.org/
+
+To make a responsive user interface in parallel with data processing
+and possible GUIs, we'll use Python's multiprocessing_ and queue_
+modules. These modules are both new in Python 2.6, but 2.6 usage is
+becoming fairly widespread. Certainly more widespread than any
+alternative queue module that I know of. Since we're leveraging the
+power of the standard library, we use configparser_ for the config
+files.
+
+.. _multiprocessing: http://docs.python.org/dev/library/multiprocessing.html
+.. _queue: http://docs.python.org/library/queue.html
+.. _configparser: http://docs.python.org/library/configparser.html
+
+On the testing side, the need to stick to the standard library relaxes
+(developers can install extra packages), so we can use nose_. See
+the `Testing`_ section for more information.
+
+.. _Testing: testing.txt
--- /dev/null
+Welcome to the Hooke documentation!
+===================================
+
+Hooke_ is software for the (semiautomatic) analysis and filtering of
+force curves. Force curves are the output of an analytical technique
+called `force spectroscopy`_. Force spectroscopy experiments usually
+require the analysis of thousands of force curves at a time. As of
+today, there is no standard, free software for the analysis of force
+curves. Hooke aims to solve that.
+
+.. _Hooke: http://code.google.com/p/hooke/
+.. _force spectroscopy: http://en.wikipedia.org/wiki/Force_spectroscopy
+
+Features:
+
+* View, annotate, and measure force curves
+* Worm-like chain and freely-jointed chain fits of force peaks
+* Automatic convolution-based filtering of empty curves
+* Automatic fit and measurement of multiple force peaks
+* Handles force-clamp force experiments (experimental)
+* Extensible by users by mean of plugins and drivers
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ install.txt
+ tutorial.txt
+ hacking.txt
+ hooke/hooke.txt
+ doc.txt
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+Publications
+============
+
+Hooke has been published [1]. Please cite Hooke if you use it. Let us
+know, and we'll link to your paper!
+
+
+[1] Sandal M, Benedetti F, Brucale M, Gomez-Casado A, Samorì B.,
+ "Hooke: an open software platform for force spectroscopy."
+ Bioinformatics, 2009.
+ doi: `10.1093/bioinformatics/btp180 <http://dx.doi.org/10.1093/bioinformatics/btp180>`_
+
+
+Troubleshooting
+===============
+
+If you have troubles in using Hooke:
+
+1. Search the `issue tracker`_.
+2. Look at the `trouble shooting wiki page`_.
+3. Search the `discussion group`_.
+3. Ask a question in the discussion group.
+4. File a bug on the issue tracker.
+
+.. _issue tracker: http://code.google.com/p/hooke/issues/list
+.. _trouble shooting wiki page:
+ http://code.google.com/p/hooke/wiki/TroubleShooting
+.. _discussion group: http://groups.google.com/group/hookesoftware
+
+
+Disclaimer
+==========
+
+Remember that Hooke is still experimental software! It has been mostly
+done to fit the needs of its authors, and there is no guarantee it
+will do what you need. However, you can write us/help us improve it so
+that it does. We aim to make of Hooke a little, universal tool that
+can help your research.
--- /dev/null
+****************
+Installing Hooke
+****************
+
+Dependencies
+============
+
+Hooke is routinely run successfully on Windows and Linux based
+systems. It is possible to run it happily on Mac OS X too (though
+install can be a bit trickier). Technically, Hooke should run wherever
+the Python_ programming language is installed.
+
+You'll need the following Python modules:
+
+* Numpy_
+* Scipy_
+* Matplotlib_ (for generating plots)
+* wxPython_ (for the GUI)
+
+.. Numpy: http://numpy.scipy.org/
+.. Scipy: http://www.scipy.org/
+.. Python: http://www.python.org/
+.. Matplotlib: http://matplotlib.sourceforge.net/
+.. wxPython: http://www.wxpython.org/
+
+Getting the source
+==================
+
+Hooke_ is available as an Subversion_ repository::
+
+ $ svn checkout http://hooke.googlecode.com/svn/trunk/ hooke
+
+There is also a `GUI fork`_ (Rolf Schmidt)::
+
+ $ svn checkout http://hooke.googlecode.com/svn/trunk/ hooke
+
+And a `fork`_ versioned in Git_ (W. Trevor King)::
+
+ $ git clone http://www.physics.drexel.edu/~wking/code/git/hooke.git/ hooke
+
+There are also periodic bundled releases. See the homepage for each
+fork for details. For example, get the most recent snapshot of
+Trevor's fork in zip form with::
+
+ $ wget -o hooke.zip http://www.physics.drexel.edu/~wking/code/git/git.php?p=hooke.git&dl=zip&h=HEAD
+ $ unzip hooke.zip
+
+.. _Hooke: http://code.google.com/p/hooke/
+.. _GUI fork: http://code.google.com/p/hooke/wiki/HookeGUI
+.. _fork: http://www.physics.drexel.edu/~wking/code/git/git.php?p=hooke.git
+.. _Subversion: http://subversion.tigris.org/
+.. _Git: http://git-scm.com/
+
+
+Installation
+============
+
+Run::
+
+ $ python setup.py install
+
+to install Hooke. Run::
+
+ $ python setup.py install --help
+
+to see a list of installation options you may want to configure.
+
+Running Hooke from the source directory
+=======================================
+
+If you like, you can avoid installation by running Hooke directly from
+it's source directory::
+
+ $ wget -o hooke.zip http://www.physics.drexel.edu/~wking/code/git/git.php?p=hooke.git&dl=zip&h=HEAD
+ $ unzip hooke.zip
+ $ cd hooke
+ $ python bin/hooke
--- /dev/null
+*************
+Testing Hooke
+*************
+
+Hooke's test framework is build using doctest_, unittest_, and nose_.
+``nosetests`` (from the ``nose`` package) scans through the source
+tree, searching out the various tests and running them. If you aren't
+familiar with ``nose``, there is excellent documentation on its home
+page. We use ``nose`` because its auto-discovery allows us to avoid
+collecting all of our assorted tests into ``unittest.TestSuite``\s and
+running them by hand.
+
+To run the test suite from the Hooke installation directory, just use::
+
+ nosetests --with-doctest --doctest-tests
+
+.. _doctest: http://docs.python.org/library/doctest.html
+.. _unittest: http://docs.python.org/library/unittest.html
+.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.3/
+
+
+Adding tests to modules
+-----------------------
+
+Just go crazy with doctests and unittests; ``nose`` will find them.
--- /dev/null
+********
+Tutorial
+********
+
+`A short video showing Hooke in action`_! (courtesy of Fabrizio
+Benedetti, EPFL, Lausanne)
+
+.. _A short video showing Hooke in action:
+ https://documents.epfl.ch/users/f/fb/fbenedet/www/hooke_short_demostration.ogv
+
+Introduction
+============
+
+This tutorial will focus on the command-line interface as the most
+powerful, and leave the GUI interface to another document.
+
+.. _command-line: `Command-line interface`_
+.. _GUI: gui.txt
+
+Installation
+============
+
+See the Installation_ page for details on downloading and installing
+Hooke.
+
+.. _Installation: install.txt
+
+
+Command-line interface
+======================
+
+Running the hooke shell
+-----------------------
+
+Hooke has a set of commands that depend on the loaded plugins_.
+To access these commands, you'll need to run the Hooke shell.::
+
+ $ hooke
+
+If you are running hooke from the source directory (see
+Installation_), the equivalent command is::
+
+ $ python bin/hooke
+
+You may need to give the full path for Python on Windows systems.
+
+As Hooke launches, you should see something like the following in your
+terminal::
+
+ Starting Hooke.
+ Imported plugin fit
+ Imported plugin procplots
+ Imported plugin flatfilts
+ Imported plugin generalclamp
+ Imported plugin generalvclamp
+ Imported plugin massanalysis
+ Imported plugin macro
+ Imported driver picoforce
+ Imported driver hemingclamp
+ Imported driver csvdriver
+ Imported driver tutorialdriver
+
+ Warning: Invalid work directory.
+ This is Hooke, version 0.8.0 Seinei
+ (c) Massimo Sandal, 2006. Released under the GNU General Public License Version 2
+ Hooke is Free software.
+ ----
+ hooke>
+
+The final line, ``hooke>``, is the Hooke prompt. It allows you to
+enter commans to interact with the interpreter.
+
+Help
+----
+
+All commands have help text explaining their purpose and usage. The
+text is stored in the code itself, and therefore more likely to be up
+to date than this tutorial. You can get a list of commands and topics
+with::
+
+ hooke> help
+
+Or see specific help on ``TOPIC`` with::
+
+ hooke> help TOPIC
+
+for example::
+
+ hooke> help current
+
+will give help on the ``current`` command.
+
+Creating a playlist
+-------------------
+
+To start analyzing your curves, you first have to build a playlist. The
+playlist is just an index of the force curve files you want to
+analyze. Imagine it as a music playlist (that’s why it is called a
+playlist), but with data files instead of audio files.
+
+Suppose you have 100 PicoForce curve files in your curves directory,
+starting from ``mycurve.000`` and ending in ``mycurve.100`` and you
+want to analyze them all.
+
+You then can ``cd`` (change directory) to the directory::
+
+ hooke> cd c:\curves
+
+Type ``pwd`` (print working directory) to check the directory is correct.::
+
+ hooke> pwd
+ c:\curves
+
+You can list the files in the directory using ``ls`` or ``dir`` (they’re
+synonyms).::
+
+ hooke> ls
+ [’mycurve.000’, ’mycurve.001’, ...
+ ]
+
+Now you are ready to generate the playlist. The command to use is
+``genlist``.::
+
+ hooke> genlist mycurve.*
+
+You can also generate a playlist containing all what you find in the
+directory by typing:
+
+ hooke> genlist c:\curves
+
+If you want to select what curves to see, based on the filename, you
+can use wildcards. For example::
+
+ hooke> genlist mycurve.05*
+
+will take only curves from mycurve.050 to mycurve.059.
+
+Note that by using ``genlist`` you just generate the playlist in the
+local session. To save your playlist to a file for future reuse,
+type::
+
+ hooke> savelist mylist
+
+In this example, the list will be saved in the file ``mylist.hkp``.
+Hooke will add the extension ``.hkp`` (Hooke playlist) to the playlist
+if you forget to. The ``.hkp`` file is an XML file you can read and
+edit with any text editor (i.e. Wordpad), if needed. If you want to
+load it, simply issue ``loadlist mylist.hkp`` or ``loadlist mylist``,
+Hooke will add ``.hkp`` if necessary.
+
+If, generating the playlist, you are including by chance a non-force
+curve file that Hooke cannot open, Hooke will print an error and
+continue on.
+
+Navigating the playlist
+-----------------------
+
+Now you can navigate through your playlist using the commands ``next``
+and ``previous`` or, their aliases ``n`` and ``p``. You don’t need to
+type ``n`` every time to run along a list of curves. If you press
+Return to an empty prompt, Hooke will repeat the last command you
+issued explicitly. You can also navigate through the command history
+by using the up and down arrows. From the last curve of your
+playlist, ``n`` will wrap around to the first curve. Analogously,
+issuing ``p`` at the first curve will jump to the last.
+
+You can also jump to a given curve::
+
+ hooke> jump c:\curves\mycurve.012
+
+where the path can be either an absolute path, or a path relative to
+the directory holding the playlist file.
+
+Taking notes
+------------
+
+You can take notes about the curves you are looking at. Just type
+``note`` followed by the text you want to append to that curve. Hooke
+will save the text in your current playlist and in an external log
+file. The output will look like this:
+
+Notes taken at Sun Sep 17 20:42:07 2006
+/home/cyclopia/work/tris/20060620a.041 | This is a note
+/home/cyclopia/work/tris/20060620a.207 | This is another note
+/home/cyclopia/work/tris/20060620a.286 | This is a third one
+
+The log file name can be configured_, but it defaults to hooke.log.
+
+.. _configured: config.txt
+
+Usually curves you annotated are useful later. You can copy the curves
+you annotated to a different directory by using the ``copylog``
+command.
+
+ hooke> copylog c:\nicecurves
+
+will copy all curves you have annotated to the c:\nicecurves
+directory. Make sure that the directory already exists before doing
+that. TODO: replace with::
+
+ hooke> copylist --log c:\curves\nice.hkp
+
+Exporting curves
+----------------
+
+You can export Hooke curves as images and as text columns. To export
+as images, issue the ``export`` command followed by the filename.
+Supported formats are PNG (raster) and EPS (Encapsulated Postscript,
+vectorial). The export format is determined by the filename
+extension, so ``export foo.png`` and ``export foo.eps`` will save
+PNG and EPS files respectively.
+
+To export as text, use the ``txt`` command, followed by the
+filename. The output is a text file containing columns (first two are
+X and Y of extension, second two are X and Y of retraction).
+
+TODO: multiple cycles? Solution: blank lines for "breaks", add option
+to extract specific sections using Python's slice notation.
+
+
+Interacting with the plot (no plots in command line mode...)
+-------------------------
+
+Measuring distances and forces
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can easily zoom in the plot by dragging a rectangle on it with the
+left mouse button. To zoom out, click the right mouse
+button. Sometimes by zooming in and out too much, you can lose the
+picture (this is probably a small bug in Matplotlib). Just type
+``plot`` at the command line and the curve will be refreshed.
+
+You can measure distances and forces directly in the plot. Just issue
+the command ``distance``. You will be asked to click two points.
+When you click a point, a blue dot should appear. When you click the
+second point, the distances (in nanometers and piconewtons) will
+appear on the command line. You can use ``delta`` if you prefer,
+which gives meaningful values for every kind of graph (not only force
+curves). If you want to know the coordinates of a single point, use
+``point``.
+
+Hooke automatically adjusts the position of the clicked point to the
+nearest point in the graph, so you will be always measuring distances
+and forces between points in the graph.
+
+The commands ``force`` and ``distance`` are present in the
+``generalvclamp`` plugin.
+
+Worm like chain and freely jointed chain fitting
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can measure by hand the parameters relative to a force peak using
+a worm-like chain fitting with the ``fit`` command. The command by
+default automatically finds the contact point, asks for two points
+delimiting the portion to fit, and performs a two-variable fit, with
+contour length, persistence length, and their relative errors as
+output. If desired, one can use the ``noauto`` option to manually
+click the contact point, and/or the ``pl=NUMBER`` options to impose a
+specific persistence or Kuhn length (in nanometers). You can choose
+which model to use with ``set fit_function wlc`` or ``set fit_function
+fjc``. See the help of the ``fit`` command from the Hooke
+command line for details.
+
+Multiple curve fitting and measuring
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can cycle through all your current playlist obtaining WLC fit, FJC
+fit, rupture force and slope (loading rate) information from each
+curve using the ``multifit`` command. The collected data can be saved
+in a text file for further analysis in your favourite spreadsheet or
+statistical program. If you want to check your parameters on the
+current curve before fitting all the files in your playlist, use
+``multifit justone``. See the ``multifit`` help for more options.
+
+Fast curve reviewing and saving
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When automatic routines are not good enough to filter your data, use
+``review`` command to cycle through your playlist presenting ten
+curves in the same graph. You can then enter the numbers of the
+interesting curves and automatically save a copy of them into another
+directory.
+
+Configuring Hooke
+-----------------
+
+You can set environment variables to influence the behaviour of
+Hooke. The command to use is ``set``.
+
+You can alter permanently the behaviour of Hooke by setting these
+variables in a Hooke configuration file. See the `Configuring Hooke`_
+section for details.
+
+.. _Configuring Hooke: config.txt
+"""The hooke module does all the legwork for Hooke_ (BE).
+
+.. _hooke: http://code.google.com/p/hooke/
+
+To facilitate faster loading, submodules are not imported by default.
+The available submodules are:
+
+* :mod:`hooke.config`
+* :mod:`hooke.compat`
+"""
+
+__version__ = (0, 9, 0, 'devel', None, 'Kenzo')
+"""Version tuple::
+
+ (major, minor, release, type, patch, name)
+
+Where
+
+ * type: Python uses alpha, beta, candidate, and final. Whatever
+ so long as the alphabetic sort gets them in the right order.
+ * patch: either manually incremented for each release, the packaging
+ date string, YYYYMMDD, date of last commit, whatever.
+
+See `Greg Noel's post on scons-devel`_ for a good explaination of why this
+versioning scheme is a good idea.
+
+.. _Greg Noel's post on scons-devel
+ http://thread.gmane.org/gmane.comp.programming.tools.scons.devel/8740
+"""
+
+def version(depth=-1, version_tuple=None):
+ """Return a nicely formatted version string.::
+
+ major.minor.release.type[.patch] (name)
+
+ Examples
+ --------
+
+ Since I seem to be unable to override __version__ in a Doctest,
+ we'll pass the version tuple in as an argument. You can ignore
+ ``version_tuple``.
+
+ >>> v = (1, 2, 3, 'devel', '20100501', 'Kenzo')
+
+ If depth -1, a full version string is returned
+
+ >>> version(depth=-1, version_tuple=v)
+ '1.2.3.devel.20100501 (Kenzo)'
+
+ Otherwise, only the first depth fields are used.
+
+ >>> version(depth=3, version_tuple=v)
+ '1.2.3'
+ >>> version(depth=4, version_tuple=v)
+ '1.2.3.devel'
+
+ Here's an example dropping the patch.
+
+ >>> v = (1, 2, 3, 'devel', None, 'Kenzo')
+ >>> version(depth=-1, version_tuple=v)
+ '1.2.3.devel (Kenzo)'
+ """
+ if version_tuple == None:
+ version_tuple = __version__
+ patch_index = 4
+ if version_tuple[patch_index] == None: # No patch field, drop that entry
+ version_tuple = version_tuple[0:patch_index] \
+ + version_tuple[patch_index+1:]
+ if depth >= patch_index:
+ depth -= 1
+ fields = version_tuple[0:depth]
+ string = '.'.join([str(x) for x in fields])
+ if depth == -1 or depth == len(version_tuple):
+ string += ' (%s)' % version_tuple[-1]
+ return string