From 9d8496be4cf2719c3dd7ca2a4b4de91ad4abeeb3 Mon Sep 17 00:00:00 2001
From: Blaise Thompson <blaise@untzag.com>
Date: Fri, 30 Mar 2018 13:54:43 -0500
Subject: 2018-03-30 13:54

---
 acquisition/chapter.tex | 153 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 137 insertions(+), 16 deletions(-)

(limited to 'acquisition/chapter.tex')

diff --git a/acquisition/chapter.tex b/acquisition/chapter.tex
index 832e698..bd08edd 100644
--- a/acquisition/chapter.tex
+++ b/acquisition/chapter.tex
@@ -9,28 +9,99 @@
 
 \clearpage
 
-In the Wright Group, \gls{PyCMDS} replaces the old acquisition softwares `ps control', written by
-Kent Meyer and `Control for Lots of Research in Spectroscopy' written by Schuyler Kain.
-
-PyCMDS directly addresses the hardware during experiments.
+MR-CMDS relies on a good number of instrumental capabilities.  %
+Fundamentally, MR-CMDS is about delivering multiple pulses of light to a given sample.  %
+The frequency and relative arrival time (delay) of each pulse must be scanned in the context of a
+basic multidimensional experiment.  %
+Scanning frequency requires using motors to change crystal angles and other optics within Optical
+Parametric Amplifiers (OPAs).  %
+Scanning delay typically involves moving mirrors very small distances such that the optical path
+length of certain beam-lines changes.  %
+In addition to these ``first-order'' controls, the power of MR-CMDS is enhanced with additional
+control of pulse intensity and polarization.  % TODO: citations to motivate this 'enhancement'
+Each of these is an optomechanical device.  %
+An automated monchromator is typically used to spectrally resolve or isolate output signal.  %
+
+An acquisition in MR-CMDS typically means going to a whole series of different positions.  %
+As an example, a three-dimensional ``movie'' might be collected in the following way:
+\begin{codefragment}{python, label=aqn:lst:psuedoaqn}
+w1_points = [14300, 14400, 14500, 14600, 14700]  # wn
+w2_points = [14100, 14200, 14300, 14400, 14500, 14600, 14700]  # wn
+d2_points = [100, 75, 50, 25, 0, 50, 75, 100, 125, 150, 175, 200]  # fs
+for w2 in w2_points:
+    set_w2(w2)
+    for w1 in w1_points:
+        set_w1(w1)
+        for d2 in d2_points:
+            set_d2(d2)
+            measure_signal()
+\end{codefragment}
+In this simple example, there are 5 \python{w1} destinations, 7 \phon{w2} destinations, and 12
+\python{d2} destinations, so there are a total of $5\times7\times12=420$ pixels in the
+three-dimensional scan.  %
+The acquisition software must set the hardware to each of these points and acquire data at each of
+them.  %
+Each hardware motion and signal measurement takes roughly one second, so this acquisition would
+take roughly 7 minutes to complete.  %
+In practice, real scans are composed of $\sim$100 to $\sim$100,000 pixels, and take between 1
+minute and one day to acquire.  %
+
+Because of the highly specialized nature of these experiments, MR-CMDS instruments typically
+require custom software to address all of simultaneous, repeated motor motion that a scan
+requires.  %
+Because MR-CMDS is really a family of techniques which require different kinds of motor motion,
+this acqusition software should be flexable enough to meet the creativity of its users.  %
+Furthermore, because MR-CMDS is a bleeding edge, rapidly evolving technique the instrumental
+software must be built in an extendable way to accommodate the ever-changing hardware
+configurations.  %
+In this chapter I describe how I built such an acquisition software.  %
 
 \section{Overview}  % =============================================================================
 
-PyCMDS has, through software improvements alone, dramatically lessened scan times...
+PyCMDS is a unified software for controlling hardware and collecting data in the Wright Group.  %
+It is written almost entirely in Python, with a graphical user interface (GUI) made using Qt.  %
+It is cross-platform, running on Linux, Windows and macOS.  %
+It is open source, developed on GitHub.  % TODO: cite PyCMDS on github
+PyCMDS is used to drive both of the MR-CMDS instruments maintained by the Wright Group: the ``fs
+table'', focused on semiconductor photophysics, and the ``ps table'', focused on molecular
+systems.  %
+In the Wright Group, \gls{PyCMDS} replaces the old acquisition softwares `ps control', ritten by
+Kent Meyer and `Control for Lots of Research in Spectroscopy' written by Schuyler Kain.
 
