diff options
Diffstat (limited to 'processing')
-rw-r--r-- | processing/PyCMDS/ideal axis positions/delay steps.pdf | bin | 0 -> 351037 bytes | |||
-rw-r--r-- | processing/PyCMDS/ideal axis positions/delay steps.tex | 99 | ||||
-rw-r--r-- | processing/PyCMDS/ideal axis positions/exponential.png | bin | 0 -> 210936 bytes | |||
-rw-r--r-- | processing/PyCMDS/ideal axis positions/steps.py | 83 | ||||
-rw-r--r-- | processing/chapter.tex | 95 |
5 files changed, 277 insertions, 0 deletions
diff --git a/processing/PyCMDS/ideal axis positions/delay steps.pdf b/processing/PyCMDS/ideal axis positions/delay steps.pdf Binary files differnew file mode 100644 index 0000000..1472e0c --- /dev/null +++ b/processing/PyCMDS/ideal axis positions/delay steps.pdf diff --git a/processing/PyCMDS/ideal axis positions/delay steps.tex b/processing/PyCMDS/ideal axis positions/delay steps.tex new file mode 100644 index 0000000..88029ea --- /dev/null +++ b/processing/PyCMDS/ideal axis positions/delay steps.tex @@ -0,0 +1,99 @@ +% document
+\documentclass[11 pt]{report}
+\usepackage[letterpaper, margin=0.75in]{geometry} % 1 inch margins required
+\usepackage{setspace}
+\usepackage{afterpage}
+\usepackage{color}
+\usepackage{soul}
+\usepackage{array}
+
+% text
+\usepackage[utf8]{inputenc}
+\setlength\parindent{0pt}
+\setlength{\parskip}{1em}
+\usepackage{enumitem}
+\renewcommand{\familydefault}{\sfdefault}
+\newcommand{\RomanNumeral}[1]{\textrm{\uppercase\expandafter{\romannumeral #1\relax}}}
+\usepackage{etoolbox}
+\AtBeginEnvironment{verse}{\singlespacing}
+\AtBeginEnvironment{tabular}{\singlespacing}
+
+% graphics
+\usepackage{graphics}
+\usepackage{graphicx}
+\usepackage{epsfig}
+\usepackage{epstopdf}
+\usepackage{etoc}
+\usepackage{tikz}
+
+% math
+\usepackage{amssymb}
+\usepackage{amsmath}
+\usepackage[cm]{sfmath}
+\DeclareMathOperator{\me}{e}
+
+% hyperref
+\usepackage[colorlinks=true, linkcolor=black, urlcolor=blue, citecolor=black, anchorcolor=black]{hyperref}
+\usepackage[all]{hypcap} % helps hyperref work properly
+
+% date (http://tex.stackexchange.com/a/237251)
+\def\twodigits#1{\ifnum#1<10 0\fi\the#1}
+\def\mydate{\leavevmode\hbox{\the\year-\twodigits\month-\twodigits\day}}
+
+\begin{document}
+
+{\Huge{delay space stepping strategy}}
+
+Blaise Thompson \hfill last modified \mydate
+
+\dotfill
+
+Linear stepping is more expensive than it needs to be.
+
+Want to capture the dynamic range of the data as quickly as possible.
+
+Typically have exponential decay dynamics (perhaps multi-exponential)\dots we can capitalize on this. We want to take high resolution data at early delays and low resolution data at late delays.
+
+Of course, we don't want to throw away any information we would otherwise be entitled to.
+
+Conceptually we want to 'linearize' the data, so that each subsequent delay step accounts for the same change in signal.
+
+Signal goes exponentially...
+
+\begin{eqnarray}
+S &=& \me^{-\frac{t}{\tau}} \\
+\log{(S)} &=& -\frac{t}{\tau} \\
+t &=& -\tau\log{(S)}
+\end{eqnarray}
+
+So to step linearly in $t$, my step size has to go as $-\tau\log{(S)}$.
+
+We want to go linearly in signal, meaning that we want to divide $S$ into even sections. If $S$ goes from 0 to 1 and we choose to acquire $N$ points,
+
+\begin{eqnarray}
+t_n &=& -\tau\log{\left(\frac{n}{N}\right)}.
+\end{eqnarray}
+
+Note that $t_n$ starts at long times and approaches zero delay. So the first $t_1$ is the smallest signal and $t_N$ is the largest.
+
+Now we can start to consider realistic cases, like where $\tau$ is not quite known and where some other longer dynamics persist (manifested as a static offset). Since these values are not separable in a general system, I'll keep $S$ normalized between 0 and 1.
+
+\begin{eqnarray}
+S &=& (1-c)\me^{-\frac{t}{\tau_{\mathrm{actual}}}} + c \\
+S_n &=& (1-c)\me^{-\frac{-\tau_{\mathrm{step}}\log{\left(\frac{n}{N}\right)}}{\tau_{\mathrm{actual}}}} + c \\
+S_n &=& (1-c)\me^{-\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm{actual}}} \log{\left(\frac{N}{n}\right)}} + c \\
+S_n &=& (1-c)\left(\frac{N}{n}\right)^{-\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm{actual}}}} + c \\
+S_n &=& (1-c)\left(\frac{n}{N}\right)^{\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm{actual}}}} + c
+\end{eqnarray}
+
+
+
+\begin{figure}[!htb]
+ \centering
+ \includegraphics[scale=0.5]{"out"}
+ \caption{}
+\end{figure}
+
+
+
+\end{document}
\ No newline at end of file diff --git a/processing/PyCMDS/ideal axis positions/exponential.png b/processing/PyCMDS/ideal axis positions/exponential.png Binary files differnew file mode 100644 index 0000000..7ad27f3 --- /dev/null +++ b/processing/PyCMDS/ideal axis positions/exponential.png diff --git a/processing/PyCMDS/ideal axis positions/steps.py b/processing/PyCMDS/ideal axis positions/steps.py new file mode 100644 index 0000000..13419c3 --- /dev/null +++ b/processing/PyCMDS/ideal axis positions/steps.py @@ -0,0 +1,83 @@ +### import ####################################################################
+
+
+import matplotlib.pyplot as plt
+plt.close('all')
+
+import numpy as np
+
+import WrightTools as wt
+
+
+### define ####################################################################
+
+
+def get_signal(d, tau, pulsewidth=10, offset=0):
+ # pulse
+ pulse = np.exp((-d**2)/(pulsewidth**2))
+ # signal
+ sig = np.zeros(d.shape)
+ sig[d<=0] = np.exp(d[d<=0]/tau)
+ sig[d<=0] += offset
+ sig /= sig.max()
+ # finish
+ #sig = np.convolve(sig, pulse, mode='same')
+ return sig
+
+
+def logarithmic_stepping(p_tau, p_npts, n_tau, n_npts):
+ # positive
+ p_xi = np.arange(0, p_npts)
+ p_delays = p_tau * np.log((p_xi.size+1)/(p_xi+1))
+ # negative
+ n_xi = np.arange(0, n_npts)
+ n_delays = -n_tau * np.log((n_xi.size+1)/(n_xi+1))
+ return np.hstack((n_delays, [0], p_delays))
+
+
+tau = 200
+
+
+d = logarithmic_stepping(50, 3, 200, 15)
+
+
+### workspace #################################################################
+
+
+if True:
+ fig, gs = wt.artists.create_figure(width=13, cols=[1, 1], nrows=1)
+ # delay space
+ ax = plt.subplot(gs[0, 0])
+ ds = np.linspace(-1500, 1500, 1000)
+ sig = get_signal(ds, tau)
+ plt.plot(ds, sig, c='b', lw=2, alpha=0.5)
+ sig = get_signal(ds, tau, offset=0.5)
+ plt.plot(ds, sig, c='r', lw=2, alpha=0.5)
+ sig = get_signal(ds, tau*2, offset=0)
+ plt.plot(ds, sig, c='g', lw=2, alpha=0.5)
+ plt.xlim(-1250, 100)
+ plt.ylim(-0.1, 1.1)
+ for x in d:
+ plt.axvline(x, c='k', zorder=0)
+ plt.axvline(0, lw=3, c='k')
+ ax.set_xlabel('delay', fontsize=18)
+ ax.set_ylabel('signal', fontsize=18)
+ plt.grid(ls=':')
+ # index space
+ ax = plt.subplot(gs[0, 1])
+ d = logarithmic_stepping(50, 3, 200, 15)
+ sig = get_signal(d, tau)
+ plt.scatter(np.arange(sig.size), sig, c='b', edgecolor='none', s=50, alpha=0.5)
+ sig = get_signal(d, tau, offset=0.5)
+ plt.scatter(np.arange(sig.size), sig, c='r', edgecolor='none', s=50, alpha=0.5)
+ sig = get_signal(d, tau*2, offset=0)
+ plt.scatter(np.arange(sig.size), sig, c='g', edgecolor='none', s=50, alpha=0.5)
+ i = np.argmin(np.abs(d))
+ plt.axvline(i, lw=3, c='k')
+ plt.grid(ls=':')
+ plt.ylim(-0.1, 1.1)
+ plt.setp(ax.get_yticklabels(), visible=False)
+ ax.set_xlim(0-1, sig.size)
+ ax.set_xlabel('index', fontsize=18)
+ # finish
+ wt.artists.savefig('exponential.png')
diff --git a/processing/chapter.tex b/processing/chapter.tex new file mode 100644 index 0000000..b755fb0 --- /dev/null +++ b/processing/chapter.tex @@ -0,0 +1,95 @@ +\chapter{Processing}
+
+\section{Overview}
+
+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.
+
+\section{WrightTools}
+
+WrightTools is a software package at the heart of all work in the Wright Group.
+
+\section{PyCMDS}
+
+PyCMDS directly addresses the hardware during experiments.
+
+\subsection{Overview}
+
+PyCMDS has, through software improvements alone, dramatically lessened scan times...
+
+\begin{itemize}[topsep=-1.5ex, itemsep=0ex, partopsep=0ex, parsep=0ex, label=$\rightarrow$]
+ \item simultaneous motor motion
+ \item digital signal processing % TODO: reference section when it exists
+ \item ideal axis positions \ref{sec:ideal_axis_positions}
+\end{itemize}
+
+\subsection{Ideal Axis Positions}\label{sec:ideal_axis_positions}
+
+Frequency domain multidimensional spectroscopy is a time-intensive process. A typical \gls{pixel} takes between one-half second and three seconds to acquire. Depending on the exact hardware being scanned and signal being detected, this time may be mostly due to hardware motion or signal collection. Due to the \gls{curse of dimensionality}, a typical three-dimensional CMDS experiment contains roughly 100,000 pixels. CMDS hardware is transiently-reliable, so speeding up experiments is a crucial component of unlocking ever larger dimensionalities and higher resolutions.
+
+One obvious way to decrease the scan-time is to take fewer pixels. Traditionally, multidimensional scans are done with linearly arranged points in each axis---this is the simplest configuration to program into the acquisition software. Because signal features are often sparse or slowly varying (especially so in high-dimensional scans) linear stepping means that \emph{most of the collected pixels} are duplicates or simply noise. A more intelligent choice of axis points can capture the same nonlinear spectrum in a fraction of the total pixel count.
+
+An ideal distribution of pixels is linearized in \emph{signal}, not coordinate. This means that every signal level (think of a contour in the N-dimensional case) has roughly the same number of pixels defining it. If some generic multidimensional signal goes between 0 and 1, one would want roughly 10\% of the pixels to be between 0.9 and 1.0, 10\% between 0.8 and 0.9 and so on. If the signal is sparse in the space explored (imagine a narrow two-dimensional Lorentzian in the center of a large 2D-Frequency scan) this would place the majority of the pixels near the narrow peak feature(s), with only a few of them defining the large (in axis space) low-signal floor. In contrast linear stepping would allocate the vast majority of the pixels in the low-signal 0.0 to 0.1 region, with only a few being used to capture the narrow peak feature. Of course, linearizing pixels in signal requires prior expectations about the shape of the multidimensional signal---linear stepping is still an appropriate choice for low-resolution ``survey'' scans.
+
+CMDS scans often posses correlated features in the multidimensional space. In order to capture such features as cheaply as possible, one would want to define regions of increased pixel density along the correlated (diagonal) lineshape. As a concession to reasonable simplicity, our acquisition software (PyCMDS) assumes that all scans constitute a regular array with-respect-to the scanned axes. We can acquire arbitrary points along each axis, but not for the multidimensional scan. This means that we cannot achieve strictly ideal pixel distributions for arbitrary datasets. Still, we can do much better than linear spacing. % TODO: refer to PyCMDS/WrightTools 'regularity' requirement when that section exists
+
+Almost all CMDS lineshapes (in frequency and delay) can be described using just a few lineshape functions:
+
+\begin{itemize}[topsep=-1.5ex, itemsep=0ex, partopsep=0ex, parsep=0ex, label=$\rightarrow$]
+ \item exponential
+ \item Gaussian
+ \item Lorentzian
+ \item bimolecular
+\end{itemize}
+
+Exponential and bimolecular dynamics fall out of simple first and second-order kinetics (I will ignore higher-order kinetics here). Gaussians come from our Gaussian pulse envelopes or from normally-distributed inhomogeneous broadening. The measured line-shapes are actually convolutions of the above. I will ignore the convolution except for a few illustrative special cases. More exotic lineshapes are possible in CMDS---quantum beating and breathing modes, for example---I will also ignore these. Derivations of the ideal pixel positions for each of these lineshapes appear below. %TODO: cite Wright Group quantum beating paper, Kambempati breathing paper
+
+\subsection{Exponential}
+
+Simple exponential decays are typically used to describe population and coherence-level dynamics in CMDS. For some generic exponential signal $S$ with time constant $\tau$,
+
+\begin{equation} \label{eq:simple_exponential_decay}
+S(t) = \me^{-\frac{t}{\tau}}.
+\end{equation}
+
+We can write the conjugate equation to \ref{eq:simple_exponential_decay}, asking ``what $t$ do I need to get a certain signal level?'':
+
+\begin{eqnarray}
+\log{(S)} &=& -\frac{t}{\tau} \\
+t &=& -\tau\log{(S)}.
+\end{eqnarray}
+
+So to step linearly in $t$, my step size has to go as $-\tau\log{(S)}$.
+
+We want to go linearly in signal, meaning that we want to divide $S$ into even sections. If $S$ goes from 0 to 1 and we choose to acquire $N$ points,
+
+\begin{eqnarray}
+t_n &=& -\tau\log{\left(\frac{n}{N}\right)}.
+\end{eqnarray}
+
+Note that $t_n$ starts at long times and approaches zero delay. So the first $t_1$ is the smallest signal and $t_N$ is the largest.
+
+Now we can start to consider realistic cases, like where $\tau$ is not quite known and where some other longer dynamics persist (manifested as a static offset). Since these values are not separable in a general system, I'll keep $S$ normalized between 0 and 1.
+
+\begin{eqnarray}
+S &=& (1-c)\me^{-\frac{t}{\tau_{\mathrm{actual}}}} + c \\
+S_n &=& (1-c)\me^{-\frac{-\tau_{\mathrm{step}}\log{\left(\frac{n}{N}\right)}}{\tau_{\mathrm{actual}}}} + c \\
+S_n &=& (1-c)\me^{-\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm{actual}}} \log{\left(\frac{N}{n}\right)}} + c \\
+S_n &=& (1-c)\left(\frac{N}{n}\right)^{-\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm{actual}}}} + c \\
+S_n &=& (1-c)\left(\frac{n}{N}\right)^{\frac{\tau_{\mathrm{step}}}{\tau_{\mathrm{actual}}}} + c
+\end{eqnarray}
+
+\begin{dfigure}[p!]
+ \includegraphics[scale=0.5]{"processing/PyCMDS/ideal axis positions/exponential"}
+ \caption[TODO]{TODO}
+ \label{fig:exponential_steps}
+\end{dfigure}
+
+\subsubsection{Gaussian}
+
+\subsubsection{Lorentzian}
+
+\subsubsection{Bimolecular}
+
+\section{WrightSim}
+
+WrightSim does simulations.
|