From: W. Trevor King Date: Wed, 1 May 2013 20:47:00 +0000 (-0400) Subject: pyafm: Fill in the chapter on my control stack X-Git-Tag: v1.0~275 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f98f56987475952d80162db830c0aafcafa570ea;p=thesis.git pyafm: Fill in the chapter on my control stack Use minted for syntax highlighting in code excerpts (yay pygments!). --- diff --git a/src/figures/binary/pulling_chan_1_2d22.png b/src/figures/binary/pulling_chan_1_2d22.png new file mode 100644 index 0000000..a3507d2 Binary files /dev/null and b/src/figures/binary/pulling_chan_1_2d22.png differ diff --git a/src/local_cmmds.tex b/src/local_cmmds.tex index debdbbc..36131c3 100644 --- a/src/local_cmmds.tex +++ b/src/local_cmmds.tex @@ -95,25 +95,47 @@ \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}} diff --git a/src/packages.tex b/src/packages.tex index 12df7cb..c03f034 100644 --- a/src/packages.tex +++ b/src/packages.tex @@ -11,6 +11,9 @@ \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} @@ -50,6 +53,10 @@ \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} @@ -64,16 +71,11 @@ \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} diff --git a/src/packaging/main.bib b/src/packaging/main.bib index a5521b3..736d67f 100644 --- a/src/packaging/main.bib +++ b/src/packaging/main.bib @@ -109,6 +109,14 @@ 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", @@ -148,3 +156,11 @@ 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", +} diff --git a/src/pyafm/auxiliary.tex b/src/pyafm/auxiliary.tex index 36c3585..625688c 100644 --- a/src/pyafm/auxiliary.tex +++ b/src/pyafm/auxiliary.tex @@ -1,4 +1,139 @@ -\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.} diff --git a/src/pyafm/conclusions.tex b/src/pyafm/conclusions.tex index ec0bd4d..803450d 100644 --- a/src/pyafm/conclusions.tex +++ b/src/pyafm/conclusions.tex @@ -1 +1,38 @@ \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. diff --git a/src/pyafm/discussion.tex b/src/pyafm/discussion.tex index 62f54a3..0dde6f6 100644 --- a/src/pyafm/discussion.tex +++ b/src/pyafm/discussion.tex @@ -1 +1,122 @@ \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. diff --git a/src/pyafm/frameworks.tex b/src/pyafm/frameworks.tex index 9050eeb..1f102f3 100644 --- a/src/pyafm/frameworks.tex +++ b/src/pyafm/frameworks.tex @@ -1,3 +1,182 @@ \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. diff --git a/src/pyafm/main.bib b/src/pyafm/main.bib new file mode 100644 index 0000000..8312c77 --- /dev/null +++ b/src/pyafm/main.bib @@ -0,0 +1,162 @@ +@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.}, +} diff --git a/src/pyafm/main.tex b/src/pyafm/main.tex index 18e987e..fd70d73 100644 --- a/src/pyafm/main.tex +++ b/src/pyafm/main.tex @@ -1,6 +1,24 @@ -\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} diff --git a/src/pyafm/stack.tex b/src/pyafm/stack.tex index 79da349..4295422 100644 --- a/src/pyafm/stack.tex +++ b/src/pyafm/stack.tex @@ -1,4 +1,357 @@ \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} diff --git a/src/root.bib b/src/root.bib index 6f09433..ad5e2bf 100644 --- a/src/root.bib +++ b/src/root.bib @@ -1,5 +1,10 @@ @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"} @@ -7,7 +12,8 @@ @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"} @@ -18,6 +24,7 @@ @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"} @@ -27,10 +34,12 @@ @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"} @@ -109,12 +118,15 @@ @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"} @@ -136,11 +148,12 @@ @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"} @@ -149,6 +162,7 @@ @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"} @@ -168,6 +182,7 @@ @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"} @@ -176,11 +191,15 @@ @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"} @@ -196,6 +215,7 @@ @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."} @@ -211,6 +231,7 @@ @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."} @@ -219,6 +240,7 @@ @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"} @@ -309,6 +331,7 @@ @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."} @@ -327,14 +350,18 @@ @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."} @@ -361,17 +388,20 @@ @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."} @@ -385,6 +415,8 @@ @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"} @@ -393,11 +425,13 @@ @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."} @@ -441,6 +475,7 @@ @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"} @@ -451,6 +486,7 @@ @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."} @@ -471,11 +507,13 @@ @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"} @@ -582,6 +620,7 @@ @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."} @@ -608,6 +647,7 @@ @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."} @@ -659,6 +699,7 @@ @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."} @@ -682,6 +723,7 @@ @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."} @@ -712,6 +754,7 @@ @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."} @@ -796,6 +839,7 @@ @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"} @@ -821,6 +865,7 @@ @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."} @@ -841,6 +886,7 @@ @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."} @@ -882,7 +928,10 @@ @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"} @@ -896,6 +945,7 @@ @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"} @@ -914,12 +964,14 @@ @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."} @@ -932,6 +984,7 @@ @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."} @@ -942,12 +995,14 @@ @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."} @@ -959,10 +1014,13 @@ @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."} @@ -1019,6 +1077,7 @@ @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"} @@ -1054,8 +1113,8 @@ title = "Statistics of Extremes", year = 1958, publisher = CUP, - address = "New York", - note = "TODO: read", + address = "New York", + note = "TODO: read", } @misc{ wikipedia:GEV, @@ -2186,7 +2245,7 @@ year = 2007, month = jan, day = 23, - journal = ACSChemBiol, + journal = ACS:ChemBiol, volume = 2, number = 1, pages = "53--61", @@ -5349,8 +5408,8 @@ 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, @@ -5391,8 +5450,8 @@ 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", @@ -7758,10 +7817,10 @@ 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 @@ -8782,8 +8841,8 @@ 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", } @@ -8807,7 +8866,7 @@ 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", @@ -8849,21 +8908,21 @@ 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", @@ -8880,17 +8939,17 @@ 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", @@ -8906,14 +8965,323 @@ 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.}, +} diff --git a/src/root.tex b/src/root.tex index 1ecaa88..c914ea4 100644 --- a/src/root.tex +++ b/src/root.tex @@ -24,8 +24,8 @@ \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.} @@ -74,6 +74,7 @@ defaultpen(fontsize(10)); // match drexel-thesis's default 10pt font size \bibliography{% apparatus/main,% % sawsim/main,% currently empty + pyafm/main,% cantilever-calib/main,% packaging/main,% figures/main,% diff --git a/src/sawsim/discussion.tex b/src/sawsim/discussion.tex index f698578..ae199d1 100644 --- a/src/sawsim/discussion.tex +++ b/src/sawsim/discussion.tex @@ -445,7 +445,7 @@ makes full use of your experimental histograms, which you specify in a 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 @@ -482,17 +482,17 @@ command line interfaces for generating and manipulating \sawsim\ runs. 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