Why use a Binning Analysis?
As described in Markus Wallerberger (2019), Vinay Ambegaokar, Matthias Troyer (2010), Tony F. Chan, Gene H. Golub, Randall J. LeVeque (1983), Carsten Bauer (2020), and James Gubernatis, Naoki Kawashima, Philipp Werner (2016), the presence of correlations in a data stream generated in Markov Chain Monte Carlo simulations renders any measures of error severely underestimated.
Theoretical background
The naive approach is to calculate the mean
and the variance of the mean, var_of_mean
, for a given data stream $X$. For uncorrelated data, this becomes
\[\begin{aligned} \mathtt{mean}(X) &= \frac{1}{M} \sum_{i = 1}^M x_i \\ \mathtt{var\_of\_mean}(X) &= \frac{1}{M(M-1)} \sum_{i = 1}^M (x_i - \mathtt{mean}(X))^2. \end{aligned}\]
Fortunately, in the presence of correlations, the mean
doesn't change. Unfortunately, the var_of_mean
does. Indeed, one can show that it's given by
\[\mathtt{var\_of\_mean}(X) = \frac{1 + 2\tau_X}{M(M-1)} \sum_{i = 1}^M (x_i - \mathtt{mean}(X))^2,\]
where the as shown in the Figure within the Accumulator
type hierarchy. Clearly, the uncorrelated var_of_mean
is just increased by a factor of $R_X \equiv 1 + 2\tau_X$, where $\tau_X$ is defined as the integrated autocorrelation_time
of the data stream. The binning analysis provides a fast as an O(N)
method for calculating the autocorrelation_time
. It's also cheap, only requiring O(log N)
in RAM. For those who are unfamiliar with the term, normally one would calculate $\tau_X$ by
\[\tau_X = \sum_{i = 1}^M \sum_{i < j} \left[ x_ix_j - \mathtt{mean}(x)^2 \right],\]
which is an O(N^2)
summation and can suffer from numerical instabilities.
As one performs pairwise means in each binning level to construct the next highest, and then calculates the var_of_mean
for each level, one can see that it rises and then eventually saturates around a particular plateau
value. Normalizing by the original var_of_mean
calculation assuming the data stream is uncorrelated, one can then calculate $R_X$ in the $\ell^{\rm th}$ binning level as
\[R_X(\ell) = \frac{\mathtt{var\_of\_mean}(X^{(\ell)})}{\mathtt{var\_of\_mean}(X^{(0)})} = \frac{ m^{(\ell)} \mathtt{var}(X^{(\ell)}) }{ \mathtt{var}(X^{(0)}) },\]
where var
is the normal variance and $m^{(\ell)}$ is the bin size, or the number of original data values accumulated into a single data point at the $\ell^{\rm th}$ level.
Visualizing a Binning Analysis
The final result of the binning analysis, for sufficiently long data streams, will be to see a sigmoid
-like curve. We've wrapped up a fitting and plotting workflow into the plot_binning_analysis
function below to demonstrate how it works. Feel free to skip over to the Visualization Examples if you have your own workflow established.
using OnlineLogBinning, Plots, LaTeXStrings
pyplot()
# Return the fitted inflection point
sigmoid_inflection(fit) = fit.param[2] / fit.param[3]
# Define a plotting function with Plots.jl
# This function plots the RxValues, the Sigmoid fit,
# the maximum trustworthy level, and the fitted
# inflection point.
function plot_binning_analysis(bacc)
# Plot the RxValues irrespective of the trusting cutoff
all_levels, all_rxvals = levels_RxValues(bacc, false)
plt = plot( all_levels, all_rxvals;
label = "Binning Analysis",
xlabel = L"Bin Level $\ell$",
ylabel = L"$R_X(\ell)$",
markershape = :circle,
legend = :topleft )
# Fit only the trustworthy levels
levels, rxvals = levels_RxValues(bacc)
fit = fit_RxValues(levels, rxvals)
# Plot the sigmoid fit
plot!(plt, all_levels, sigmoid(all_levels, fit.param);
label = "Sigmoid Fit")
# Plot the maximum trustworthy level
vline!(plt, [ max_trustworthy_level(bacc[level = 0].num_bins) ];
ls = :dash, color = "gray",
label = "Maximum Trustworthy Level")
# Plot the fitted inflection point if it's positive
if sigmoid_inflection(fit) > zero(fit.param[2])
vline!(plt, [ sigmoid_inflection(fit) ];
ls = :dot, color = "red",
label = "Sigmoid Inflection Point")
end
return plt
end
[ Info: Installing matplotlib via the Conda matplotlib package...
[ Info: Running `conda install -q -y matplotlib` in root environment
Collecting package metadata (current_repodata.json): ...working... done
Solving environment: ...working... done
## Package Plan ##
environment location: /home/runner/.julia/conda/3
added / updated specs:
- matplotlib
The following packages will be downloaded:
package | build
---------------------------|-----------------
alsa-lib-1.2.8 | h166bdaf_0 578 KB conda-forge
attr-2.5.1 | h166bdaf_1 69 KB conda-forge
brotli-1.0.9 | h166bdaf_8 18 KB conda-forge
brotli-bin-1.0.9 | h166bdaf_8 20 KB conda-forge
cairo-1.16.0 | h35add3b_1015 1.1 MB conda-forge
contourpy-1.0.7 | py310hdf3cbec_0 211 KB conda-forge
cycler-0.11.0 | pyhd8ed1ab_0 10 KB conda-forge
dbus-1.13.6 | h5008d03_3 604 KB conda-forge
expat-2.5.0 | hcb278e6_1 134 KB conda-forge
font-ttf-dejavu-sans-mono-2.37| hab24e00_0 388 KB conda-forge
font-ttf-inconsolata-3.000 | h77eed37_0 94 KB conda-forge
font-ttf-source-code-pro-2.038| h77eed37_0 684 KB conda-forge
font-ttf-ubuntu-0.83 | hab24e00_0 1.9 MB conda-forge
fontconfig-2.14.2 | h14ed4e7_0 266 KB conda-forge
fonts-conda-ecosystem-1 | 0 4 KB conda-forge
fonts-conda-forge-1 | 0 4 KB conda-forge
fonttools-4.39.3 | py310h1fa729e_0 2.0 MB conda-forge
freetype-2.12.1 | hca18f0e_1 611 KB conda-forge
gettext-0.21.1 | h27087fc_0 4.1 MB conda-forge
glib-2.76.2 | hfc55251_0 473 KB conda-forge
glib-tools-2.76.2 | hfc55251_0 109 KB conda-forge
graphite2-1.3.13 | h58526e2_1001 102 KB conda-forge
gst-plugins-base-1.22.0 | h4243ec0_2 2.6 MB conda-forge
gstreamer-1.22.0 | h25f0c4b_2 1.9 MB conda-forge
harfbuzz-6.0.0 | h3ff4399_1 1.2 MB conda-forge
icu-72.1 | hcb278e6_0 11.4 MB conda-forge
keyutils-1.6.1 | h166bdaf_0 115 KB conda-forge
kiwisolver-1.4.4 | py310hbf28c38_1 76 KB conda-forge
krb5-1.20.1 | h81ceb04_0 1.3 MB conda-forge
lame-3.100 | h166bdaf_1003 496 KB conda-forge
lcms2-2.15 | haa2dc70_1 236 KB conda-forge
lerc-4.0.0 | h27087fc_0 275 KB conda-forge
libbrotlicommon-1.0.9 | h166bdaf_8 66 KB conda-forge
libbrotlidec-1.0.9 | h166bdaf_8 33 KB conda-forge
libbrotlienc-1.0.9 | h166bdaf_8 288 KB conda-forge
libcap-2.67 | he9d0100_0 97 KB conda-forge
libclang-16.0.3 |default_h83cc7fd_0 21 KB conda-forge
libclang13-16.0.3 |default_hd781213_0 9.8 MB conda-forge
libcups-2.3.3 | h36d4200_3 4.3 MB conda-forge
libdeflate-1.18 | h0b41bf4_0 64 KB conda-forge
libedit-3.1.20191231 | he28a2e2_2 121 KB conda-forge
libevent-2.1.10 | h28343ad_4 1.1 MB conda-forge
libexpat-2.5.0 | hcb278e6_1 76 KB conda-forge
libflac-1.4.2 | h27087fc_0 411 KB conda-forge
libgcrypt-1.10.1 | h166bdaf_0 703 KB conda-forge
libglib-2.76.2 | hebfc3b9_0 2.6 MB conda-forge
libgpg-error-1.46 | h620e276_0 252 KB conda-forge
libiconv-1.17 | h166bdaf_0 1.4 MB conda-forge
libjpeg-turbo-2.1.5.1 | h0b41bf4_0 479 KB conda-forge
libllvm16-16.0.3 | hbf9e925_1 33.7 MB conda-forge
libogg-1.3.4 | h7f98852_1 206 KB conda-forge
libopus-1.3.1 | h7f98852_1 255 KB conda-forge
libpng-1.6.39 | h753d276_0 276 KB conda-forge
libpq-15.2 | hb675445_0 2.3 MB conda-forge
libsndfile-1.2.0 | hb75c966_0 342 KB conda-forge
libsystemd0-253 | h8c4010b_1 372 KB conda-forge
libtiff-4.5.0 | ha587672_6 398 KB conda-forge
libvorbis-1.3.7 | h9c3ff4c_0 280 KB conda-forge
libwebp-base-1.3.0 | h0b41bf4_0 348 KB conda-forge
libxcb-1.13 | h7f98852_1004 391 KB conda-forge
libxkbcommon-1.5.0 | h79f4944_1 550 KB conda-forge
libxml2-2.10.4 | hfdac1af_0 697 KB conda-forge
lz4-c-1.9.4 | hcb278e6_0 140 KB conda-forge
matplotlib-3.7.1 | py310hff52083_0 8 KB conda-forge
matplotlib-base-3.7.1 | py310he60537e_0 6.5 MB conda-forge
mpg123-1.31.3 | hcb278e6_0 474 KB conda-forge
munkres-1.1.4 | pyh9f0ad1d_0 12 KB conda-forge
mysql-common-8.0.32 | hf1915f5_2 728 KB conda-forge
mysql-libs-8.0.32 | hca2cd23_2 1.5 MB conda-forge
nspr-4.35 | h27087fc_0 222 KB conda-forge
nss-3.89 | he45b914_0 1.9 MB conda-forge
openjpeg-2.5.0 | hfec8fc6_2 344 KB conda-forge
pcre2-10.40 | hc3806b6_0 2.3 MB conda-forge
pillow-9.5.0 | py310h065c6d2_0 44.3 MB conda-forge
pixman-0.40.0 | h36c2ea0_0 627 KB conda-forge
ply-3.11 | py_1 44 KB conda-forge
pthread-stubs-0.4 | h36c2ea0_1001 5 KB conda-forge
pulseaudio-client-16.1 | h5195f5e_3 735 KB conda-forge
pyparsing-3.0.9 | pyhd8ed1ab_0 79 KB conda-forge
pyqt-5.15.7 | py310hab646b1_3 5.0 MB conda-forge
pyqt5-sip-12.11.0 | py310heca2aa9_3 83 KB conda-forge
python-dateutil-2.8.2 | pyhd8ed1ab_0 240 KB conda-forge
qt-main-5.15.8 | h5c52f38_10 58.3 MB conda-forge
sip-6.7.9 | py310hc6cd4ac_0 481 KB conda-forge
six-1.16.0 | pyh6c4a22f_0 14 KB conda-forge
toml-0.10.2 | pyhd8ed1ab_0 18 KB conda-forge
tomli-2.0.1 | pyhd8ed1ab_0 16 KB conda-forge
tornado-6.3 | py310h1fa729e_0 624 KB conda-forge
unicodedata2-15.0.0 | py310h5764c6d_0 500 KB conda-forge
xcb-util-0.4.0 | h166bdaf_0 20 KB conda-forge
xcb-util-image-0.4.0 | h166bdaf_0 24 KB conda-forge
xcb-util-keysyms-0.4.0 | h166bdaf_0 12 KB conda-forge
xcb-util-renderutil-0.3.9 | h166bdaf_0 15 KB conda-forge
xcb-util-wm-0.4.1 | h166bdaf_0 55 KB conda-forge
xkeyboard-config-2.38 | h0b41bf4_0 861 KB conda-forge
xorg-kbproto-1.0.7 | h7f98852_1002 27 KB conda-forge
xorg-libice-1.0.10 | h7f98852_0 58 KB conda-forge
xorg-libsm-1.2.3 | hd9c2040_1000 26 KB conda-forge
xorg-libx11-1.8.4 | h0b41bf4_0 810 KB conda-forge
xorg-libxau-1.0.9 | h7f98852_0 13 KB conda-forge
xorg-libxdmcp-1.1.3 | h7f98852_0 19 KB conda-forge
xorg-libxext-1.3.4 | h0b41bf4_2 49 KB conda-forge
xorg-libxrender-0.9.10 | h7f98852_1003 32 KB conda-forge
xorg-renderproto-0.11.1 | h7f98852_1002 9 KB conda-forge
xorg-xextproto-7.3.0 | h0b41bf4_1003 30 KB conda-forge
xorg-xf86vidmodeproto-2.3.1| h7f98852_1002 23 KB conda-forge
xorg-xproto-7.0.31 | h7f98852_1007 73 KB conda-forge
zlib-1.2.13 | h166bdaf_4 92 KB conda-forge
------------------------------------------------------------
Total: 221.9 MB
The following NEW packages will be INSTALLED:
alsa-lib conda-forge/linux-64::alsa-lib-1.2.8-h166bdaf_0
attr conda-forge/linux-64::attr-2.5.1-h166bdaf_1
brotli conda-forge/linux-64::brotli-1.0.9-h166bdaf_8
brotli-bin conda-forge/linux-64::brotli-bin-1.0.9-h166bdaf_8
cairo conda-forge/linux-64::cairo-1.16.0-h35add3b_1015
contourpy conda-forge/linux-64::contourpy-1.0.7-py310hdf3cbec_0
cycler conda-forge/noarch::cycler-0.11.0-pyhd8ed1ab_0
dbus conda-forge/linux-64::dbus-1.13.6-h5008d03_3
expat conda-forge/linux-64::expat-2.5.0-hcb278e6_1
font-ttf-dejavu-s~ conda-forge/noarch::font-ttf-dejavu-sans-mono-2.37-hab24e00_0
font-ttf-inconsol~ conda-forge/noarch::font-ttf-inconsolata-3.000-h77eed37_0
font-ttf-source-c~ conda-forge/noarch::font-ttf-source-code-pro-2.038-h77eed37_0
font-ttf-ubuntu conda-forge/noarch::font-ttf-ubuntu-0.83-hab24e00_0
fontconfig conda-forge/linux-64::fontconfig-2.14.2-h14ed4e7_0
fonts-conda-ecosy~ conda-forge/noarch::fonts-conda-ecosystem-1-0
fonts-conda-forge conda-forge/noarch::fonts-conda-forge-1-0
fonttools conda-forge/linux-64::fonttools-4.39.3-py310h1fa729e_0
freetype conda-forge/linux-64::freetype-2.12.1-hca18f0e_1
gettext conda-forge/linux-64::gettext-0.21.1-h27087fc_0
glib conda-forge/linux-64::glib-2.76.2-hfc55251_0
glib-tools conda-forge/linux-64::glib-tools-2.76.2-hfc55251_0
graphite2 conda-forge/linux-64::graphite2-1.3.13-h58526e2_1001
gst-plugins-base conda-forge/linux-64::gst-plugins-base-1.22.0-h4243ec0_2
gstreamer conda-forge/linux-64::gstreamer-1.22.0-h25f0c4b_2
harfbuzz conda-forge/linux-64::harfbuzz-6.0.0-h3ff4399_1
icu conda-forge/linux-64::icu-72.1-hcb278e6_0
keyutils conda-forge/linux-64::keyutils-1.6.1-h166bdaf_0
kiwisolver conda-forge/linux-64::kiwisolver-1.4.4-py310hbf28c38_1
krb5 conda-forge/linux-64::krb5-1.20.1-h81ceb04_0
lame conda-forge/linux-64::lame-3.100-h166bdaf_1003
lcms2 conda-forge/linux-64::lcms2-2.15-haa2dc70_1
lerc conda-forge/linux-64::lerc-4.0.0-h27087fc_0
libbrotlicommon conda-forge/linux-64::libbrotlicommon-1.0.9-h166bdaf_8
libbrotlidec conda-forge/linux-64::libbrotlidec-1.0.9-h166bdaf_8
libbrotlienc conda-forge/linux-64::libbrotlienc-1.0.9-h166bdaf_8
libcap conda-forge/linux-64::libcap-2.67-he9d0100_0
libclang conda-forge/linux-64::libclang-16.0.3-default_h83cc7fd_0
libclang13 conda-forge/linux-64::libclang13-16.0.3-default_hd781213_0
libcups conda-forge/linux-64::libcups-2.3.3-h36d4200_3
libdeflate conda-forge/linux-64::libdeflate-1.18-h0b41bf4_0
libedit conda-forge/linux-64::libedit-3.1.20191231-he28a2e2_2
libevent conda-forge/linux-64::libevent-2.1.10-h28343ad_4
libexpat conda-forge/linux-64::libexpat-2.5.0-hcb278e6_1
libflac conda-forge/linux-64::libflac-1.4.2-h27087fc_0
libgcrypt conda-forge/linux-64::libgcrypt-1.10.1-h166bdaf_0
libglib conda-forge/linux-64::libglib-2.76.2-hebfc3b9_0
libgpg-error conda-forge/linux-64::libgpg-error-1.46-h620e276_0
libiconv conda-forge/linux-64::libiconv-1.17-h166bdaf_0
libjpeg-turbo conda-forge/linux-64::libjpeg-turbo-2.1.5.1-h0b41bf4_0
libllvm16 conda-forge/linux-64::libllvm16-16.0.3-hbf9e925_1
libogg conda-forge/linux-64::libogg-1.3.4-h7f98852_1
libopus conda-forge/linux-64::libopus-1.3.1-h7f98852_1
libpng conda-forge/linux-64::libpng-1.6.39-h753d276_0
libpq conda-forge/linux-64::libpq-15.2-hb675445_0
libsndfile conda-forge/linux-64::libsndfile-1.2.0-hb75c966_0
libsystemd0 conda-forge/linux-64::libsystemd0-253-h8c4010b_1
libtiff conda-forge/linux-64::libtiff-4.5.0-ha587672_6
libvorbis conda-forge/linux-64::libvorbis-1.3.7-h9c3ff4c_0
libwebp-base conda-forge/linux-64::libwebp-base-1.3.0-h0b41bf4_0
libxcb conda-forge/linux-64::libxcb-1.13-h7f98852_1004
libxkbcommon conda-forge/linux-64::libxkbcommon-1.5.0-h79f4944_1
libxml2 conda-forge/linux-64::libxml2-2.10.4-hfdac1af_0
lz4-c conda-forge/linux-64::lz4-c-1.9.4-hcb278e6_0
matplotlib conda-forge/linux-64::matplotlib-3.7.1-py310hff52083_0
matplotlib-base conda-forge/linux-64::matplotlib-base-3.7.1-py310he60537e_0
mpg123 conda-forge/linux-64::mpg123-1.31.3-hcb278e6_0
munkres conda-forge/noarch::munkres-1.1.4-pyh9f0ad1d_0
mysql-common conda-forge/linux-64::mysql-common-8.0.32-hf1915f5_2
mysql-libs conda-forge/linux-64::mysql-libs-8.0.32-hca2cd23_2
nspr conda-forge/linux-64::nspr-4.35-h27087fc_0
nss conda-forge/linux-64::nss-3.89-he45b914_0
openjpeg conda-forge/linux-64::openjpeg-2.5.0-hfec8fc6_2
pcre2 conda-forge/linux-64::pcre2-10.40-hc3806b6_0
pillow conda-forge/linux-64::pillow-9.5.0-py310h065c6d2_0
pixman conda-forge/linux-64::pixman-0.40.0-h36c2ea0_0
ply conda-forge/noarch::ply-3.11-py_1
pthread-stubs conda-forge/linux-64::pthread-stubs-0.4-h36c2ea0_1001
pulseaudio-client conda-forge/linux-64::pulseaudio-client-16.1-h5195f5e_3
pyparsing conda-forge/noarch::pyparsing-3.0.9-pyhd8ed1ab_0
pyqt conda-forge/linux-64::pyqt-5.15.7-py310hab646b1_3
pyqt5-sip conda-forge/linux-64::pyqt5-sip-12.11.0-py310heca2aa9_3
python-dateutil conda-forge/noarch::python-dateutil-2.8.2-pyhd8ed1ab_0
qt-main conda-forge/linux-64::qt-main-5.15.8-h5c52f38_10
sip conda-forge/linux-64::sip-6.7.9-py310hc6cd4ac_0
six conda-forge/noarch::six-1.16.0-pyh6c4a22f_0
toml conda-forge/noarch::toml-0.10.2-pyhd8ed1ab_0
tomli conda-forge/noarch::tomli-2.0.1-pyhd8ed1ab_0
tornado conda-forge/linux-64::tornado-6.3-py310h1fa729e_0
unicodedata2 conda-forge/linux-64::unicodedata2-15.0.0-py310h5764c6d_0
xcb-util conda-forge/linux-64::xcb-util-0.4.0-h166bdaf_0
xcb-util-image conda-forge/linux-64::xcb-util-image-0.4.0-h166bdaf_0
xcb-util-keysyms conda-forge/linux-64::xcb-util-keysyms-0.4.0-h166bdaf_0
xcb-util-renderut~ conda-forge/linux-64::xcb-util-renderutil-0.3.9-h166bdaf_0
xcb-util-wm conda-forge/linux-64::xcb-util-wm-0.4.1-h166bdaf_0
xkeyboard-config conda-forge/linux-64::xkeyboard-config-2.38-h0b41bf4_0
xorg-kbproto conda-forge/linux-64::xorg-kbproto-1.0.7-h7f98852_1002
xorg-libice conda-forge/linux-64::xorg-libice-1.0.10-h7f98852_0
xorg-libsm conda-forge/linux-64::xorg-libsm-1.2.3-hd9c2040_1000
xorg-libx11 conda-forge/linux-64::xorg-libx11-1.8.4-h0b41bf4_0
xorg-libxau conda-forge/linux-64::xorg-libxau-1.0.9-h7f98852_0
xorg-libxdmcp conda-forge/linux-64::xorg-libxdmcp-1.1.3-h7f98852_0
xorg-libxext conda-forge/linux-64::xorg-libxext-1.3.4-h0b41bf4_2
xorg-libxrender conda-forge/linux-64::xorg-libxrender-0.9.10-h7f98852_1003
xorg-renderproto conda-forge/linux-64::xorg-renderproto-0.11.1-h7f98852_1002
xorg-xextproto conda-forge/linux-64::xorg-xextproto-7.3.0-h0b41bf4_1003
xorg-xf86vidmodep~ conda-forge/linux-64::xorg-xf86vidmodeproto-2.3.1-h7f98852_1002
xorg-xproto conda-forge/linux-64::xorg-xproto-7.0.31-h7f98852_1007
zlib conda-forge/linux-64::zlib-1.2.13-h166bdaf_4
Preparing transaction: ...working... done
Verifying transaction: ...working... done
Executing transaction: ...working... done
Visualization Examples
Now we demonstrate four cases that tend to appear with binning analyses:
- The binning analysis converges to a plateau for a correlated data stream $R_X(\ell \rightarrow \infty) > 0$.
- The binning analysis reveals that the data stream is truly uncorrelated $R_X(\ell \rightarrow \infty) = 0$.
- The binning analysis has not converged because too few data were taken in the data stream to isolate the uncorrelated data.
- The binning analyis has not convered because all of the data in the data stream are more-or-less equally correlated.
The first two cases are ideal. They represent situations where the data stream has enough data to distinguish correlated blocks from one another. In these first two cases, the BinningAnalysisResult
will yield plateau_found == true
.
The second two cases are not so ideal. Either way they show that the correlations in the data stream are so strong that individual uncorrelated blocks can not be robustly created and more sampling is required. Therefore, their BinningAnalysisResult
yields plateau_found == false
.
The data shown are pre-simulated signals generated by the TelegraphNoise.jl
package (v0.1.0
). Random telegraph signals have an analytically-defined autocorrelation time $\tau_X$ related to their average dwell time $T_D$ by $\tau_X = T_D / 2$. Since the signals are random, they are saved previously, but I'll provide each chosen $T_D$ for reproducibility purposes.
Example 1: Clear $R_X$ plateau at a finite value
This first case shows the textbook (James Gubernatis, Naoki Kawashima, Philipp Werner (2016)) example of an $R_X$ plateau found in a binning analysis. The dwell time for this signal was chosen to be $T_D = 16$, meaning $\tau_X = 8$, and the signal generated was $2^{18} = 262144$ in length.
# Read in pre-simulated TelegraphNoise.jl data with a plateau
signal = zeros(Float64, Int(2^18))
read!( joinpath("assets", "telegraph_plateau.bin"), signal )
bacc = BinningAccumulator()
push!(bacc, signal)
plot_binning_analysis(bacc)
result = fit_RxValues(bacc)
result.plateau_found
# output
true
Importantly, note that the fitted inflection point is greater than zero, but less than the maximum trustworthy level. The variations in the calculated $R_X$ values for $\ell$ greater than the maximum trustworthy level are due to strong fluctuations because of small number statistics.
Example 2: Uncorrelated data ~ $R_X(\ell \rightarrow \infty) = 0$
The dwell time for this signal was chosen to be $T_D = 1/2$, meaning $\tau_X = 1/4$, and the signal generated was $2^{14} = 16384$ in length.
# Read in pre-simulated TelegraphNoise.jl data with a plateau
signal = zeros(Float64, Int(2^14))
read!( joinpath("assets", "telegraph_uncorrelated.bin"), signal )
bacc = BinningAccumulator()
push!(bacc, signal)
plot_binning_analysis(bacc)
result = fit_RxValues(bacc)
result.plateau_found
# output
true
Notice that the $R_X$ values decay for increasing $\ell$. This is because the binning analysis cannot detect any smaller blocks of uncorrelated data since the original data stream is indeed correlated.
Example 3: No plateau due to data insufficiency
For insufficiently long data streams, we do not expect a plateau, as shown in the following case:
# Read in pre-simulated TelegraphNoise.jl data without a plateau
signal = zeros(Float64, Int(2^10))
read!( joinpath("assets", "telegraph_no_plateau.bin"), signal )
bacc = BinningAccumulator()
push!(bacc, signal)
plot_binning_analysis(bacc)
result = fit_RxValues(bacc)
result.plateau_found
# output
false
Here, the dwell time was chosen to be $T_D = 256$, meaning $\tau_X = 128$, and the signal generated was $2^{10} = 1024$ in length. Notice, that the binning analysis began to pick up on a set of uncorrelated blocks, but there was not enough simulated data to reveal them before the maximum trustworthy level was reached. In a case like this, one would simply need to run their simulation about 64 times longer reveal a fitted plateau.
Example 4: No plateau due to totally-correlated data
In this final example, we demonstrate what happens for a data stream that has "frozen-in" correlations. By this, we mean one where the autocorrelation time $\tau_X$ far exceeds the data stream size. For this case, $T_D = 2^{16} = 65536$, so $\tau_X = 2^{15} = 32768$, while the signal length is only $2^{12} = 4096$.
# Read in pre-simulated TelegraphNoise.jl data with a plateau
signal = zeros(Float64, Int(2^12))
read!( joinpath("assets", "telegraph_totally_correlated.bin"), signal )
bacc = BinningAccumulator()
push!(bacc, signal)
plot_binning_analysis(bacc)
result = fit_RxValues(bacc)
result.plateau_found
# output
false
In this case, eventually the binning analysis returns $R_X = 0$, since the blocks start comparing literally identical elements. Notice that this case would return a plateau_found
if it were not for the check if any of the $R_X$ values were too small. (In principle this case also would result from a data stream with a defined periodicity, despite having correlations, but this is unavoidable.)
This is the most dangerous case to automate because the var
iance of such a data stream is naturally very small relative to the mean
. As is the case with all Monte Carlo simulations, or statistical data streams, one should be very wary when the error is a mathematical zero, or vanishingly small compared to the calculated mean
.