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:

  1. The binning analysis converges to a plateau for a correlated data stream $R_X(\ell \rightarrow \infty) > 0$.
  2. The binning analysis reveals that the data stream is truly uncorrelated $R_X(\ell \rightarrow \infty) = 0$.
  3. The binning analysis has not converged because too few data were taken in the data stream to isolate the uncorrelated data.
  4. 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.)

Tip

This is the most dangerous case to automate because the variance 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.