From e3fb4a515856d3f6561baad09f5c5a2e088e4e37 Mon Sep 17 00:00:00 2001 From: Blaise Thompson Date: Wed, 11 Apr 2018 09:46:30 -0500 Subject: 2018-04-11 09:46 --- acquisition/chapter.tex | 70 ++++++++++++++++++++++++++++++++++++++---------- acquisition/quad.png | Bin 132067 -> 156161 bytes acquisition/quad.py | 23 +++++++++++----- 3 files changed, 73 insertions(+), 20 deletions(-) (limited to 'acquisition') diff --git a/acquisition/chapter.tex b/acquisition/chapter.tex index 803049e..df1c887 100644 --- a/acquisition/chapter.tex +++ b/acquisition/chapter.tex @@ -740,13 +740,63 @@ a signal that causes \python{queue.on_action_complete} to be called. % If there are more enqueued acquisitions, and \python{queue_status.go} is true, the \python{queue} instance pushes the next operation to the \python{worker} and the process starts over again. % +The queue manager is capable of more than just acquisitions. % +For example, users can enqueue a wait operation that simply pauses PyCMDS for a certain amount of +time or until some condition is met. % + +Those who wish to learn more can refer to \bash{PyCMDS/somatic/queue.py}. % + \subsection{Scans} % ----------------------------------------------------------------------------- -The central loop of scans in PyCMDS. % +Every single scan within PyCMDS is handled by one method of one class, \python{Worker.scan} +from the file \bash{PyCMDS/somatic/acquisition.py}. % +This method understands how to any scan that PyCMDS can do: any stepwise multidimensional scan with +separate hardware and sensors. % + +The central scan method requires acquisition modules to provide all of the axes (instances of +\python{PyCMDS.somatic.acquisition.Axis}) that need to be broadcast across each-other. % +Then something very simple happens. % +For each hardware that will move during the scan, a destinations object (instance of +\python{PyCMDS.somatic.acquisition.Destinations}) is created. % +This object has the same shape as the full multidimensional scan, and contains the destination for +that hardware for that pixel in the scan. % +Then, a \bash{.data} file is created to accept the data that is about to be collected. % +A bunch of signals go off, telling PyCMDS that it needs to yield to somatic control. % +Then PyCMDS simply sits in a loop generated by \python{numpy.ndindex} [CITE] and visits each pixel +in turn. % +\python{ndindex} is a n-dimensional iterator over a given array shape. % +Written simply, it does the following: +\begin{codefragment}{python} +def ndindex(shape): + rs = [range(s) for s in shape] + pools = map(tuple, rs) + result = [[]] + for pool in pools: + result = [x+[y] for x in result for y in pool] + for prod in result: + yield tuple(prod) +\end{codefragment} +So that when evaluated: +\begin{codefragment}{python} +>>> for idx in ndindex((4, 3, 2)): print idx +(0, 0, 0) +(0, 0, 1) +(0, 1, 0) +(0, 1, 1) +(0, 2, 0) +(0, 2, 1) +(1, 0, 0) +... +(3, 2, 0) +(3, 2, 1) +\end{codefragment} + +This simple algorithm is used to visit each pixel in the entire PyCMDS scan space. % +At each pixel, something much like the following happens. % \begin{codefragment}{python, label=aqn:lst:loop_simple} -for coordinates in list_of_coordinates: - for hardware, coordinate in zip(hardwares, coordinates): - hardware.set(coordinate) +for idx in ndindex(shape): + for hardware in hardwares:: + hardware.set(idx) for hardware in hardwares: hardware.wait_until_still() for sensor in sensors: @@ -754,6 +804,8 @@ for coordinates in list_of_coordinates: for sensor in sensors: sensor.wait_until_done() \end{codefragment} +The pattern is simple: launch hardware, wait for still, launch sensors, wait for done. % +The simplicity of this central loop truly shows the power of abstraction in PyCMDS. % \subsection{Acquisition modules} % --------------------------------------------------------------- @@ -799,16 +851,6 @@ Automatically do appropriate scans and process as in chapter... Dedicated to poynting (get content from Kyle S)... -\subsection{The data file} % --------------------------------------------------------------------- - -Does not have the same dimensionality restrictions as prior acquisition software. % - -Self describing (enabled by \python{tidy_headers}). - -\subsection{Automatic processing} % -------------------------------------------------------------- - -For scan module, just - \clearpage \section{Conditional validity} % ================================================================= diff --git a/acquisition/quad.png b/acquisition/quad.png index 3b1c7f6..ea933da 100644 Binary files a/acquisition/quad.png and b/acquisition/quad.png differ diff --git a/acquisition/quad.py b/acquisition/quad.py index d6519e5..ee5fab9 100644 --- a/acquisition/quad.py +++ b/acquisition/quad.py @@ -21,19 +21,30 @@ here = os.path.abspath(os.path.dirname(__file__)) fig, gs = wt.artists.create_figure(width='double') ax = plt.subplot(gs[0, 0]) -ax.set_xlim(-1.1, 1.1) -ax.set_ylim(-1.1, 1.1) - -ax.arrow(-1, 0, 2, 0, lw=5, head_width=0.1) -ax.arrow(0, -1, 0, 2, lw=5, head_width=0.1) +ax.set_xlim(0, 1.25) +ax.set_ylim(0, 1.25) es = {} -es['MR-CMDS'] = (-0.5, 0.5) +es['MR-CMDS'] = (1, 0.3) +es['AFM'] = (0.5, 0.4) +es['GRAPES'] = (0.1, 1) +es['FTIR'] = (0.1, 0.1) +es['z-scan'] = (0.1, 0.2) +es['UV-VIS'] = (0.1, 0.3) +es['TRPL'] = (0.1, 0.4) +es['NMR'] = (0.1, 0.5) + + for label, coordinates in es.items(): ax.text(*coordinates, label, fontsize=20) +# decoration +xlabel = r'hardware complexity $\rightarrow$' +ylabel = r'measurement complexity $\rightarrow$' +wt.artists.set_ax_labels(xlabel=xlabel, ylabel=ylabel, xticks=False, yticks=False) + # save p = os.path.join(here, 'quad.png') wt.artists.savefig(p) -- cgit v1.2.3