Use minted for syntax highlighting in code excerpts (yay pygments!).
\newcommand{\diNaHPO}{Na\textsubscript{2}HPO\textsubscript{4}}
\newcommand{\NadiHPO}{NaH\textsubscript{2}PO\textsubscript{4}}
+% Workaround for inline minted markup
+% http://code.google.com/p/minted/issues/detail?id=15
+% usage: \imint{language}|value|
+\NewDocumentCommand\imint{mv}{\texttt{#2}}
+
% Aliases for citations
\defcitealias{calibcant}{calibcant}
\defcitealias{comedi}{Comedi}
+\defcitealias{cygwin}{Cygwin}
+\defcitealias{cython}{Cython}
+\defcitealias{epics}{EPICS}
\defcitealias{gentoo}{Gentoo}
+\defcitealias{h5config}{h5config}
+\defcitealias{hdf5}{HDF5}
\defcitealias{interix}{Interix}
\defcitealias{king10}{sawsim}
+\defcitealias{labview}{LabVIEW}
\defcitealias{prefix}{Gentoo Prefix}
\defcitealias{pyafm}{pyafm}
\defcitealias{pycomedi}{pycomedi}
+\defcitealias{pymodbus}{pymodbus}
\defcitealias{pymol}{PyMol}
+\defcitealias{pypid}{pypid}
\defcitealias{pypiezo}{pypiezo}
\defcitealias{sandal09}{Hooke}
\defcitealias{stepper}{stepper}
+\defcitealias{beazley96}{SWIG}
+\defcitealias{unfold-protein}{unfold-protein}
+\defcitealias{wavemetrics-igor}{IGOR Pro}
\defcitealias{xcode}{Xcode}
+\defcitealias{yaml}{YAML}
\newcommand{\Comedi}{\citetalias{comedi}}
\newcommand{\Hooke}{\citetalias{sandal09}}
\newcommand{\calibcant}{\citetalias{calibcant}}
+\newcommand{\hFconfig}{\citetalias{h5config}}
\newcommand{\pyafm}{\citetalias{pyafm}}
+\newcommand{\pypid}{\citetalias{pypid}}
+\newcommand{\pypiezo}{\citetalias{pypiezo}}
+\newcommand{\pycomedi}{\citetalias{pycomedi}}
\newcommand{\pysawsim}{\texttt{pysawsim}}
\newcommand{\sawsim}{\citetalias{king10}}
\newcommand{\stepper}{\citetalias{stepper}}
+\newcommand{\unfoldprotein}{\citetalias{unfold-protein}}
\bibliographystyle{unsrtnat} % Number citations in the order referenced.
+% use symbols for footnotes, so they aren't confused with references
+\usepackage[symbol*]{footmisc}
+
% Nicer references with \cref, \Cref, etc.
\usepackage[capitalize]{cleveref}
\usepackage{dsfont}
% nicer table formatting (\toprule, \cimidrule, \midrule, and \bottomrule)
\usepackage{booktabs}
+% syntax highlighting for source code
+\usepackage{minted}
+% for \NewDocumentCommand
+\usepackage{xparse}
\usepackage{xcolor}
\usepackage{tikz} % a nice, inline PGF frontend
\usetikzlibrary{automata} % graph-theory library
\usetikzlibrary{calc} % coordinate-calculation library
+\usetikzlibrary{shapes.misc} % for 'rounded rectangle'
\usepackage[inline]{asymptote} % more fancy graphics ;).
\usepackage{epsdice} % dice-face font
-% nicer verbatim environments (Verbatim)
-\usepackage{fancyvrb}
-
-\RecustomVerbatimEnvironment{Verbatim}{Verbatim}{%
- frame=lines,commandchars=\\\{\}}
-
\usepackage{wtk_cmmds} % common personal macros, in ~/texmf/tex/latex/
\input{local_cmmds}
note = "Version 0.7",
}
+@misc{ unfold-protein,
+ author = WKing,
+ title = {Unfold-protein},
+ year = 2013,
+}
+% url = {http://pypi.python.org/pypi/unfold-protein/},
+% note = "Version 0.2",
+
@misc{ pyafm,
author = WKing,
title = "Pyafm",
year = 2012,
note = "Version 0.4",
}
+
+@misc{ h5config,
+ author = WKing,
+ title = "H5config",
+ url = "http://pypi.python.org/pypi/h5config/",
+ year = 2013,
+ note = "Version 0.3",
+}
-\section{Auxilliary packages}
+\section{Auxiliary packages}
+\label{sec:pyafm:auxiliary}
+
+The previous section covered the core of the experiment stack
+(\cref{sec:pyafm:stack}), but skipped over some of the more peripheral
+packages.
+
\subsection{h5config}
+\label{sec:pyafm:h5config}
+
+The \hFconfig\ package makes it easy to save and load configuration
+classes from disk. After populating base configuration classes with
+parameters (\cref{fig:h5config}), \hFconfig\ automatically generates
+\citetalias{hdf5} and \citetalias{yaml} backends for saving and
+loading that class.
+
+\begin{figure}
+ \begin{center}
+\begin{minted}[mathescape]{python}
+import h5config.config as _config
+
+class AxisConfig (_config.Config):
+ "Configure a single piezo axis"
+ settings = [
+ _config.FloatSetting(
+ name='gain',
+ help=(
+ 'Volts applied at piezo per volt output from the DAQ card '
+ '(e.g. if your DAQ output is amplified before driving the '
+ 'piezo),')),
+ _config.FloatSetting(
+ name='sensitivity',
+ help='Meters of piezo deflection per volt applied to the piezo.'),
+ # $\ldots$
+ _config.ConfigSetting(
+ name='channel',
+ help='Configure the underlying DAC channel.',
+ config_class=OutputChannelConfig,
+ default=None),
+ # $\ldots$
+ ]
+\end{minted}
+ \caption{Portions of the configuration class for a single piezo
+ axis (from \pypiezo, \cref{sec:pyafm:pypiezo}). The more
+ generic analog output channel configuration is nested under the
+ \imint{python}|channel| setting.\label{fig:h5config}}
+ \end{center}
+\end{figure}
+
+Basic configuration types include booleans, integers, floating point
+numbers, enumerated choices, and freeform text. There is also support
+for lists of these basic types (e.g.~lists of integers). The killer
+feature is nesting configuration classes. This means that your higher
+level tools can have their own configuration settings and also include
+the configuration settings for their lower level components. For
+example, the piezo axis configuration given in \cref{fig:h5config}
+contains configuration settings specific to piezo axes, and it also
+contains a reference to the configuration settings for a generic
+analog output channel. The piezo axis code doesn't need to know what
+the analog output channel configuration settings are, those are
+defined somewhere else.
+
+The nesting continues all the way up the stack, to the
+\unfoldprotein\ configuration. This means that a single file
+(\imint{console}|~/.config/unfold_protein.yaml|) contains every
+configurable setting required for the whole experiment in an
+easy-to-edit text format. Adding additional configuration settings at
+any level of the experiment stack is just a matter of adjusting a
+single \imint{python}|h5config.config.Config| subclass the
+corresponding entry in the configuration file. There is no need to
+adjust the higher level code, the new setting is passed down the stack
+to its point of use automatically.
+
+Besides making it easy to configure your experiment, \hFconfig\ also
+makes it easy to save the configuration alongside your data. The
+section of \unfoldprotein\ that writes the whole configuration stack
+into the per-pull HDF5 file is only four lines long. This makes
+post-processing much easier, because almost every setting needed to
+analyze the data is already stored in the data file (the only missing
+values are those that you did not need during the experiment control
+phase).
+
\subsection{stepper}
+\label{sec:pyafm:stepper}
+
+The \stepper\ package provides Python control of stepper
+motors\cite{jones95}. The package is mostly concerned with the
+maintenance of internal motor state:
+
+\begin{description}
+ \item[position] is a half-step counter that records the current
+ motor position.
+ \item[full step] selects full or half stepping.
+ \item[logic] selects active high or active low operation.
+ \item[delay] sets the time delay between steps in seconds, in case
+ the motor response is slower than the digital output driver.
+ \item[step size] approximates step size in meters.
+ \item[backlash] estimates the drive chain backlash in half-steps.
+\end{description}
+
+Actualizing the motor control signal is left up to the caller, in this
+case \pyafm.
+
+TODO: backlash and step-size graphics.
+
\subsection{pypid}
+\label{sec:pyafm:pypid}
+
+The final component of the experiment control stack is \pypid, which
+uses \citetalias{pymodbus} to communicate with a Melcor Series MTCA
+Thermoelectric Cooler Controller\citep{melcor} over a serial line.
+The controller monitors the fluid cell temperature with a
+thermocouple, and reading temperatures from the controller is fairly
+straightforward (\cref{fig:unfold-protein:unfolder}). Temperature
+control is via a peltier mounted underneath the sample surface.
+
+The controller tries to keep the measured temperature at the setpoint
+temperature via a modified proportional-integral-derivative (PID)
+feedback algorithm. PID systems have been around for a
+while\citep{ziegler42}, but finding appropriate feedback terms for
+sensitive systems is not trivial. There are a number of tuning
+procedures which characterize the system by evaluating its response
+under simpler driving conditions. The \pypid\ package implements
+Ziegler--Nichols' step response\citep{ziegler42}, bang-bang
+response\citep{TODO}, ultimate cycle response\citep{ziegler42} tuning
+rules, as well as Cohen--Coon's\citep{cohen53} and
+Wang--Juang--Chan's\citep{wang95} step response tuning
+rules\citep{astrom93}.
+
+\nomenclature{PID}{Proportional-integral-derivative feedback. For a
+ process value $p$, setpoint $p_0$, and manipulated variable $m$, the
+ standard PID algorithm is
+ \begin{align}
+ m(t) &= K_p e(t) + K_i \integral{0}{t}{\tau}{e(\tau)}
+ + K_d \deriv{t}{e(t)} \\
+ e(t) &= p_0 - p \;,
+ \end{align}
+ where $e$ is the error function, $K_p$ is the proportional gain,
+ $K_i$ is the integral gain, and $K_d$ is the derivative gain.}
\section{Conclusions}
+\label{sec:pyafm:conclusions}
+
+Developing an open software stack for controlling single molecule
+force spectroscopy is hard work, especially for scientists who lack
+experience designing or managing moderately large software projects.
+Coming into this project, I already had several years of experience
+working with LabVIEW, but I had very little experience in other
+languages and no formal training in project maintenance. I spent the
+first two years of my research project floundering about until I
+aquired enough experience to start making progress on a sustainable
+stack\footnote{%
+ Since last summer I've been helping the
+ \href{http://software-carpentry.org/}{Software Carpentry}
+ project\citep{wilson06b} reach out to scientists (mostly graduate
+ students) to provide boot camp introductions to software development
+ and version control. It's a chance to tell other folks what I wish
+ I'd been told when I was starting out.
+}, and I've spent the remaining time tuning this stack (and the
+analysis software) while running experiments.
+
+A FLOSS stack allows collaborative development so that this
+development cost can be shared between labs, as well as lowering the
+barrier to entry for new labs entering the field. Besides benefiting
+SMFS groups, lower-level packages in the stack will be useful to a
+wider audience (who can share the maintenance cost). My existing
+stack and future distributed maintenance will allow researchers to
+focus on generating new science, instead of generating new software.
+
+Besides development efficiencies, a common stack could provide a
+benchmark for comparative analysis between experiments carried out by
+different labs. With every lab using in-house software and in-house
+hardware, it's hard to judge the reliability or accuracy of the lab's
+published research. A common stack should include methods like those
+used in \cref{sec:pyafm:discussion} to characterize and validate your
+apparatus. A common stack also provides a common file format for
+experimental data, which makes it easier to share data and analysis
+tools.
\section{Discussion}
+\label{sec:pyafm:discussion}
+
+With the radical shift from LabVIEW and Microsoft Windows over to
+Comedi and Linux, it is a good idea to compare my new experiment
+control software with the earlier stack. Because the fundamental
+procedure in my experiments is the velocity-clamp pull
+(\cref{sec:procedure}), I used both approaches in quick succession to
+collect pulls. Because the stacks diverge after the PCI DAQ card, I
+was able to collect several pulls using my setup, power down the Linux
+computer, swap the PCI card into the Windows computer, power up, and
+collect several pulls using the Windows stack on top of the exact same
+hardware.
+
+\begin{figure}
+ \begin{center}
+ \subfloat[][]{\label{fig:pyafm:labview-comparison:many}
+ \includegraphics[width=0.9\textwidth]{%
+ figures/labview-comparison/full}}
+ \caption{\protect\subref{fig:pyafm:labview-comparison:many}Several
+ velocity clamp pulls using both the LabVIEW/Windows stack (blue)
+ and the Comedi/Linux stack (red). The contact voltage and
+ pulling distance were not synchronized between the two
+ experiments, and the raw data has been shifted to locate the
+ contact point at the origin. One LabVIEW/Windows curve has a
+ flat deflection in the high-contact region, where the laser was
+ deflected beyond the photodiode's working range. This is
+ probably due to a high approach setpoint, followed by surface
+ drift during the binding phase, but is not relevant to the
+ stack comparison.\label{fig:pyafm:labview-comparison}}
+ \end{center}
+\end{figure}
+
+\begin{figure}
+ \ContinuedFloat
+ \begin{center}
+ \subfloat[][]{\label{fig:pyafm:labview-comparison:single:contact}
+ \includegraphics[width=0.9\textwidth]{%
+ figures/labview-comparison/single-contact}} \\
+ \caption{\protect\subref{fig:pyafm:labview-comparison:single:contact}The
+ contact region from a single pull from
+ \protect\subref{fig:pyafm:labview-comparison:many}. The
+ LabVIEW/Windows stack takes $0.5\U{nm}$ piezo steps with ten
+ deflection reads at each step. The Comedi/Linux stack makes a
+ single read per step, but can as many small steps as possible
+ within DAQ card's memory buffer, frequency, and precision
+ limitations. For $1\U{$\mu$m/s}$ pulls, a stepping/sampling
+ frequency of $50\U{kHz}$ generated steps that were less than one
+ DAC bit wide.}
+ \end{center}
+\end{figure}
+
+\begin{figure}
+ \ContinuedFloat
+ \begin{center}
+ \subfloat[][]{\label{fig:pyafm:labview-comparison:single:non-contact}
+ \includegraphics[width=0.9\textwidth]{%
+ figures/labview-comparison/single-non-contact}}
+ \caption{\protect\subref{fig:pyafm:labview-comparison:single:non-contact}The
+ non-contact region from a single pull from
+ \protect\subref{fig:pyafm:labview-comparison:many}. The signal
+ oscillates because the AFM is sitting directly on the lab bench,
+ our usual isolation mechanisms being unavailable at the time.
+ All protein unfolding experiments were carried out with
+ isolation, so the vibration was not a problem in those cases.}
+ \end{center}
+\end{figure}
+
+Because the goal of these experiments was to compare the two software
+stacks, the comparison was carried out using our standard AFM
+cantilevers and gold surface, but distilled water was used instead of
+PBS and no protein was bound to the surface. This gives a simpler
+system with fewer distracting features. As shown in
+\cref{fig:pyafm:labview-comparison,fig:pyafm:labview-comparison:stats},
+large-scale features are identical, with similar contact slopes and
+non-contact noise.
+
+\begin{figure}
+ \begin{center}
+ \subfloat[][]{\label{fig:pyafm:labview-comparison:contact-slope}
+ \includegraphics[width=0.5\textwidth]{%
+ figures/labview-comparison/contact-slope}}
+ \subfloat[][]{\label{fig:pyafm:labview-comparison:non-contact-noise}
+ \includegraphics[width=0.9\textwidth]{%
+ figures/labview-comparison/non-contact-noise}} \\
+ \caption{\protect\subref{fig:pyafm:labview-comparison:contact-slope}Contact
+ slope for the pull in \cref{fig:pyafm:labview-comparison}. The
+ low-slope outlier is from the pull with out-of-range
+ deflection.
+ \protect\subref{fig:pyafm:labview-comparison:non-contact-noise}Power
+ spectral densities (PSDs) of the non-contact noise for the pulls
+ from \ref{fig:pyafm:labview-comparison:many}. To produce this
+ image, the PSD of the non-contact data extracted from
+ \ref{fig:pyafm:labview-comparison:many} was averaged for each
+ software stack. The number of points in the non-contact region
+ truncated to the nearest power of two (for efficient fast
+ Fourier transformation), which has the convenient side effect of
+ aligning the frequency axis for easy cross-pull
+ averaging.\label{fig:pyafm:labview-comparison:stats}}
+ \end{center}
+\end{figure}
+
+Although grossly similar, the two stacks do have some statistically
+significant differences. The slope of the contact region for the
+LabVIEW/Windows stack (excluding the out-of-deflection-range outlier)
+is $6.59\pm0.13$, while the Comedi/Linux stack slope is $6.17\pm0.03$
+(both in deflection bits per $z$-piezo bit,
+\cref{fig:pyafm:labview-comparison:contact-slope}). While small, the
+7\% difference is significant, both statistically ($3\sigma$ for the
+LabVIEW/Windows standard deviation) and practically, because contact
+slope plays a key role in cantilever calibration
+(\cref{sec:calibcant:bump}).
+
+Due to the table vibration, comparisons of non-contact noise between
+the two stacks are less conclusive. However, rough comparisons of the
+noise spectra show that noise in the Comedi/Linux data is generally a
+factor of two two three less than noise in the LabVIEW/Windows data
+across a range of frequencies
+(\cref{fig:fig:pyafm:labview-comparison:non-contact-noise}). While
+the noise difference should be taken with a grain of salt, it does
+highlight the importance (and difficulty) of characterizing your
+apparatus and controlling software.
\section{Analog input output frameworks}
+\label{sec:aio-frameworks}
+
+For many users, computers are fairly self-contained systems. Users
+read and write files, using a variety of editors, and share
+information between computers via networked connections. Using
+computers to control and monitor arbitrary physical processes is
+common in the scientific community and industry, but less so in the
+the general consumer market. This means that interfaces between the
+digital and analog worlds haven't seen the focused development in the
+FLOSS community that more mainstream problem areas have received. In
+this section I'll discuss a few possible options---both open and
+proprietary---in the context of my experiment control stack.
+
\subsection{LabVIEW}
+\label{sec:labview}
+
+National Instruments\citep{national-instruments} is a major player in
+the experiment control and data aquisition market. On the hardware
+side, they produce a wide range of DAQ cards. On the software side,
+they produce LabVIEW\citep{labview}, a graphical programming language
+designed to make writing control and aquisition experiments
+straightforward. Both LabVIEW and NI-DAQ cards are ubiquitous in
+scientific computing; in the four research labs I've worked in over my
+career, every lab has used both. By the time I joined Prof.~Yang's
+lab, I'd been using LabVIEW for years, and had become familiar with
+its two major limitations: name based linking and a binary file
+format.
+
+\nomenclature{DAQ}{Data acquisition. Although the term only refers to
+ input, it is sometimes implicitly extended to include signal output
+ as well (for controlling experiments as well as measuring results).}
+
+Programming in a graphical language is quite similar to programming in
+a textual language. In both, you reduce complexity by encapsulating
+functional subroutines of your process, and then assembling those
+subroutines in other, higher-level
+subroutines\citep{dijkstra70,wirth74,shneiderman79,hughes89}. This
+means that the application level code can focus on application-level
+task (approach the surface, wait for binding, \ldots) without getting
+bogged down in the details (increment analog output channel zero in 5
+bit steps until analog input channel exceeds 39322 bits). In textual
+languages like C or Python, you can use functions and libraries to
+package the functional subroutines. In LabVIEW, you package the
+subroutines in \emph{virtual instruments} (VIs).
+
+\nomenclature{VI}{Virtual instrument. LabVIEW's analog to functions
+ for encapsulating subroutines.}
+
+The problem comes when you want to update one of your subroutines.
+LabVIEW VIs are linked dynamically by VI name\citep{ni-vi-management},
+so there was no easy way to swap a new version of the VI into your
+application for testing without renaming the subroutine. With the
+Project Explorer (new in LabVIEW 8.0\citep{ni-vi-management}, released
+2005), these renames became easier. However, throughout my time in
+the Yang lab, the Windows machines all ran LabVIEW 7.1 (released in
+2004).
+
+Because of difficulties with name-based VI linking and the relative
+inexperience of many scientists in the maintenance benefits of modular
+programming\citep{hilburn93,wilson06b}, LabVIEW code often ends up
+without a clean separation between high-level and low-level tasks
+(\cref{fig:labview}). This lack of structure makes it difficult to
+reuse existing code to address similar tasks.
+
+\begin{figure}
+ \begin{center}
+ \includegraphics[width=0.8\textwidth]{%
+ figures/binary/pulling_chan_1_2d22.png}
+ \caption{An excerpt from the main frame of the LabVIEW stack.
+ This frame codes for the velocity-clamped pull phase of a
+ push--bind--pull experiment.\label{fig:labview}}
+ \end{center}
+\end{figure}
+
+The second obstacle to maintaining LabVIEW code is the binary file
+format for VIs. The established method for recording software history
+is to use a version control system (VCS), which recording versions of
+the project in a repository. Each change to the project is committed
+to the repository with some associated metadata (timestamp, committer
+name, explanatory message, \ldots). Users can access this database to
+recover earlier versions of the project. For example, if you find a
+bug in your package, you can use your VCS to determine if that bug
+affected the data you gathered six months ago.
+
+There are a number of FLOSS version control systems in common use
+(Git, Mercurial, and Subversion, \dots), but in order to track and
+merge \emph{changes}, they need a way to calculate the difference
+between two versions of a given file. For textual programming
+languages, the line-based textual differences used by VCSs work
+extremely well, but for binary file formats, performance decreases
+drastically. There are third-party merge tools\citep{ni-merge} for
+LabVIEW, but the tools are not officially supported.
+
+\nomenclature{VCS}{Version control system. A system for tracking
+ project development by recording versions of the project in a
+ repository.}
+\nomenclature{FLOSS}{Free, Libre, and Open Source (software). A
+ catch-all for copyleft licensing.}
+
+While National Instruments seems to put a reasonable amount of effort
+into maintaining backwards compatibility, long term archival of binary
+formats is still a difficult problem. For example, our legacy LabVIEW
+7.1 installation is no longer compatible with recent LabVIEW releases.
+Support for the releases is so low, that without access to the old
+LabVIEW release, you may not even be able to determine which version
+of LabVIEW your VI corresponds to. One officially suggested method
+for extracting the version from an older VI is\citep{ni-vi-version}:
+
+\begin{quote}
+ Open the VI in the earliest version on your computer. If an error
+ occurs, the VI is saved in a later version. Close the VI and repeat
+ this process for the next version of LabVIEW. The first version
+ that opens a VI without any error is the version in which the VI is
+ compiled.
+\end{quote}
+
+This does not inspire confidence in an ability to extract experiment
+control software from VIs after a decade of archival.
+
+\subsection{NI-DAQmx}
+\label{sec:ni-daqmx}
+
+After deciding to avoid LabVIEW, my first attempt at writing an
+experiment control framework involved calling National Instrument's
+DAQmx library from C\citep{ni-daqmx} (\cref{fig:ni-daqmx}). I spent
+most of 2007 working this framework, using \citetalias{cygwin} as the
+development environment. Inspired by \citetalias{epics}, I built a
+message passing server with experiment control and hardware interface
+modules connected via sockets.
+
+As the experiment server evolved, I started running into problems.
+The overhead of sending all the data through sockets to generic
+hardware interface modules was larger than I had na\"ively expected.
+I also had trouble with multithreaded socket code on Cygwin, and
+decided to scrap Microsoft Windows altogether in favor of a FLOSS
+operating system.
+
+\begin{figure}
+ \begin{center}
+\begin{minted}{c}
+static int set_digital_output_data(DIGITAL_OUTPUT *d, unsigned int data)
+{
+ d->data = (uInt32) data;
+ DAQmxErrChk_struct( Write_WriteDigPort(d->taskHandle, d->data) );
+ Error:
+ if (d->error != 0) {
+ CHK( close_digital_output(d) );
+ M_EXIT(FAILURE, "Error in NIDAQ stepper output\n");
+ }
+ CHK( nsleep(100) );
+ PING(1);
+ return SUCCESS;
+}
+\end{minted}
+ \caption{An excerpt from the digital output module of my
+ experiment server stack. Most of the C code is error checking
+ and tracing macros. The hardcoded delay time and
+ stepper-specific error message are symptoms of my previously
+ poor programming practices. \imint{c}|Write_WriteDigPort| is a
+ simplifying wrapper around \imint{c}|DAQmxWriteDigitalU32| from
+ the examples bundled with NI-DAQmx.\label{fig:ni-daqmx}}
+ \end{center}
+\end{figure}
+
\subsection{Comedi}
+\label{sec:comedi}
+
+After transitioning to Linux-based systems, I could no longer use
+NI-DAQmx (which only supported Microsoft Windows). Luckily, the
+\citetalias{comedi} project already provided FLOSS driver code for our
+DAQ card (an NI-PCI-6052E). Comedi (from ``Control and Measurement
+Device Interface'') is general purpose library for interacting with
+DAQ devices, and supports a wide range of hardware. When I moved to
+Comedi, it was a stand-alone kernel module, but since November 2008 it
+has been included in the Linux source as a staging driver.
+
+Comedi development goes back to 2000, so by the time I arrived things
+were already pretty stable. I submitted
+\href{http://comedi.org/git?p=comedi/comedi.git;a=commit;h=4284c2266987ad08a26f2758cd09fef06d1ce3cf}{a
+ small patch} to support simultaneous analog input/output triggering
+on National Instruments cards, and started building my stack.
--- /dev/null
+@string{DBeazley = "Beazley, David M."}
+@string{DWJones = "Jones, Douglas W."}
+@string{HDFG = "The HDF Group"}
+@string{EKerry = "Kerry, Elijah"}
+@string{NI = "National Instruments"}
+@string{USENIX = "USENIX Association"}
+@string{WM = "WaveMetrics"}
+
+@misc{ wavemetrics-igor,
+ author = WM,
+ title = {{IGOR Pro}},
+ url = {http://www.wavemetrics.com/products/igorpro/igorpro.htm},
+}
+
+@misc{ labview,
+ author = NI,
+ title = {{LabVIEW}},
+ url = {http://www.ni.com/labview/},
+}
+
+@misc{ national-instruments,
+ title = {{National Instruments}},
+ url = {https://www.ni.com/},
+}
+
+@article{ ni-vi-management,
+ author = NI,
+ title = {Best Practices for Managing {NI} {LabVIEW} Applications Using
+ the {Project Explorer}},
+ year = 2013,
+ month = jan,
+ day = 28,
+ journal = {Software Engineering with LabVIEW},
+ url = {http://www.ni.com/white-paper/7197/en},
+}
+
+@misc{ ni-merge,
+ author = EKerry,
+ title = {Source Code Control: Using {TortoiseSVN} ({Subversion}) with
+ {LabVIEW} for Diff and Merge Operations},
+ year = 2012,
+ month = dec,
+ day = 6,
+ url = {https://decibel.ni.com/content/docs/DOC-2936},
+}
+
+@misc{ ni-vi-version,
+ author = NI,
+ title = {How Can {I} Determine the {LabVIEW} Version that was Used
+ to Save a {VI}?},
+ year = 2012,
+ month = apr,
+ day = 9,
+ url = {http://digital.ni.com/public.nsf/allkb/0C72D335AA87DD6486256FC40069C17F},
+ note = {Document ID: 3JDC8IZH},
+}
+
+@misc{ ni-daqmx,
+ author = NI,
+ title = {Using {NI-DAQmx} in {LabWindows/CVI}},
+ year = 2007,
+ month = mar,
+ date = 14,
+ url = {http://www.ni.com/white-paper/2931/en},
+}
+
+@misc{ cygwin,
+ title = {Cygwin},
+ url = {http://www.cygwin.com/},
+}
+
+@misc{ epics,
+ title = {{EPICS}: Experimental Physics and Industrial Control System},
+ url = {http://www.aps.anl.gov/epics/},
+}
+
+@inproceedings{ beazley96,
+ author = DBeazley,
+ title = {{SWIG}: An easy to use tool for integrating scripting
+ languages with {C} and {C++}},
+ booktitle = {Proceedings of the 4th conference on USENIX Tcl/Tk Workshop},
+ series = {Tcl/Tk 1996},
+ volume = 4,
+ location = {Monterey, California},
+ year = 1996,
+ pages = {15--15},
+ numpages = 1,
+ url = {http://www.swig.org/},
+ eprint = {http://www.swig.org/papers/Tcl96/tcl96.html},
+ paper_url = {http://dl.acm.org/citation.cfm?id=1267498.1267513},
+ publisher = USENIX,
+ address = {Berkeley, CA, USA},
+}
+
+@misc{ cython,
+ title = {Cython: C-Extensions for {Python}},
+ url = {http://www.cython.org/},
+}
+
+@misc{ scipy-leastsq,
+ title = {\texttt{scipy.optimize.leastsq}},
+ url = {http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html},
+}
+
+@misc{ minpack,
+ title = {{MINPACK}},
+ url = {http://www.netlib.org/minpack/},
+}
+
+@misc{ hdf5,
+ author = HDFG,
+ title = {Hierarchical data format version 5},
+ year = 2013,
+ url = {http://www.hdfgroup.org/HDF5/},
+ note = {Version 1.8.10},
+}
+
+@misc{ yaml,
+ title = {{YAML} Ain't Markup Language ({YAML\texttrademark})
+ Version 1.2},
+ year = 2009,
+ month = oct,
+ day = 1,
+ edition = 3,
+ url = {http://www.yaml.org/},
+ eprint = {http://www.yaml.org/spec/1.2/spec.html},
+}
+
+@misc{ jones95,
+ author = DWJones,
+ title = {Control of Stepping Motors},
+ year = 1995,
+ url = {http://homepage.cs.uiowa.edu/~jones/step/},
+ note = {This material expands on material originally posted to the
+ rec.railroad newsgroup in 1990. Significant parts of this material
+ have been republished as sections 5.2.10, 10.8, 10.9 and 10.10 of
+ the Handbook of Small Electric Motors edited by W. H. Yeadon and
+ A. W. Yeadon, McGraw-Hill, 2001, and as Applications Note 907
+ published by Microchip Inc in 2004.},
+}
+
+@misc{ pymodbus,
+ title = {Pymodbus},
+ url = {https://github.com/bashwork/pymodbus},
+ note = {Version TODO},
+}
+
+@misc{ melcor,
+ title = {Melcor},
+ note = {Companies don't stay in business forever, but lab equipment
+ does. Our controller is still going strong (since 1999), but
+ Melcor has moved around. According to their
+ \href{http://www.lairdtech.com/NewsItem.aspx?id=953}{2005
+ announcement} the Laird Group PLC purchased Melcor from Fedders
+ Corporation, and by 2009 (according to the
+ \href{http://web.archive.org/web/20090204201524/http://melcor.com/}{Internet
+ Archive Wayback Machine}) they phased out the old website at
+ \href{http://melcor.com/}{melcor.com} in favor of
+ \href{http://lairdtech.thomasnet.com/category/thermal-management-solutions/}{their
+ own thermal site}. It looks like there is no longer support for
+ the older MTCA controllers.},
+}
-\chapter{Experiment control software, \pyafm\ and related packages}
+\chapter{Experiment control software, \pyafm, and related packages}
\label{sec:pyafm}
+Velocity clamp experiments have been carried out since the initial
+work by \citet{rief97a}, so I was somewhat surprised that there
+weren't already community-driven packages for carrying out and
+analyzing these
+experiments\citep{claerbout92,buckheit95,schwab00,vandewalle09}. When
+I joined Prof.~Yang's lab, we were using experiment control software
+written in \citetalias{labview} and analysis software written in
+\citetalias{wavemetrics-igor}, both developed in-house. The existing
+software was not designed to control sample temperature or for easy
+extension, so I proceeded to write my own control and analysis stack
+to add this capabilities. In this chapter, I will discuss the earlier
+frameworks and some abortive attempts that lead me towards my current
+architecture (\cref{sec:aio-frameworks,sec:pyafm:stack}). I will also
+discuss some auxiliary packages I developed to support the main stack
+(\cref{sec:pyafm:auxiliary}). I'll wrap up by comparing my stack with
+Prof.~Yang's earlier framework and summarizing lessons I've learned
+along the way (\cref{sec:pyafm:discussion,sec:pyafm:conclusions}).
+
\input{pyafm/frameworks}
\input{pyafm/stack}
\input{pyafm/auxiliary}
\section{The pyafm stack}
+\label{sec:pyafm:stack}
+
+In order to reduce future maintenance costs, I have based my stack as
+much as possible on existing FLOSS software, and split my stack into
+reusable components where such components might appeal to a wider
+audience. From the bottom up, \pycomedi\ wraps the Comedi device
+driver for generic input/output, \pypiezo\ builds generic
+piezo-control logic on top of \pycomedi, \pyafm\ combines a
+\pypiezo-controlled piezo with a \stepper-controlled stepper motor and
+\pypid-controlled temperature controller, and \unfoldprotein\ adds
+experiment logic to \pyafm\ to carry out velocity-clamp force
+spectroscopy (\cref{fig:pyafm:stack}).
+
+\begin{figure}
+ \begin{tikzpicture}
+ \tikzstyle{every node}=[text depth=0pt, rounded rectangle,
+ draw=blue!50, very thick, minimum height=1.7em]
+ \node (pycomedi) at (0,0) {\pycomedi};
+ \node (pypiezo) at ($(pycomedi) + (0,1)$) {\pypiezo};
+ \node (pyafm) at ($(pypiezo) + (0,1)$) {\pyafm};
+ \node (unfold-protein) at ($(pyafm) + (0,1)$) {\unfoldprotein};
+ \node (stepper) at ($(pycomedi) + (2,1)$) {\stepper};
+ \node (pypid) at ($(stepper) + (2,0)$) {\pypid};
+ \node (h5config) at ($(pycomedi) + (-3,0)$) {\hFconfig};
+ \node (calibcant) at ($(unfold-protein) + (-3,0)$) {\calibcant};
+ \draw (pycomedi) -- (pypiezo);
+ \draw (pycomedi) -- (stepper);
+ \draw (pypiezo) -- (pyafm);
+ \draw (stepper) -- (pyafm);
+ \draw (pypid) -- (pyafm);
+ \draw (pyafm) -- (unfold-protein);
+ \draw (pyafm) -- (calibcant);
+ \draw (h5config) -- (pypiezo);
+ \draw (h5config) -- (pyafm);
+ \draw (h5config) -- (unfold-protein);
+ \draw (h5config) -- (calibcant);
+ \end{tikzpicture}
+ \caption{Dependency graph for my modular experiment control
+ stack.\label{fig:pyafm:stack}}
+\end{figure}
+
\subsection{Pycomedi}
+\label{sec:pyafm:pycomedi}
+
+After my experience with C (\cref{sec:ni-daqmx}), I knew I wanted a
+higher level language for the bulk of my experiments.
+\citetalias{comedi} already had \citetalias{beazley96}-generated
+Python bindings, so I set to work creating \pycomedi, an
+object-oriented interface around the SWIG bindings. The first
+generation \pycomedi\ interface was much easier to use than the raw
+SWIG bindings, especially for simultaneous analog input/output, which
+I needed to monitor cantilever deflection during piezo-sweeping
+velocity-clamp pulls.
+
+The SWIG-based interface to Comedi provided a solid base for my
+experiment control stack, but as the stack matured, I started bumping
+up against problems due to both my poor design
+choices\footnote{\citet{brooks95} says ``plan to throw one away,''
+ although I'm a more optimistic about the feasibility of long-term
+ maintenance than he is.} and general awkwardness with the thin SWIG
+bindings. In 2011 I ripped out most of this layer and used
+\citetalias{cython} to bind directly to Comedi's userspace library.
+This lead to a much more Pythonic interface, and removed a number of
+previously sticky workarounds required by earlier versions of
+\pycomedi.
+
+As a generic Python interface to Comedi, \pycomedi\ has a wider user
+base than the rest of my experiment control stack (there are more
+folks writing Python code for DAQ cards on Linux than there are
+writing velocity-clamp AFM controllers on Linux). I've had a number
+of people contact me directly with \pycomedi\ questions, including a
+neuroscientist, a radiologist, and an automotive electrician.
+\href{http://pieleric.free.fr/}{\'Eric Piel} even contributed a few
+patches for software-calibrated devices.
+
+Comparing the NI-DAQmx implementation of digital writes
+(\cref{fig:ni-daqmx}) with a more complete \pycomedi\ implementation
+(\cref{fig:pycomedi}), the \pycomedi\ implementation reads much more
+naturally. The main difference is that Python's object-oriented
+structure allows us to bundle complex Comedi subdevice handling into a
+series of intuitive methods. We also benefit from Python's exception
+handling. While C requires you to actively check for exceptions where
+they might occur (``hey, this write failed''), Python exceptions
+bubble up the call stack so you can deal with them at a more
+appropriate level (``hey, the stepper motor failed''). This allows us
+to centralize error handling in higher level code, making the low
+level code much cleaner.
+
+\begin{figure}
+ \begin{center}
+\begin{minted}{python}
+from pycomedi.device import Device
+from pycomedi.channel import DigitalChannel
+from pycomedi.constant import SUBDEVICE_TYPE, IO_DIRECTION
+
+device = Device('/dev/comedi0')
+device.open()
+
+subdevice = device.find_subdevice_by_type(SUBDEVICE_TYPE.dio)
+channels = [subdevice.channel(i, factory=DigitalChannel)
+ for i in (0, 1, 2, 3)]
+for chan in channels:
+ chan.dio_config(IO_DIRECTION.output)
+
+def write(value):
+ subdevice.dio_bitfield(bits=value, write_mask=2**4-1)
+\end{minted}
+ \caption{A four-channel digital output example in \pycomedi\ (from
+ the \stepper\ doctest). Compare this with the much more verbose
+ \cref{fig:ni-daqmx}, which is analogous to the
+ \texttt{subdevice.dio\_bitfield()} call.\label{fig:pycomedi}}
+ \end{center}
+\end{figure}
+
\subsection{Pypiezo}
+\label{sec:pyafm:pypiezo}
+
+The piezo controlling code builds on the framework established by
+\pycomedi\ to define an interface for controlling the peizo-mounted
+surface (\cref{fig:piezo-schematic}). This involves code to sweep the
+piezo in a hardware-timed ramp as well as code for discrete jumps. To
+carry out these tasks, \pypiezo also contains code to convert piezo
+motion (in meters) to DAC output voltages (in bits), an
+\hFconfig-based framework for automatically configuring
+\pycomedi\ channels and piezo axes, and surface detection logic.
+
+Because of the tight coupling needed between piezo motion and
+cantilever deflection detection for synchronized ramps, the basic
+\texttt{Piezo} class can be configured with generic \pycomedi\ input
+channels. In practice, only the cantilever deflection is monitored,
+but if other \pypiezo\ users want to measure other analog inputs, the
+functionality is already built in.
+
+\nomenclature{DAC}{Digital to analog converter. A device that
+ converts a digital signal into an analog signal. The inverse of an
+ ADC}
+\nomenclature{ADC}{Analog to digital converter. A device that
+ digitizes an analog signal. The inverse of a DAC.}
+
+The surface detection logic is somewhat heuristic, although it has
+proven quite robust in practice. Given a particular piezo axis,
+target deflection, number of steps, and an allowed piezo range, the
+procedure is:
+
+\begin{enumerate}
+ \item \label{item:pypiezo-surface-retract-1} Ramp the piezo from its
+ current position away to its maximum separation $z_\text{max}$.
+ \item \label{item:pypiezo-surface-step-approach} Step the piezo in
+ towards its minimum separation, checking the deflection after each
+ step to see if the target deflection threshold has been crossed.
+ This is the high-contact piezo position $z_\text{min}$.
+ \item \label{item:pypiezo-surface-retract-2} Ramp the piezo away to
+ its maximum separation $z_\text{max}$. Because of protein on the
+ surface, the detachment region between the contact region and
+ non-contact region may have additional forces
+ (\cref{fig:expt-sawtooth}). This can make the determination of
+ the contact kink difficult. The full retraction breaks any
+ protein-based contacts between the cantilever and the surface.
+ \item \label{item:pypiezo-surface-ramp-approach} Ramp the piezo in
+ to the high-contact position $z_\text{min}$. Because any
+ protein-based contacts were broken in the previous step, the
+ contact kink at $z_\text{kink}$ should be clear and crisp.
+ \item \label{item:pypiezo-surface-reset} Ramp the piezo back to the
+ original position.
+\end{enumerate}
+
+The deflection data $d(z)$ from
+\ref{item:pypiezo-surface-ramp-approach}, which should clearly show
+the contact kink, is fit to a bilinear model (a linear non-contact
+region and a linear contact region, which meet at the the contact
+kink). The fitting is carried out my minimizing the residual
+difference between the approach data and bilinear model with SciPy's
+\imint{python}|leastsq| optimizer, a wrapper around MINPACK's
+\imint{fortran}|lmdif| and \imint{fortran}|lmder|
+algorithms\citep{scipy-leastsq,minpack}.
+
+\begin{align}
+ d(z) = \begin{cases}
+ d_\text{kink} + \sigma_{p,\text{c}} (z - z_\text{kink})
+ & z \le z_\text{kink} \\
+ d_\text{kink} + \sigma_{p,\text{nc}} (z - z_\text{kink})
+ & z \ge z_\text{kink}
+ \end{cases}
+\end{align}
+
+Initial parameters for the fit are:
+
+\begin{align}
+ d_\text{kink} &= d(z_\text{max}) \\
+ z_\text{kink} &= \frac{z_\text{max} - z_\text{min}}{2} \\
+ \sigma_{p,\text{c}} &= 2\cdot
+ \frac{d(z_\text{max}) - d(z_\text{min})}{z_\text{max} - z_\text{min}} \\
+ \sigma_{p,\text{nc}} &= 0
+\end{align}
+
+The fitted $d_\text{kink}$ is accepted unless:
+
+\begin{itemize}
+ \item the fitted slope ratio
+ $|\sigma_{p,\text{c}}/\sigma_{p,\text{nc}}|$ is less than a
+ minimum threshold (which defaults to 10), or
+ \item the fitted kink position $z_\text{kink}$ is within an excluded
+ $z_\text{window}$ of the boundaries ($z_\text{window}$ defaults to
+ 2\% of the total range $z_\text{max} - z_\text{min}$).
+\end{itemize}
+
+The default slope ratios work well for the cantilevers I generally
+use, but softer cantilevers may have enough drift that the minumum
+slope ratio threshold needs to be reduced. I have not yet run into
+problems with the default kink window. Although these are low level
+parameters, appropriate values may depend on details of the particular
+experimental setup. The \hFconfig-based configuration structure makes
+it easy to configure (and record) the values of many similar heuristic
+parameters like these involved in robust experiment control.
+
+In the event that the surface detection is not acceptable,
+\pypiezo\ raises an exception which bubbles up the call stack until it
+is handled in \unfoldprotein\ (\cref{sec:pyafm:unfold-protein}).
+
\subsection{Pyafm}
+\label{sec:pyafm:pyafm}
+
+Sweeping piezos around and measuring the resulting cantilever
+deflection is the core of velocity-clamp force spectroscopy. However,
+our experimental apparatus contains some additional supporting
+hardware: a stepper motor for coarse positioning and a
+peltier/thermocouple module for temperature control. The
+\pyafm\ module builds on \pypiezo,
+\stepper\ (\cref{sec:pyafm:stepper}), and
+\pypid\ (\cref{sec:pyafm:pypid}) to provide an easy to use (and easy
+to configure) \imint{python}|AFM| class for controlling the whole
+package.
+
+While the piezo tube is able to move the surface relative to the
+cantilever tip (\cref{fig:afm-schematic-and-piezo}), it only has a
+limited range (on the order of microns). Achieving such a small
+separation by hand when assembling the microscope is unlikely, so a
+stepper motor controlling a fine pitch screw is used for course
+positioning. Generic stepper control is handled by the
+\stepper\ package, and \pyafm\ builds on this to add \hFconfig-based
+configuration (time delay between steps, approximate step size,
+approximate stepper backlash, digital control port, \ldots) and a few
+course positioning methods:
+
+\begin{description}
+ \item[\imint{python}|AFM.move_away_from_surface|] provides a safety
+ mechanism that higher level applications can use to bail out. For
+ example, when \unfoldprotein\ can not locate the surface (for
+ example, a bubble in the fluid cell may be blocking the laser
+ beam), it uses this method to put some distance between the
+ cantilever and the surface, to avoid crashing the tip and breaking
+ the cantilever. Less drastically, this method is also used by
+ \calibcant\ (\cref{sec:calibcant}) when it changes from the
+ surface bump stage (\cref{TODO}) to the thermal vibration stage
+ (\cref{TODO}).
+ \item[\imint{python}|AFM.stepper_approach|] quickly positions the
+ surface within piezo-range of the cantilever tip by stepping in
+ (with the stepper motor) until the cantilever deflection crosses a
+ target threshold. The piezo extension is kept constant during the
+ approach, but a single stepper step only moves the surface $\sim
+ 170\U{nm}$, and our cantilevers can safely absorb deflections on
+ that scale.
+ \item[\imint{python}|AFM.move_just_onto_surface|] is a more refined
+ version of \imint{python}|AFM.stepper_approach|. This method uses
+ \pypiezo's surface detection algorithm to locate the surface kink
+ position $z_\text{kink}$, and adjusts the stepper in single steps
+ until the measured kink is within two stepper steps ($\sim
+ 340\U{nm}$) of the centered piezo position. Then it shifts the
+ piezo to position the cantilever tip at an exact offset from the
+ measured kink. This precise positioning is used for running
+ \calibcant's bumps, but the per-step piezo manipulation makes long
+ distance approaches much slower than
+ \imint{python}|AFM.stepper_approach|.
+\end{description}
+
+\subsection{Unfold-protein}
+\label{sec:pyafm:unfold-protein}
+
+Capping the experimental control stack, \unfoldprotein\ adds the
+actual experiment logic to the lower level control software. The
+abstractions provided by the lower level code make for clean, easily
+adaptable code
+(\cref{fig:unfold-protein:unfolder,fig:unfold-protein:scanner}).
+
+\begin{figure}
+ \begin{center}
+\begin{minted}[mathescape]{python}
+class Unfolder (object):
+ # $\ldots$
+ def run(self):
+ """Approach-bind-unfold-save[-plot] cycle.
+ """
+ ret = {}
+ ret['timestamp'] = _email_utils.formatdate(localtime=True)
+ ret['temperature'] = self.afm.get_temperature()
+ ret['approach'] = self._approach()
+ self._bind()
+ ret['unfold'] = self._unfold()
+ self._save(**ret)
+ if _package_config['matplotlib']:
+ self._plot(**ret)
+ return ret
+\end{minted}
+ \caption{The main unfolding loop in \unfoldprotein. Compare this
+ with the much more opaque pull phase in
+ \cref{fig:labview}.\label{fig:unfold-protein:unfolder}}
+ \end{center}
+\end{figure}
+
+\begin{figure}
+ \begin{center}
+\begin{minted}[mathescape]{python}
+class UnfoldScanner (object):
+ # $\ldots$
+ def run(self, stepper_tweaks=True):
+ self._stop = False
+ _signal.signal(_signal.SIGTERM, self._handle_stop_signal)
+ self.unfolder.afm.move_away_from_surface()
+ self.stepper_approach()
+ for i in range(self.config['velocity']['num loops']):
+ _LOG.info('on loop {} of {}'.format(
+ i, self.config['velocity']['num loops']))
+ for velocity in self.config['velocity']['unfolding velocities']:
+ if self._stop:
+ return
+ self.unfolder.config['unfold']['velocity'] = velocity
+ try:
+ self.unfolder.run()
+ except _ExceptionTooFar:
+ if stepper_tweaks:
+ self.stepper_approach()
+ else:
+ raise
+ except _ExceptionTooClose:
+ if stepper_tweaks:
+ self.afm.move_away_from_surface()
+ self.stepper_approach()
+ else:
+ raise
+ else:
+ self.position_scan_step()
+\end{minted}
+ \caption{The scanning loop \unfoldprotein. Unfolding pulls are
+ carried out with repeated calls to
+ \imint{python}|self.unfolder.run()|
+ (\cref{fig:unfold-protein:unfolder}), looping over the
+ configured range of velocities for a configured number of
+ cycles. If \imint{python}|stepper_tweaks| is
+ \imint{python}|True|, the scanner adjusts the stepper position
+ to keep the surface within the piezo's range. After a
+ successful pull, \imint{python}|self.position_scan_step()|
+ shifts the piezo in the $x$ direction, so the next pull will not
+ hit the same surface
+ location.\label{fig:unfold-protein:scanner}}
+ \end{center}
+\end{figure}
@string{AAPT = "AAPT"}
-@string{ACSChemBiol = "ACS Chem Biol"}
+@string{CoRR = "arXiv Computing Research Repository"}.
+@string{ACM = "Association for Computing Machinery"}
+@string{KAstrom = "{\AA}str{\"o}m, K.~J."}
+@string{ACM:SIGCSE = "ACM Special Interest Group on Computer Science Education Bulletin"}
+@string{ACM:CSur = "ACM Computing Surveys"}
+@string{ACS:ChemBiol = "ACS Chem Biol"}
@string{AIP = "AIP"}
@string{APL = "Applied Physics Letters"}
@string{DAbramavicius = "Abramavicius, Darius"}
@string{JAbu-Threideh = "Abu-Threideh, J."}
@string{KAdachi = "Adachi, Kengo"}
@string{MDAdams = "Adams, M. D."}
-@string{AdvExpMedBiol = "Adv Exp Med Biol"}
+@string{AW = "Addison-Wesley Longman Publishing Co., Inc."}
+@string{AdvExpMedBiol = "Advances in Experimental Medicine and Biology"}
@string{SAinavarapu = "Ainavarapu, Sri Rama Koti"}
@string{FAli = "Ali, F."}
@string{JFAllemand = "Allemand, Jean-Fran\c{c}ois"}
@string{NMAmer = "Amer, Nabil M."}
@string{AJP = "American Journal of Physics"}
@string{APS = "American Physical Society"}
+@string{AS = "American Scientist"}
@string{ASA = "American Statistical Association"}
@string{HAn = "An, H."}
@string{KNAn = "An, Kai-Nan"}
@string{ARBBS = "Annu Rev Biophys Biomol Struct"}
@string{ARBC = "Annual Review of Biochemistry"}
@string{DAnselmetti = "Anselmetti, Dario"}
+@string{AAntoniadis = "Antoniadis, Anestis"}
@string{AMC = "Applied Mathematics and Computation"}
@string{SArcidiacono = "Arcidiacono, S"}
@string{CArciola = "Arciola, Carla Renata"}
@string{ABArtyukhin = "Artyukhin, Alexander B."}
+@string{DAruliah = "Aruliah, Dhavide A."}
@string{SAsakawa = "Asakawa, S."}
@string{AAwe = "Awe, A."}
@string{SBedard = "B\'edard, Sabrina"}
@string{SBroder = "Broder, S."}
@string{SBroedel = "Broedel, Sheldon E."}
@string{ABrolo = "Brolo, Alexandre G."}
+@string{FBrooks = "Brooks, Jr., Frederick P."}
@string{BrooksCole = "Brooks/Cole"}
@string{BDBrowerToland = "Brower-Toland, Brent D."}
+@string{CTBrown = "Brown, C. Titus"}
@string{MBrucale = "Brucale, Marco"}
@string{TBruls = "Bruls, T."}
@string{VBrumfeld = "Brumfeld, Vlad"}
@string{JDBryngelson = "Bryngelson, J. D."}
+@string{JBuckheit = "Buckheit, Jonathan B."}
@string{ABuguin = "Buguin, A."}
@string{ABulhassan = "Bulhassan, Ahmed"}
@string{BBullard = "Bullard, Belinda"}
@string{MCarrionVazquez = "Carrion-Vazquez, Mariano"}
@string{CCarter = "Carter, C."}
@string{ACarver = "Carver, A."}
-@string{JJCatanese = "Catanese, J. J."}
+@string{JJCatanese = "Catanese, J.~J."}
@string{PCaulk = "Caulk, P."}
@string{CCecconi = "Cecconi, Ciro"}
@string{ACenter = "Center, A."}
-@string{HSChan = "Chan, H. S."}
+@string{CTChan = "Chan, C.~T."}
+@string{HSChan = "Chan, H.~S."}
@string{AChand = "Chand, Ami"}
@string{IChandramouliswaran = "Chandramouliswaran, I."}
@string{CHChang = "Chang, Chung-Hung"}
@string{KChaturvedi = "Chaturvedi, K."}
@string{CChauzy = "Chauzy, C."}
@string{SChe = "Che, Shunai"}
+@string{CEC = "Chemical Engineering Communications"}
@string{CHEMREV = "Chemical reviews"}
@string{CHEM = "Chemistry (Weinheim an der Bergstrasse, Germany)"}
@string{CPC = "Chemphyschem"}
@string{TYChung = "Chung, Tse-Yu"}
@string{CLChyan = "Chyan, Chia-Lin"}
@string{GCiccotti = "Ciccotti, Giovanni"}
+@string{JClaerbout = "Claerbout, Jon F."}
@string{AGClark = "Clark, A. G."}
@string{Clarke = "Clarke"}
@string{JClarke = "Clarke, Jane"}
@string{JMClaverie = "Claverie, J. M."}
@string{KClerc-Blankenburg = "Clerc-Blankenburg, K."}
@string{NJCobb = "Cobb, Nathan J."}
+@string{GHCohen = "Cohen, G.~H."}
@string{FSCollins = "Collins, Francis S."}
@string{CUP = "Columbia University Press"}
@string{CPR = "Computer Physics Reports"}
+@string{CSE = "Computing in Science \& Engineering"}
@string{UniProtConsort = "Consortium, The UniProt"}
@string{MConti = "Conti, Matteo"}
+@string{CEP = "Control Engineering Practice"}
+@string{GACoon = "Coon, G.~A."}
@string{PVCornish = "Cornish, Peter V."}
@string{MNCourel = "Courel, M. N."}
@string{GCowan = "Cowan, Glen"}
@string{FDahlquist = "Dahlquist, Frederick W."}
@string{SDanaher = "Danaher, S."}
@string{LDavenport = "Davenport, L."}
+@string{MDavis = "Davis, Matt"}
@string{SDecatur = "Decatur, Sean M."}
@string{WDeGrado = "DeGrado, William F."}
@string{PDebrunner = "Debrunner, P."}
@string{KDiemer = "Diemer, K."}
@string{HDietz = "Dietz, Hendrik"}
@string{SDietz = "Dietz, S."}
+@string{EDijkstra = "Dijkstra, Edsger Wybe"}
@string{KADill = "Dill, K. A."}
@string{RDima = "Dima, Ruxandra I."}
@string{DDischer = "Discher, Dennis E."}
@string{NDoggett = "Doggett, N."}
@string{MDombroski = "Dombroski, M."}
@string{MDonnelly = "Donnelly, M."}
+@string{DDonoho = "Donoho, David L."}
@string{CDornmair = "Dornmair, C."}
@string{MDors = "Dors, M."}
@string{LDougan = "Dougan, Lorna"}
@string{AGomezCasado = "Gomez-Casado, Alberto"}
@string{BGompertz = "Gompertz, Benjamin"}
@string{FGong = "Gong, F."}
+@string{GordonBreach = "Gordon Breach Scientific Publishing Ltd."}
@string{MGorokhov = "Gorokhov, M."}
@string{JHGorrell = "Gorrell, J. H."}
@string{KGraham = "Graham, K."}
@string{HJGuntherodt = "Guntherodt, Hans-Joachim"}
@string{NGuo = "Guo, N."}
@string{YGuo = "Guo, Yi"}
+@string{RTGuy = "Guy, Richard T."}
@string{PHanggi = {H\"anggi, Peter}}
@string{THa = "Ha, Taekjip"}
@string{JHaack = "Haack, Julie A."}
+@string{SHaddock = "Haddock, Steven H.~D."}
@string{GHager = "Hager, Gabriele"}
+@string{THagglund = "H{\"a}gglund, T."}
@string{RHajjar = "Hajjar, Roger J."}
@string{AHalpern = "Halpern, A."}
@string{KHalvorsen = "Halvorsen, Ken"}
@string{FHan = "Han, Fangpu"}
+@string{CCHang = "Hang, C.~C."}
@string{SHannenhalli = "Hannenhalli, S."}
@string{HHansma = "Hansma, H. G."}
@string{PHansma = "Hansma, Paul K."}
@string{BHeymann = "Heymann, Berthold"}
@string{NHiaro = "Hiaro, N."}
@string{MEHiggins = "Higgins, M. E."}
+@string{THilburn = "Hilburn, Thomas B."}
@string{LHillier = "Hillier, L."}
@string{HHinssen = "Hinssen, Horst"}
@string{PHinterdorfer = "Hinterdorfer, Peter"}
@string{HistochemJ = "Histochem J"}
@string{SHladun = "Hladun, S."}
+@string{WKHo = "Ho, W.~K."}
@string{RHochstrasser = "Hochstrasser, Robin M."}
@string{CHoff = "Hoff, C."}
@string{WHoff = "Hoff, Wouter D."}
@string{JLHolden = "Holden, J. L."}
@string{RAHolt = "Holt, R. A."}
@string{MHonda = "Honda, M."}
+@string{NPCHong = "Hong, Neil P. Chue"}
@string{XHong = "Hong, Xia"}
@string{LHood = "Hood, L."}
@string{JHoover = "Hoover, J."}
@string{CKHu = "Hu, Chin-Kun"}
@string{BHuang = "Huang, Baiqu"}
@string{HHuang = "Huang, Hector Han-Li"}
+@string{KHuff = "Huff, Katy"}
+@string{JHughes = "Hughes, John"}
@string{GHummer = "Hummer, Gerhard"}
@string{SJHumphray = "Humphray, S. J."}
@string{WLHung = "Hung, Wen-Liang"}
@string{JHutter = "Hutter, Jeffrey L."}
@string{CHyeon = "Hyeon, Changbong"}
@string{IEEE:TIT = "IEEE Transactions on Information Theory"}
+@string{IEEE:SPM = "IEEE Signal Processing Magazine"}
@string{CIbegwam = "Ibegwam, C."}
@string{JRIdol = "Idol, J. R."}
@string{SImprota = "Improta, S."}
@string{TInoue = "Inoue, Tadashi"}
@string{IJBMM = "International Journal of Biological Macromolecules"}
+@string{IJCIS = "International Journal of Computer \& Information Sciences"}
@string{HItoh = "Itoh, Hiroyasu"}
@string{AIrback = "Irback, Anders"}
@string{BIsralewitz = "Isralewitz, B."}
@string{JP:CM = "Journal of Physics: Condensed Matter"}
@string{JP:CON = "Journal of Physics: Conference Series"}
@string{JASA = "Journal of the American Statistical Association"}
+@string{WSJuang = "Juang, F.~S."}
@string{DAJuckett = "Juckett, D. A."}
@string{SRJun = "Jun, Se-Ran"}
@string{DKaftan = "Kaftan, David"}
@string{AKardinal = "Kardinal, Angelika"}
@string{BKarlak = "Karlak, B."}
@string{MKarplus = "Karplus, Martin"}
+@string{MKarrenbach = "Karrenbach, Martin"}
@string{JKasha = "Kasha, J."}
@string{KKawasaki = "Kawasaki, K."}
@string{ZKe = "Ke, Z."}
@string{DKlimov = "Klimov, Dmitri K."}
@string{LKline = "Kline, L."}
@string{LKlumb = "Klumb, L."}
+@string{KAPPP = "Kluwer Academic Publishers--Plenum Publishers"}
@string{CDKodira = "Kodira, C. D."}
@string{SKoduru = "Koduru, S."}
@string{BKolmerer = "Kolmerer, B."}
@string{JKorenberg = "Korenberg, J."}
@string{IKosztin = "Kosztin, Ioan"}
+@string{JKovacevic = "Kovacevic, Jelena"}
@string{CKraft = "Kraft, C."}
@string{HAKramers = "Kramers, H. A."}
@string{AKrammer = "Krammer, Andre"}
@string{AMatouschek = "Matouschek, Andreas"}
@string{BMatthews = "Matthews, Brian W."}
@string{DMay = "May, D."}
+@string{RMayer = "Mayer, Richard"}
@string{LMayne = "Mayne, Leland"}
@string{AMays = "Mays, A."}
@string{OTMcCann = "McCann, O. T."}
@string{AMiller = "Miller, A."}
@string{NMilshina = "Milshina, N."}
@string{SMinoshima = "Minoshima, S."}
+@string{IMitchell = "Mitchell, Ian"}
@string{SMitternacht = "Mitternacht, Simon"}
@string{CMobarry = "Mobarry, C."}
@string{NMohandas = "Mohandas, N."}
@string{TNguyen = "Nguyen, T."}
@string{MNguyen-Duong = "Nguyen-Duong, M."}
@string{INicholls = "Nicholls, Ian A."}
+@string{NNichols = "Nichols, N.~B."}
@string{SNie = "Nie, S."}
@string{MNodell = "Nodell, M."}
@string{AANoegel = "Noegel, Angelika A."}
@string{POmling = {Omlink, P{\"a}r}}
@string{JNOnuchic = "Onuchic, J. N."}
@string{YOono = "Oono, Y."}
+@string{GOppenheim = "Oppenheim, Georges"}
@string{COpitz = "Optiz, Christiane A."}
@string{KOroszlan = "Oroszlan, Krisztina"}
@string{EOroudjev = "Oroudjev, E."}
@string{Physica = "Physica"}
@string{GPing = "Ping, Guanghui"}
@string{NPinotsis = "Pinotsis, Nikos"}
+@string{MPlumbley = "Plumbley, Mark"}
@string{DPlunkett = "Plunkett, David"}
@string{PPodsiadlo = "Podsiadlo, Paul"}
@string{ASPolitou = "Politou, A. S."}
@string{GDSchuler = "Schuler, G. D."}
@string{KSchulten = "Schulten, Klaus"}
@string{ZSchulten = "Schulten, Zan"}
+@string{MSchwab = "Schwab, M."}
@string{ISchwaiger = "Schwaiger, Ingo"}
@string{RSchwartz = "Schwartz, R."}
@string{RSchweitzerStenner = "Scheitzer-Stenner, Reinhard"}
@string{NShimizu = "Shimizu, N."}
@string{RShimoKon = "Shimo-Kon, Rieko"}
@string{AShintani = "Shintani, A."}
+@string{BShneiderman = "Shneiderman, Ben"}
@string{BShue = "Shue, B."}
@string{RSiebert = "Siebert, R."}
@string{EDSiggia = "Siggia, Eric D."}
@string{TSmith = "Smith, T."}
@string{JSoares = "Soares, J."}
@string{NDSocci = "Socci, N. D."}
+@string{SEG = "Society of Exploration Geophysicists"}
@string{ESodergren = "Sodergren, E."}
@string{CSoderlund = "Soderlund, C."}
@string{JSpanier = "Spanier, Jonathan E."}
@string{RTampe = "Tamp{\'e}, Robert"}
@string{JTang = "Tang, Jianyong"}
@string{BNTaylor = "Taylor, Barry N."}
+@string{THEMath = "Technische Hogeschool Eindhoven, Nederland,
+ Onderafdeling der Wiskunde"}
@string{STeukolsky = "Teukolsky, S."}
+@string{CJ = "The Computer Journal"}
@string{JCP = "The Journal of Chemical Physics"}
@string{JPC:B = "The Journal of Physical Chemistry B"}
@string{JPC:C = "The Journal of Physical Chemistry C"}
@string{TTlusty = "Tlusty, Tsvi"}
@string{JTocaHerrera = "Toca-Herrera, Jose L."}
@string{AToyoda = "Toyoda, A."}
+@string{TASME = "Transactions of the American Society of Mechanical Engineers"}
@string{BTrask = "Trask, B."}
@string{TBI = "Tribology International"}
@string{JTrinick = "Trinick, John"}
@string{UTMB = "University of Texas Medical Branch"}
@string{MUrbakh = "Urbakh, M."}
@string{KJVanVliet = "Van Vliet, Krystyn J."}
+@string{PVandewalle = "Vandewalle, Patrick"}
@string{CVech = "Vech, C."}
@string{OVelasquez = "Velasquez, O."}
@string{EVenter = "Venter, E."}
@string{JCVenter = "Venter, J. C."}
@string{PHVerdier = "Verdier, Peter H."}
@string{IVetter = "Vetter, Ingrid R."}
+@string{MVetterli = "Vetterli, Martin"}
@string{WVetterling = "Vetterling, W."}
@string{MViani = "Viani, Mario B."}
@string{JCVoegel = "Voegel, J.-C."}
@string{AJWalton = "Walton, Alan J"}
@string{EBWalton = "Walton, Emily B."}
@string{AWang = "Wang, A."}
+@string{FSWang = "Wang, F.~S."}
@string{GWang = "Wang, G."}
@string{JWang = "Wang, J."}
@string{MWang = "Wang, M."}
@string{HWatanabe = "Watanabe, Hiroshi"}
@string{KWatanabe = "Watanabe, Kaori"}
@string{RHWaterston = "Waterston, R. H."}
+@string{BWaugh = "Waugh, Ben"}
@string{MWei = "Wei, M."}
@string{YWei = "Wei, Yen"}
@string{JWeissenbach = "Weissenbach, J."}
@string{GWen = "Wen, G."}
@string{MWen = "Wen, M."}
@string{JWetter = "Wetter, J."}
+@string{EPWhite = "White, Ethan P."}
@string{AWhittaker = "Whittaker, A."}
@string{YWickramasinghe = "Wickramasinghe, H. K."}
@string{RWides = "Wides, R."}
@string{MWilliams = "Williams, M."}
@string{SWilliams = "Williams, S."}
@string{MWilmanns = "Wilmanns, Matthias"}
+@string{GWilson = "Wilson, Greg"}
+@string{PWilson = "Wilson, Paul"}
@string{RKWilson = "Wilson, R. K."}
@string{SWilson = "Wilson, Scott"}
@string{SWindsor = "Windsor, S."}
@string{EWinn-Deen = "Winn-Deen, E."}
+@string{NWirth = "Wirth, Niklaus"}
@string{CWitt = "Witt, Christian"}
@string{KWolfe = "Wolfe, K."}
@string{TGWolfsberg = "Wolfsberg, T. G."}
@string{XZhu = "Zhu, X."}
@string{YJZhu = "Zhu, Ying-Jie"}
@string{WZhuang = "Zhuang, Wei"}
+@string{JZiegler = "Ziegler, J.G."}
@string{NZinder = "Zinder, N."}
@string{RCZinober = "Zinober, Rebecca C."}
@string{JZlatanova = "Zlatanova, Jordanka"}
title = "Statistics of Extremes",
year = 1958,
publisher = CUP,
- address = "New York",
- note = "TODO: read",
+ address = "New York",
+ note = "TODO: read",
}
@misc{ wikipedia:GEV,
year = 2007,
month = jan,
day = 23,
- journal = ACSChemBiol,
+ journal = ACS:ChemBiol,
volume = 2,
number = 1,
pages = "53--61",
title = "Designing an extracellular matrix protein with enhanced mechanical
stability",
year = 2007,
- month = jun,
- day = 5,
+ month = jun,
+ day = 5,
journal = PNAS,
volume = 104,
number = 23,
number = 4,
pages = "851–854",
year = 2007,
- month = aug,
- day = 24,
+ month = aug,
+ day = 24,
issn = "0022-2836",
doi = "10.1016/j.jmb.2007.06.015",
url = "http://www.sciencedirect.com/science/article/pii/S0022283607007966",
the deviation of the predicted behavior with respect to the
experimental data.",
language = "eng",
-}
+}
@article { measey09,
- author = TMeasey #" and "# KBSmith #" and "# SDecatur #" and "#
+ author = TMeasey #" and "# KBSmith #" and "# SDecatur #" and "#
LZhao #" and "# GYang #" and "# RSchweitzerStenner,
title = "Self-aggregation of a polyalanine octamer promoted by
its {C}-terminal tyrosine and probed by a strongly
them to unfold single titin molecules over an order of magnitude
faster than previously reported with conventional cantilevers.",
ISSN = "0021-8979",
- issn_online = "1089-7550",
- doi = "10.1063/1.371039",
+ issn_online = "1089-7550",
+ doi = "10.1063/1.371039",
URL = "http://jap.aip.org/resource/1/japiau/v86/i4/p2258_s1",
language = "eng",
}
detection. Finally, a time of flight method that permits the
reconstruction of the optical potential well was demonstrated.",
ISSN = "0034-6748",
- issn_online = "1089-7623",
+ issn_online = "1089-7623",
doi = "10.1063/1.1460929",
URL = "http://rsi.aip.org/resource/1/rsinak/v73/i4/p1687_s1",
language = "eng",
volume = 49,
number = 23,
pages = "1587--1589",
- abstract = "A new high‐resolution profilometer has been demonstrated
- based upon a noncontacting near‐field thermal probe. The thermal
- probe consists of a thermocouple sensor with dimensions
- approaching 100 nm. Profiling is achieved by scanning the heated
- sensor above but close to the surface of a solid. The conduction
- of heat between tip and sample via the air provides a means for
- maintaining the sample spacing constant during the lateral
- scan. The large difference in thermal properties between air and
- solids makes the profiling technique essentially independent of
- the material properties of the solid. Noncontact profiling of
- resist and metal films has shown a lateral resolution of 100 nm
- and a depth solution of 3 nm. The basic theory of the new probe is
- described and the results presented.",
- issn = "0003-6951",
- issn_online = "1077-3118",
+ abstract = "A new high‐resolution profilometer has been demonstrated
+ based upon a noncontacting near‐field thermal probe. The thermal
+ probe consists of a thermocouple sensor with dimensions
+ approaching 100 nm. Profiling is achieved by scanning the heated
+ sensor above but close to the surface of a solid. The conduction
+ of heat between tip and sample via the air provides a means for
+ maintaining the sample spacing constant during the lateral
+ scan. The large difference in thermal properties between air and
+ solids makes the profiling technique essentially independent of
+ the material properties of the solid. Noncontact profiling of
+ resist and metal films has shown a lateral resolution of 100 nm
+ and a depth solution of 3 nm. The basic theory of the new probe is
+ described and the results presented.",
+ issn = "0003-6951",
+ issn_online = "1077-3118",
doi = "10.1063/1.97288",
URL = "http://apl.aip.org/resource/1/applab/v49/i23/p1587_s1",
language = "eng",
volume = 61,
number = 10,
pages = "4723--4729",
- abstract = "A modified version of the atomic force microscope is
- introduced that enables a precise measurement of the force between
- a tip and a sample over a tip‐sample distance range of 30--150
- \AA. As an application, the force signal is used to maintain the
- tip‐sample spacing constant, so that profiling can be achieved
- with a spatial resolution of 50 \AA. A second scheme allows the
- simultaneous measurement of force and surface profile; this scheme
- has been used to obtain material-dependent information from
- surfaces of electronic materials.",
- issn = "0021-8979",
- issn_online = "1089-7550",
+ abstract = "A modified version of the atomic force microscope is
+ introduced that enables a precise measurement of the force between
+ a tip and a sample over a tip‐sample distance range of 30--150
+ \AA. As an application, the force signal is used to maintain the
+ tip‐sample spacing constant, so that profiling can be achieved
+ with a spatial resolution of 50 \AA. A second scheme allows the
+ simultaneous measurement of force and surface profile; this scheme
+ has been used to obtain material-dependent information from
+ surfaces of electronic materials.",
+ issn = "0021-8979",
+ issn_online = "1089-7550",
doi = "10.1063/1.338807",
URL = "http://jap.aip.org/resource/1/japiau/v61/i10/p4723_s1",
language = "eng",
volume = 53,
number = 12,
pages = "1045--1047",
- abstract = "A sensitive and simple optical method for detecting the
- cantilever deflection in atomic force microscopy is described. The
- method was incorporated in an atomic force microscope, and imaging
- and force measurements, in ultrahigh vacuum, were successfully
- performed.",
- issn = "0003-6951",
- issn_online = "1077-3118",
+ abstract = "A sensitive and simple optical method for detecting the
+ cantilever deflection in atomic force microscopy is described. The
+ method was incorporated in an atomic force microscope, and imaging
+ and force measurements, in ultrahigh vacuum, were successfully
+ performed.",
+ issn = "0003-6951",
+ issn_online = "1077-3118",
doi = "10.1063/1.100061",
URL = "http://apl.aip.org/resource/1/applab/v53/i12/p1045_s1",
language = "eng",
}
+
+@book{ dijkstra70,
+ author = EDijkstra,
+ title = {Notes on Structured Programming},
+ year = 1970,
+ month = apr,
+ url = {http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD249.PDF},
+ publisher = THEMath,
+ note = {T.H. Report 70-WSK-03},
+}
+
+@article{ wirth74,
+ author = NWirth,
+ title = {On the Composition of Well-Structured Programs},
+ journal = ACM:CSur,
+ year = 1974,
+ month = dec,
+ volume = 6,
+ number = 4,
+ pages = {247--259},
+ numpages = {13},
+ issn = {0360-0300},
+ doi = {10.1145/356635.356639},
+ url = {http://doi.acm.org/10.1145/356635.356639},
+ publisher = ACM,
+ address = {New York, NY, USA},
+}
+
+@article{ shneiderman79,
+ author = BShneiderman #" and "# RMayer,
+ title = {Syntactic/semantic interactions in programmer behavior: A
+ model and experimental results},
+ year = 1979,
+ journal = IJCIS,
+ volume = 8,
+ number = 3,
+ pages = {219--238},
+ issn = {0091-7036},
+ doi = {10.1007/BF00977789},
+ url = {http://dx.doi.org/10.1007/BF00977789},
+ publisher = KAPPP,
+ keywords = {Programming; programming languages; cognitive models;
+ program composition; program comprehension; debugging;
+ modification; learning; education; information processing},
+ language = {English},
+}
+
+@article{ hughes89,
+ author = JHughes,
+ title = {Why Functional Programming Matters},
+ journal = CJ,
+ year = 1989,
+ volume = 32,
+ number = 2,
+ pages = {98--107},
+ doi = {10.1093/comjnl/32.2.98},
+ URL = {http://comjnl.oxfordjournals.org/content/32/2/98.abstract},
+ eprint = {http://comjnl.oxfordjournals.org/content/32/2/98.full.pdf+html},
+ abstract ={As software becomes more and more complex, it is more and
+ more important to structure it well. Well-structured software is
+ easy to write, easy to debug, and provides a collection of modules
+ that can be re-used to reduce future programming
+ costs. Conventional languages place conceptual limits on the way
+ problems can be modularised. Functional languages push those
+ limits back. In this paper we show that two features of functional
+ languages in particular, higher-order functions and lazy
+ evaluation, can contribute greatly to modularity. As examples, we
+ manipulate lists and trees, program several numerical algorithms,
+ and implement the alpha-beta heuristics (an Artificial
+ Intelligence algorithm used in game-playing programs). Since
+ modularity is the key to successful programming, functional
+ languages are vitally important to the real world.},
+}
+
+@article{ hilburn93,
+ author = THilburn,
+ title = {A top-down approach to teaching an introductory computer science course},
+ journal = ACM:SIGCSE,
+ year = 1993,
+ month = mar,
+ volume = 25,
+ number = 1,
+ issn = {0097-8418},
+ pages = {58--62},
+ numpages = 5,
+ doi = {10.1145/169073.169349},
+ url = {http://doi.acm.org/10.1145/169073.169349},
+ acmid = {169349},
+ publisher = ACM,
+ address = {New York, NY, USA},
+}
+
+@book{ brooks95,
+ author = FBrooks,
+ title = {The mythical man-month},
+ edition = {20$^\text{th}$ anniversary},
+ year = 1995,
+ isbn = {0-201-83595-9},
+ publisher = AW,
+ address = {Boston, MA, USA},
+ url = {http://dl.acm.org/citation.cfm?id=207583},
+ note = {First published in 1975},
+}
+
+@inproceedings{ claerbout92,
+ author = JClaerbout #" and "# MKarrenbach,
+ title = {Electronic documents give reproducible research a new meaning},
+ booktitle = {SEG Technical Program Expanded Abstracts 1992},
+ chapter = 161,
+ year = 1992,
+ pages = {601--604},
+ doi = {10.1190/1.1822162},
+ issn = {1052-3812},
+ publisher = SEG,
+ url = {http://library.seg.org/doi/abs/10.1190/1.1822162},
+ eprint = {http://sepwww.stanford.edu/doku.php?id=sep:research:reproducible:seg92},
+}
+
+@incollection{ buckheit95,
+ author = JBuckheit #" and "# DDonoho,
+ title = {WaveLab and Reproducible Research},
+ booktitle = {Wavelets and Statistics},
+ series = {Lecture Notes in Statistics},
+ editor = AAntoniadis #" and "# GOppenheim,
+ year = 1995,
+ volume = 103,
+ pages = {55--81},
+ isbn = {978-0-387-94564-4},
+ doi = {10.1007/978-1-4612-2544-7_5},
+ url = {http://dx.doi.org/10.1007/978-1-4612-2544-7_5},
+ eprint = {http://www-stat.stanford.edu/~wavelab/Wavelab_850/wavelab.pdf},
+ publisher = SPRINGER,
+ language = {English},
+}
+
+@article{ schwab00,
+ author = MSchwab #" and "# MKarrenbach #" and "# JClaerbout,
+ title = {Making scientific computations reproducible},
+ journal = CSE,
+ year = 2000,
+ month = {November--December},
+ volume = 2,
+ number = 6,
+ pages = {61--67},
+ doi = {10.1109/5992.881708},
+ ISSN = {1521-9615},
+ keywords = {document handling;file organisation;natural sciences
+ computing;research and development
+ management;ReDoc;authors;computational results;reproducible
+ scientific computations;research paper;software filing
+ system;standardized rules;Computer
+ interfaces;Documentation;Electronic
+ publishing;Laboratories;Organizing;Reproducibility of
+ results;Software maintenance;Software systems;Software
+ testing;Technological innovation},
+ abstract = {To verify a research paper's computational results,
+ readers typically have to recreate them from scratch. ReDoc is a
+ simple software filing system for authors that lets readers easily
+ reproduce computational results using standardized rules and
+ commands},
+}
+
+@article{ wilson06a,
+ author = GWilson,
+ title = {Where's the Real Bottleneck in Scientific Computing?},
+ journal = AS,
+ year = 2006,
+ month = {January--February},
+}
+
+@article{ wilson06b,
+ author = GWilson ,
+ title = {Software Carpentry: Getting Scientists to Write Better
+ Code by Making Them More Productive},
+ journal = CSE,
+ year = 2006,
+ month = {November--December},
+}
+
+@article{ vandewalle09,
+ author = PVandewalle #" and "# JKovacevic #" and "# MVetterli ,
+ title = {Reproducible Research in Signal Processing - What, why, and how},
+ journal = IEEE:SPM,
+ year = 2009,
+ month = may,
+ volume = 26,
+ number = 3,
+ pages = {37--47},
+ doi = {10.1109/MSP.2009.932122},
+ issn = {1053-5888},
+ url = {http://rr.epfl.ch/17/},
+ eprint = {http://rr.epfl.ch/17/1/VandewalleKV09.pdf},
+ keywords={research and development;signal processing;high-quality
+ reviewing process;large data set;reproducible research;signal
+ processing;win-win situation;Advertising;Digital signal
+ processing;Education;Programming;Reproducibility of
+ results;Scholarships;Signal processing;Signal processing
+ algorithms;Testing;Wikipedia},
+ abstract = {Have you ever tried to reproduce the results presented
+ in a research paper? For many of our current publications, this
+ would unfortunately be a challenging task. For a computational
+ algorithm, details such as the exact data set, initialization or
+ termination procedures, and precise parameter values are often
+ omitted in the publication for various reasons, such as a lack of
+ space, a lack of self-discipline, or an apparent lack of interest
+ to the readers, to name a few. This makes it difficult, if not
+ impossible, for someone else to obtain the same results. In our
+ experience, it is often even worse as even we are not always able
+ to reproduce our own experiments, making it difficult to answer
+ questions from colleagues about details. Following are some
+ examples of e-mails we have received: ``I just read your paper
+ X. It is very completely described, however I am confused by
+ Y. Could you provide the implementation code to me for reference
+ if possible?'' ``Hi! I am also working on a project related to
+ X. I have implemented your algorithm but cannot get the same
+ results as described in your paper. Which values should I use for
+ parameters Y and Z?''},
+}
+
+@article{ aruliah12,
+ author = DAruliah #" and "# CTBrown #" and "# MPCHong #" and "#
+ MDavis #" and "# RTGuy #" and "# SHaddock #" and "# KHuff #" and "#
+ IMitchell #" and "# MPlumbley #" and "# BWaugh #" and "#
+ EPWhite #" and "# GWilson #" and "# PWilson,
+ title = {Best Practices for Scientific Computing},
+ journal = CoRR,
+ volume = {abs/1210.0530},
+ year = 2012,
+ month = nov,
+ day = 29,
+ numpages = 6,
+ url = {http://arxiv.org/abs/1210.0530},
+ eprint = {http://arxiv.org/pdf/1210.0530v3},
+ note = {v3: Thu, 29 Nov 2012 19:28:27 GMT},
+}
+
+@article{ ziegler42,
+ author = JZiegler #" and "# NNichols,
+ title = {Optimum Settings for Automatic Controllers},
+ journal = TASME,
+ year = 1942,
+ month = nov,
+ volume = 64,
+ pages = {759--765},
+ url = {http://www.driedger.ca/Z-N/Z-N.html},
+ eprint = {http://www.driedger.ca/Z-N/Z-n.pdf},
+}
+
+@article{ cohen53,
+ author = GHCohen #" and "# GACoon,
+ title = {Theoretical considerations of retarded control},
+ year = 1953,
+ journal = TASME,
+ volume = 75,
+ pages = {827--834},
+}
+
+@article{ wang95,
+ author = FSWang #" and "# WSJuang #" and "# CTChan,
+ title = {Optimal tuning of {PID} controllers for single and
+ cascade control loops},
+ year = 1995,
+ journal = CEC,
+ volume = 132,
+ number = 1,
+ pages = {15--34},
+ publisher = GordonBreach,
+ issn = {0098-6445},
+ doi = {10.1080/00986449508936294},
+ url = {http://www.tandfonline.com/doi/abs/10.1080/00986449508936294},
+ keywords = {process control; cascade control; controller tuning},
+ abstract = {Design of one parameter tuning of three-mode PID
+ controller was developed in this present study. The integral time
+ and the derivative time of the controller were expressed in terms
+ of the time constant and dead time of the process. Only the
+ proportional gain was observed to be dependent on the implemented
+ tunable parameter in which the stable region could be
+ predetermined by the Routh test. Extension of the concept towards
+ designing cascade PID controllers was straightforward such that
+ only two parameters for the inner and outer PID controllers
+ required to be tuned, respectively. The optimal tuning correlative
+ formulas of the proportional gain for single and cascade control
+ systems were obtained by the least square regression method.},
+}
+
+@article{ astrom93,
+ author = KAstrom #" and "# THagglund #" and "# CCHang #" and "# WKHo,
+ title = {Automatic tuning and adaptation for {PID} controllers---a survey},
+ journal = CEP,
+ year = 1993,
+ volume = 1,
+ number = 4,
+ pages = {699--714},
+ issn = "0967-0661",
+ doi = "10.1016/0967-0661(93)91394-C",
+ url = "http://www.sciencedirect.com/science/article/pii/096706619391394C",
+ keywords = {Adaptive control},
+ keywords = {automatic tuning},
+ keywords = {gain scheduling},
+ keywords = {{PID} control},
+ abstract = {Adaptive techniques such as gain scheduling, automatic
+ tuning and continuous adaptation have been used in industrial
+ single-loop controllers for about ten years. This paper gives a
+ survey of the different adaptive techniques, the underlying
+ process models and control designs. An overview of industrial
+ products is also presented, which includes a fairly detailed
+ investigation of four different adaptive single-loop
+ controllers.},
+}
\author{William Trevor King}
\title{Open source single molecule force spectroscopy}
-\DUTmonth{July}
-\DUTyear{2012}
+\DUTmonth{May}
+\DUTyear{2013}
\degree{Doctor of Philosophy}
\advisor{Guoliang Yang, Ph.D.}
\advisor{Louis Cruz Cruz, Ph.D.}
\bibliography{%
apparatus/main,%
% sawsim/main,% currently empty
+ pyafm/main,%
cantilever-calib/main,%
packaging/main,%
figures/main,%
plain-text histogram file:
\begin{center}
\begin{spacing}{1}
-\begin{Verbatim}
+\begin{Verbatim}[commandchars=\\\{\}]
#HISTOGRAM: -v 6e-7
#Force (N) Unfolding events
1.4e-10 1
For example, to compare the experimental histograms listed above with
simulated data over a 50-by-50 grid of $k_{u0}$ and $\Delta x$, you
would use something like
-\begin{Verbatim}[samepage]
+\begin{minted}[samepage]{console}
$ sawsim_hist_scan.py -f '-s cantilever,hooke,0.05 -N1 -s folded,null -N8
-s "unfolded,wlc,{0.39e-9,28e-9}" -k "folded,unfolded,bell,{%g,x%g}"
-q folded' -r '[1e-5,1e-3,50],[0.1e-9,1e-9,50]' --logx histograms.txt
-\end{Verbatim}
+\end{minted}
That's a bit of a mouthful, so let's break it down. Without the
\sawsim\ template (\Verb+-f ...+), we can focus on the comparison
options:
-\begin{Verbatim}[samepage]
+\begin{minted}[samepage]{console}
$ sawsim_hist_scan.py \ldots -r '[1e-5,1e-3,50],[0.1e-9,1e-9,50]' --logx histograms.txt
-\end{Verbatim}
+\end{minted}
This sets up a two-parameter sweep, with the first parameter going
from $1\E{-5}$ to $1\E{-3}$ in 50 logarithmic steps, and the second
going from $0.1\E{-9}$ to $1\E{-9}$ in 50 linear steps. The