-\begin{ditemize}
-  \item simultaneous motor motion
-	\item digital signal processing  % TODO: reference section when it exists
-	\item ideal axis positions \ref{acq:sec:ideal_axis_positions}
-\end{ditemize}
+When PyCMDS starts up, the GUI is constructed out of modules depending on which hardware and
+sensors the user has instructed the program to address.  %
+A screenshot of the PyCMDS GUI, running on the fs table, is shown in
+\autoref{aqn:fig:pycmds_screenshot}.  %
+On the left hand there is a single column displaying the current positions for all loaded
+hardware.  %
+Users may enter new destinations and hit the ``SET'' button.  %
+Positions have units, which are changeable through the pull-down menu next to the control and
+display.  %
+Each hardware knows its own limits, displayed in a tool tip when hovering over the control.  %
+Users cannot type values outside of hardware limits into the controls.  %
+
+The large right-hand section is tabbed...
 
-% TODO: screenshot
+\begin{figure}
+  \caption{
+    TODO (PyCMDS screenshot, including limits in tool tip)
+  }
+  \label{aqn:fig:pycmds_screenshot}
+\end{figure}
 
-% TODO: modularity
+To perform an acquisition, a user goes to the SOMATIC tab and enters an item into the QUEUE...
 
-% TODO: n-dimensional scans...
+During the acquisition...
+Progress bar...
+Cannot hit SET...
+QUEUE states...
 
-% TODO: calibration
+\begin{figure}
+  \caption{
+    TODO (PyCMDS screenshot while acquiring a 2D delay scan)
+  }
+  \label{aqn:fig:pycmds_screenshot_during_scan}
+\end{figure}
 
 \section{Structure}  % ============================================================================
 
@@ -124,8 +195,56 @@ Note that multithreading is very different from multiprocessing.  %
 
 \subsection{High level objects}  % ----------------------------------------------------------------
 
-PyCMDS is made to be extended and developed by and for immature programmers, so it is crucial to
-create something that is less complicated...
+Towards the goal of stability and extensability, PyCMDS makes heavy use of abstraction and
+inheritance.  %
+
+Abstraction means that complex implementation details are hidden by simple interfaces.  %
+For example, consider the simple case of setting an OPA to a particular color.  %
+For OPAs in the Wright Group, this operation requires the following:
+\begin{ditemize}
+  \item Load the OPA tuning curve, find which motors must move.
+  \item Interpolate the discrete tuning curve, and evaluate that interpolated curve at the desired
+    destination.
+  \item Send each motor towards their new destination.
+  \item Wait for the motors to arrive, check that nothing has gone wrong.
+\end{ditemize}
+This is not even to mention the complexity of spawning and sending information between the main
+thread and working threads.  %
+Through abstraction, PyCMDS is able to wrap all this complexity into the \python{OPA} class and
+it's \python{set_position} method---so doing all of the operations above is as simple as
+\python{opa.set_position(1300, 'nm')}.  %
+Importantly, abstraction does not magically get rid of the complexity.  %
+It simply \emph{hides} the complexity so that it becomes tractable to write simple interfaces to
+accomplish complex things.  %
+
+PyCMDS implements abstraction through inheritance.  %
+In object oriented programming, inheritance is when one class is based on another.  %
+The \emph{child} class acquires all of the properties of the \emph{parent} class.  %
+The child class, then, can modify or extend the properties that it needs, without needing to
+re-implement the properties that it shares with the parent.  %
+Let's consider PyCMDS hardware again.  %
+Every single unique hardware in PyCMDS lives in it's own worker thread, so the basic problem of
+information transfer through queues and Mutexes is shared between them.  %
+A \python{Hardware} class which is parent to \emph{all} hardwares can define the methods and
+attributes necessary to abstract this basic thread communication issue.  %
+Every type of delay stage addressed by PyCMDS needs to handle the basic task of translating between
+``natural'' units (femtosecond, picosecond, nanosecond) and ``native'' units (typically mm).  %
+They all need an attribute \python{zero_position}, in native units, and a method to do the
+conversion.  %
+A class common to all delay stages can abstract away all of these conversion details.  %
+In summary, an inheritance-based system for implementing delay stages might look like this:
+\begin{codefragment}{bash}
+Hardware  # implements basic thread control
+└── Delay  # implements conversion between natural and native units
+    ├── Homemade
+    ├── Thorlabs
+    └── Newport
+\end{codefragment}
+The powerful thing about this strategy is that the three driver-specific classes (...) need only
+implement minimal driver-specific code, typically start, set close...
+This means that code is more maintainable and less buggy...
+Easier to change high-level behavior without redoing low-level code...
+Only implemented once...
 
 At it's most basic PyCMDS defines the following simple data types (derived from
 \python{PyCMDS_object}):
@@ -336,6 +455,8 @@ For DAQ cards, shots and samples...
 
 Power of digital processing...
 
+Old boxcar: 300 ns window, ~10 micosecond delay. Onset of saturation ~2 V.
+
 % TODO: screenshots
 
 \subsection{Sensors as axes}  % -------------------------------------------------------------------
-- 
cgit v1.2.3

