Fixes suggested by my mom (Lynn Duncan)
[thesis.git] / src / pyafm / frameworks.tex
1 \section{Analog input output frameworks}
2 \label{sec:aio-frameworks}
3
4 For many users, computers are fairly self-contained systems.  Users
5 read and write files, using a variety of editors, and share
6 information between computers via networked connections.  Using
7 computers to control and monitor arbitrary physical processes is
8 common in the scientific community and industry, but less so in the
9 the general consumer market.  This means that interfaces between the
10 digital and analog worlds haven't seen the focused development in the
11 FLOSS community that more mainstream problem areas have received.  In
12 this section I'll discuss a few possible options---both open and
13 proprietary---in the context of my experiment control stack.
14
15 \subsection{LabVIEW}
16 \label{sec:labview}
17
18 National Instruments\citep{national-instruments} is a major player in
19 the experiment control and data aquisition market.  On the hardware
20 side, they produce a wide range of DAQ cards.  On the software side,
21 they produce LabVIEW\citep{labview}, a graphical programming language
22 designed to make writing control and aquisition experiments
23 straightforward.  Both LabVIEW and NI-DAQmx cards are ubiquitous in
24 scientific computing; in the four research labs I've worked in over my
25 career, every lab has used both.  By the time I joined Prof.~Yang's
26 lab, I'd been using LabVIEW for years, and had become familiar with
27 its two major limitations: name based linking and a binary file
28 format.
29 %
30 \nomenclature{DAQ}{Data acquisition.  Although the term only refers to
31   input, it is sometimes implicitly extended to include signal output
32   as well (for controlling experiments as well as measuring results).}
33
34 Programming in a graphical language is quite similar to programming in
35 a textual language.  In both, you reduce complexity by encapsulating
36 functional subroutines of your process, and then assembling those
37 subroutines in other, higher-level
38 subroutines\citep{dijkstra70,wirth74,shneiderman79,hughes89}.  This
39 means that the application level code can focus on application-level
40 task (approach the surface, wait for binding, \ldots) without getting
41 bogged down in the details (increment analog output channel zero in 5
42 bit steps until analog input channel exceeds 39322 bits).  In textual
43 languages like C or Python, you can use functions and libraries to
44 package the functional subroutines.  In LabVIEW, you package the
45 subroutines in \emph{virtual instruments} (VIs).
46
47 \nomenclature{VI}{Virtual instrument.  LabVIEW's analog to functions
48   for encapsulating subroutines.}
49
50 The problem comes when you want to update one of your subroutines.
51 LabVIEW VIs are linked dynamically by VI name\citep{ni-vi-management},
52 so there was no easy way to swap a new version of the VI into your
53 application for testing without renaming the subroutine.  With the
54 Project Explorer (new in LabVIEW 8.0\citep{ni-vi-management}, released
55 2005), these renames became easier.  However, throughout my time in
56 the Yang lab, the Windows machines all ran LabVIEW 7.1 (released in
57 2004).
58
59 Because of difficulties with name-based VI linking and the relative
60 inexperience of many scientists in the maintenance benefits of modular
61 programming\citep{hilburn93,wilson06b}, LabVIEW code often ends up
62 without a clean separation between high-level and low-level tasks
63 (\cref{fig:labview}).  This lack of structure makes it difficult to
64 reuse existing code to address similar tasks.
65
66 \begin{figure}
67   \begin{center}
68     \includegraphics[width=0.8\textwidth]{%
69       figures/binary/pulling_chan_1_2d22.png}
70     \caption{An excerpt from the main frame of the LabVIEW stack.
71       This frame codes for the velocity-clamped pull phase of a
72       push--bind--pull experiment.\label{fig:labview}}
73   \end{center}
74 \end{figure}
75
76 The second obstacle to maintaining LabVIEW code is the binary file
77 format for VIs.  The established method for recording software history
78 is to use a version control system (VCS), which records versions of
79 the project in a repository.  Each change to the project is committed
80 to the repository with some associated metadata (timestamp, committer
81 name, explanatory message, \ldots).  Users can access this database to
82 recover earlier versions of the project.  For example, if you find a
83 bug in your package, you can use your VCS to determine if that bug
84 affected the data you gathered six months ago.
85
86 There are a number of FLOSS version control systems in common use
87 (Git, Mercurial, and Subversion, \dots), but in order to track and
88 merge \emph{changes}, they need a way to calculate the difference
89 between two versions of a given file.  For textual programming
90 languages, the line-based textual differences used by VCSs work
91 extremely well, but for binary file formats, performance decreases
92 drastically.  There are third-party merge tools\citep{ni-merge} for
93 LabVIEW, but the tools are not officially supported.
94
95 \nomenclature{VCS}{Version control system.  A system for tracking
96   project development by recording versions of the project in a
97   repository.}
98 \nomenclature{FLOSS}{Free, Libre, and Open Source (software).  A
99   catch-all for copyleft licensing.}
100
101 While National Instruments seems to put a reasonable amount of effort
102 into maintaining backwards compatibility, long term archival of binary
103 formats is still a difficult problem.  For example, our legacy LabVIEW
104 7.1 installation is no longer compatible with recent LabVIEW releases.
105 Support for the releases is so low, that without access to the old
106 LabVIEW release, you may not even be able to determine which version
107 of LabVIEW your VI corresponds to.  One officially suggested method
108 for extracting the version from an older VI is\citep{ni-vi-version}:
109
110 \begin{quote}
111   Open the VI in the earliest version on your computer.  If an error
112   occurs, the VI is saved in a later version.  Close the VI and repeat
113   this process for the next version of LabVIEW.  The first version
114   that opens a VI without any error is the version in which the VI is
115   compiled.
116 \end{quote}
117
118 This does not inspire confidence in an ability to extract experiment
119 control software from VIs after a decade of archival.
120
121 \subsection{NI-DAQmx}
122 \label{sec:ni-daqmx}
123
124 After deciding to avoid LabVIEW, my first attempt at writing an
125 experiment control framework involved calling National Instrument's
126 DAQmx library from C\citep{ni-daqmx} (\cref{fig:ni-daqmx}).  I spent
127 most of 2007 working this framework, using \citetalias{cygwin} as the
128 development environment.  Inspired by \citetalias{epics}, I built a
129 message passing server with experiment control and hardware interface
130 modules connected via sockets.
131
132 As the experiment server evolved, I started running into problems.
133 The overhead of sending all the data through sockets to generic
134 hardware interface modules was larger than I had na\"{\i}vely
135 expected.  I also had trouble with multithreaded socket code on
136 Cygwin, and decided to drop Microsoft Windows altogether in favor of
137 a FLOSS operating system.
138
139 \begin{figure}
140   \begin{center}
141 \begin{minted}{c}
142 static int set_digital_output_data(DIGITAL_OUTPUT *d, unsigned int data)
143 {
144   d->data = (uInt32) data;
145   DAQmxErrChk_struct( Write_WriteDigPort(d->taskHandle, d->data) );
146  Error:
147   if (d->error != 0) {
148     CHK( close_digital_output(d) );
149     M_EXIT(FAILURE, "Error in NIDAQ stepper output\n");
150   }
151   CHK( nsleep(100) );
152   PING(1);
153   return SUCCESS;
154 }
155 \end{minted}
156     \caption{An excerpt from the digital output module of my
157       experiment server stack.  Most of the C code is error checking
158       and tracing macros.  The hardcoded delay time and
159       stepper-specific error message are symptoms of my previously
160       poor programming practices.  \imint{c}|Write_WriteDigPort| is a
161       simplifying wrapper around \imint{c}|DAQmxWriteDigitalU32| from
162       the examples bundled with NI-DAQmx.\label{fig:ni-daqmx}}
163   \end{center}
164 \end{figure}
165
166 \subsection{Comedi}
167 \label{sec:comedi}
168
169 After transitioning to Linux-based systems, I could no longer use
170 NI-DAQmx (which only supported Microsoft Windows).  Luckily, the
171 \citetalias{comedi} project already provided FLOSS driver code for our
172 DAQ card (an NI-PCI-6052E).  Comedi (from ``Control and Measurement
173 Device Interface'') is a general purpose library for interacting with
174 DAQ devices, and supports a wide range of hardware.  When I moved to
175 Comedi, it was a stand-alone kernel module, but since November 2008 it
176 has been included in the Linux source as a staging driver.
177
178 Comedi development goes back to 2000, so by the time I arrived things
179 were already pretty stable.  I submitted
180 \href{http://comedi.org/git?p=comedi/comedi.git;a=commit;h=4284c2266987ad08a26f2758cd09fef06d1ce3cf}{a
181   small patch} to support simultaneous analog input/output triggering
182 on National Instruments cards, and started building my stack.