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