13 To clean up the internals, were going to go crazy on the
14 object-oriented front, and try to keep the core functionality free of
15 any dependencies other than the `Python Standard Library`_, Numpy_,
18 .. _Python Standard Library: http://docs.python.org/library/
19 .. _Numpy: http://numpy.scipy.org/
20 .. _Scipy: http://www.scipy.org/
21 .. _PyYAML: http://pyyaml.org/
23 To make a responsive user interface in parallel with data processing
24 and possible GUIs, we'll use Python's multiprocessing_ module. This
25 module is new in Python 2.6, but 2.6 usage is becoming fairly
26 widespread. Certainly more widespread than any alternative queue
27 module that I know of. Since we're leveraging the power of the
28 standard library, we use configparser_ for the config files.
30 .. _multiprocessing: http://docs.python.org/dev/library/multiprocessing.html
31 .. _configparser: http://docs.python.org/library/configparser.html
33 On the testing side, the need to stick to the standard library relaxes
34 (developers can install extra packages), so we can use nose_. See
35 the :doc:`testing` section for more information.
37 .. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.3/
43 Hooke aims to be easily modified and extended by new recruits. To
44 make this easier, we try to abide by several programming practices.
46 * `DRY`_ (Don't Repeat Yourself), also phrased as "Every piece of
47 knowledge must have a single, unambiguous, authoritative
48 representation within a system."
49 * `LoD`_ (Law of Demeter): Don't reach through layers, e.g. `a.b.c.d()`.
51 .. _DRY: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
52 .. _LoD: http://en.wikipedia.org/wiki/Law_of_Demeter
58 Hooke's main entry point is :class:`~hooke.hooke.Hooke`.
59 :class:`~hooke.hooke.Hooke` reads in the configuration files and loads
60 Plugins_ and Drivers_. Then it forks off a
61 :class:`~hooke.engine.CommandEngine` instance to execute Commands_,
62 and a :class:`~hooke.ui.UserInterface` instance to connect the
63 :class:`~hooke.engine.CommandEngine` with the user. The
64 :class:`~hooke.engine.CommandEngine` runs in a subprocess, which
65 allows command execution to occur in parallel with
66 :class:`~hooke.ui.UserInterface` interaction. The two processes
67 communicate via two :class:`multiprocessing.Queue`\s.
69 There are a number of special classes availiable to structure queue
70 communications. See :mod:`~hooke.interaction` and
71 :class:`~hooke.command.CommandExit` for details.
76 :class:`~hooke.plugin.Plugin`\s contain bundles of Commands_,
77 representing the various operations a user can carry out through the
80 :class:`~hooke.plugin.Plugin`\s can depend on other
81 :class:`~hooke.plugin.Plugin`\s, so you shouldn't need to repeat code.
82 One central :class:`~hooke.plugin.Plugin` can provide useful
83 functionality to several dependent :class:`~hooke.plugin.Plugin`\s.
85 There is a :class:`~hooke.plugin.Plugin` subtype
86 :class:`~hooke.plugin.Builtin` which is just like a
87 :class:`~hooke.plugin.Plugin`, but is considered fundamental enough to
88 not be optional. :class:`~hooke.plugin.Builtin`\s are always loaded.
93 :class:`~hooke.command.Command`\s specify user-actions in an
94 interface-agnostic manner. This makes writing
95 :class:`~hooke.ui.UserInterface`\s easier, because you don't need to
96 know anything about particular :class:`~hooke.plugin.Plugin`\s or
97 :class:`~hooke.command.Command`\s, you just need to be able to explain
98 the base classes for you user and then speak the language of
99 :mod:`~hooke.interaction` and :class:`~hooke.command.CommandExit` with
100 the :class:`~hooke.engine.CommandEngine` process.
105 :class:`~hooke.driver.Driver`\s are responsible for reading assorted
106 data files into Hooke's Data_ structure.
114 Force spectroscopy experiments come in several major flavors. Each
115 flavor gets its own subclass of :class:`~hooke.experiment.Experiment`
116 in :mod:`~hooke.experiment`. For example, force clamp experiments are
117 :class:`~hooke.experiment.ForceClamp`. This gives Drivers_ a way to
118 tag experimental data so Commands_ know what they are working with.
123 Experiments_ tags need a data-holding container to tag, and
124 :class:`~hooke.curve.Curve`\s are that container. Each
125 :class:`~hooke.curve.Curve` can hole several blocks of
126 :class:`~hooke.curve.Data` (for example approach and retract curves in
127 a :class:`~hooke.experiment.VelocityClamp` experiment would be
128 seperate blocks). :class:`~hooke.curve.Curve`\s also have an
129 :attr:`~hooke.curve.Curve.info` attribute for persistently storing
135 Normally you'll want to analyze multiple Curves_ in one session.
136 :class:`~hooke.playlist.Playlist`\s provide a convenient container for
137 Curves_, and the subclass :class:`~hooke.playlist.FilePlaylist` add
138 persistant file backing (save, load, etc.).
143 There are a number of general coding features we need for Hooke that
144 are not provided by Python's standard library. We factor those
145 features out into :mod:`~hooke.util`.
147 There are also a number of features who's standard library support
148 changes with different versions of Python. :mod:`~hooke.compat`
149 provides a uniform interface to those tools so that Hooke will work
150 with several Python versions.
155 The :class:`hooke.curve.Data` blocks store data in various states of
156 processing. For example, velocity clamp drivers will load two columns
157 of data: `z piezo (m)` and `deflection (m)` (all column names have the
158 `name (unit)` format, see :func:`~hooke.util.si.split_data_label`).
159 Most data processing consists of manipulating current block
160 information to create additional data columns in the same block. For
161 example, :class:`~hooke.plugin.vclamp.SurfaceContactCommand` usually
162 uses the `z piezo (m)` and `deflection (m)` columns to add
163 `surface distance (m)` and `surface adjusted deflection (m)` columns.
164 However, you might want to use e.g. `median filtered deflection (m)`
165 instead of `deflection (m)`. Because of this, analysis plugins should
166 use :class:`~hooke.command.Argument`\s rather than hard-coding source
167 or target column or info dict names. See
168 :class:`~hooke.plugin.vclamp.SurfaceContactCommand` for an example of
169 the recommended approach.
171 Also keep in mind that some analyses will not generate columns that
172 are the same size as the source data
173 (e.g. :class:`~hooke.plugin.flatfilt.FlatPeaksCommand` and
174 :class:`~hooke.plugin.curve.PowerSpectrumCommand`). These commands
175 will either stash information in the :class:`~hooke.curve.Data`'s
176 `.info` dictionary (e.g. a list of peaks) and/or add new
177 :class:`~hooke.curve.Data` blocks to the parent
178 :class:`~hooke.curve.Curve`. The main reason for adding new blocks
179 rather than storing all the data in `.info` is to take advantage of
180 built in :class:`~hooke.curve.Data` processing
181 :class:`~hooke.command.Command`\s. For example, the power spectrum
182 from :class:`~hooke.plugin.curve.PowerSpectrumCommand` can be easily
183 exported to a text file. However, extra care must be taken to avoid
184 name collisions or ambiguity, since the output blocks must be unique
185 on a :class:`~hooke.curve.Curve`-wide level, while `Data.info` output
186 need only be unique on a :class:`~hooke.curve.Data`-wide level.
191 :mod:`hooke.ui.gui` contains enough code that you might want a word
192 about its organization before diving into the code. Information flows
195 .. image:: img/gui_flow/gui_flow.svg
197 With the following naming scheme in HookeFrame:
199 =================== ==================
201 response processors ``_postprocess_*``
202 =================== ==================