From 093ce016b23812d0aaf58c2b05c9d4189791e2a6 Mon Sep 17 00:00:00 2001 From: Blaise Thompson Date: Tue, 27 Mar 2018 16:06:30 -0500 Subject: 2018-03-27 16:06 --- acquisition/chapter.tex | 141 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 3 deletions(-) (limited to 'acquisition/chapter.tex') diff --git a/acquisition/chapter.tex b/acquisition/chapter.tex index 1525b9e..863bf96 100644 --- a/acquisition/chapter.tex +++ b/acquisition/chapter.tex @@ -56,6 +56,8 @@ Besides the extendable modular pieces, the rest of PyCMDS is a mostly-static cod modules and does the necessary things to handle display of information from, and communication between them. % +\subsection{Multithreading} % -------------------------------------------------------------------- + For the kinds of acquisitions that the Wright Group has done the acquisition software spends the vast majority of its run-time waiting---waiting for user input through mouse clicks or keyboard presses, waiting for hardware to finish moving or for sensors to finish reading and return @@ -72,7 +74,7 @@ acquisition requires. % Threads are powerful because they allow for ``semi-synchronous'' operation. % Imagine PyCMDS is in the middle of a 2D delay-delay scan, and the scan thread has just told each of -the two delay stages to head to their positions. % +the two delay stages to head to their destinations. % PyCMDS must sit in a tight loop to keep track of the position as closely as possible during motor motion. % In a single-threaded configuration, this tight loop would only run for one delay at a time, such @@ -84,12 +86,102 @@ This switching is handled in an OS and hardware specific way---luckily it is all platform-agnostic Qt threads. % Threads are dangerous because it is hard to pass information between them. % -Thus, mutexes... signals and slots... +Without any special protection, two threads have no reason not to simultaneously edit and read the +same location in memory. % +If a delay stage is writing its position to memory as a 64-bit double at the same time as the +acquisition thread reads that memory address, the acquisition thread will read in nonsense (or +worse), it will crash). % +So some strategy is needed to ensure that threads respect each other. % +The Mutex design allows threads to ``lock'' an object such that it cannot be modified by a +different thread. % +This lock is like the ``talking stick'' employed my many early child educators. % +When the talking stick is being used, only the child that holds the stick is allowed to speak. % +The stick must be passed to another child (as directed by the teacher) before they can share their +thought. % +PyCMDS makes heavy use of Mutexes, in particular the \bash{QMutex} class \cite{QMutex}. % + +Mutexes handle basic information transfer (two threads can both safely modify and read a particular +object), but what about sending instructions between threads? % +Here the problem is deciding what happens when multiple instructions are given simultaneously, or +an instruction is given while another instruction is being carried out. % +Again, this is a classic problem in computer science, and the classic answer is the queue. % +Queues are just like lines at the coffee shop---each person (instruction) is served (carried out) +in the order that they joined the line. % +Queues are commonly referred to as FIFO (First In First Out) for this reason. % +PyCMDS uses queues for almost all instructions. % + +Finally, PyCMDS makes extensive use of the ``signals and slots'' construct, which is somewhat +unique (and certainly original) to Qt. % +Signals and slots are powerful because they allow threads without instruction to go completely +silent, making them essentially free in terms of CPU usage. % +Normally, a thread needs to sit in a loop merely listening for instructions. % +Within the Qt framework, a thread can be ``woken'' by a signal without needing that thread to +explicitly ``listen''. % +These concepts fit within the broader umbrella of ``event-driven programming'', a concept that has +been used in many languages and frameworks (notably high level LabVIEW tends to be very +event-driven). % +The Qt signals and slots system massively simplifies programming within PyCMDS. % + +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... + +At it's most basic PyCMDS defines the following simple data types (derived from +\python{PyCMDS_object}): +\begin{ditemize} + \item Bool + \item Combo + \item Filepath + \item Number + \item String +\end{ditemize} +These classes do multiple things. % +First, they \emph{are} Mutexes, with thread-safe \python{read} and \python{write} methods. % +Secondly, they support ``implicit'' storage in ini files. % +Third, they know how to participate in the GUI. % +They can display their value, and if modified they will propagate that modification to the internal +threads of outward... +Finally, they have special properties like units and limits etc... Without getting into details, let's investigate the key ``signals and slots'' that hardware and sensors have. % % TODO: elaborate +The following is the top-level hardware class, parent of all hardware and sensors. % + +\begin{figure} + \includepython{"acquisition/parent_hardware.py"} + \caption[Parent to hardware and sensors.]{ + Parent class of all hardware and sensors. % + For brevity, methods \python{close}, \python{update} and \python{wait_until_still} have been + omitted. % + } + \label{aqn:fig:parent_hardware_class} +\end{figure} + +\begin{figure} + \includepython{"acquisition/driver.py"} + \caption[TODO]{ + TODO + } + \label{aqn:fig:driver} +\end{figure} + +\subsection{Graphical user interface} % ---------------------------------------------------------- + +Made up of widgets... + +Table widget... + +Use of qt plots... + +pyqtgraph \cite{pyqtgraph} + +\subsection{Scans} % ----------------------------------------------------------------------------- + The central loop of scans in PyCMDS. % \begin{codefragment}{python, label=aqn:lst:loop_simple} for coordinates in list_of_coordinates: @@ -146,6 +238,45 @@ because indeed that is all that can be generalized. % \section{Hardware} \label{aqn:sec:hardware} % ==================================================== +Hardware are things that 1) have a position, 2) can be set to a destination. % +Typically they also have associated units and limits. % +Each hardware can be thought of as a dimension of the MR-CMDS experiment, and scans include a +specific traversal through this multidimensional space. % + +\subsection{Hardware inheritance} % -------------------------------------------------------------- + +All hardware classes are children of the parent \python{Hardware} class, which is itself subclassed +from the global \python{Hardware} class shown in \autoref{aqn:lst:parent_hardware}. % + +\begin{figure} + \includepython{"acquisition/hardware.py"} + \caption[Parent hardware class.]{ + Parent class of all hardware. % + For brevity, methods \python{close}, \python{get_destination}, \python{get_position}, + \python{is_valid}, \python{on_address_initialized}, \python{poll}, and \python{@property units} + have been omitted. % + } + \label{aqn:fig:hardware_class} +\end{figure} + + +\begin{figure} + \includebash{"acquisition/hardware_inheritance"} + \caption[Hardware inheritance.]{ + } + \label{aqn:fig:hardware_inheritance} +\end{figure} + + + +\subsection{Delays} % ---------------------------------------------------------------------------- + +\subsection{Spectrometers} % --------------------------------------------------------------------- + +\subsection{OPAs} % ------------------------------------------------------------------------------ + +\subsection{Filters} % --------------------------------------------------------------------------- + \section{Sensors (devices)} \label{aqn:sec:sensors} % ============================================ \subsection{Sensors as axes} % ------------------------------------------------------------------- @@ -292,4 +423,8 @@ S_n &=& (1-c)\left(\frac{n}{N}\right)^{\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm \subsection{Enhanced modularity} % --------------------------------------------------------------- -\subsection{wt5 savefile} % ---------------------------------------------------------------------- \ No newline at end of file +\subsection{wt5 savefile} % ---------------------------------------------------------------------- + +\subsection{Hotswappable hardware} % ------------------------------------------------------------- + +\subsection{Better logging and error handling} % ------------------------------------------------- \ No newline at end of file -- cgit v1.2.3