绘制大数据

绘制大数据

众所周知,TikZ 必须面对 TeX 编译器给出的内存限制。

对于我的大多数图表,最大时间步长约为 1us,并且我在几秒钟内记录了几个波形,这导致了固有的内存问题。

我正在考虑使用 gnuplot 和 tikz,以便用 tikz 呈现轴,并且绘图将是我决定的大小的光栅图像。

有什么最佳实践吗?

(我将在今天结束前或周末发布一个最简单的例子)

评论我认为其中一种解决方法是将数据点栅格化,并以矢量图形绘制图例、轴等。理想情况下,栅格应该在绘图内制作,以保证其正确大小。我知道它的一部分matlab2tikz 2.0 发布

答案1

在处理这样的大矢量数据时,我非常担心出现(未被发现的)的可能性视觉混叠例如,考虑周期为 10(任意单位)的正弦信号,其噪声周期为 0.11。

#! /usr/bin/env python3
#
import math
import numpy as np
import scipy as sp

t1 = np.arange(0.0, 100.0, 1e-3)
y1 = np.sin(2*math.pi*t1/10) + 0.2*np.sin(2*math.pi*t1/0.11)
raw = np.column_stack((t1, y1))
np.savetxt("rawdata.dat", raw)

数据在文件中rawdata.dat,您有 100000 个点。

pgfplots会给你一个“TeX 容量超出”但你可以用以下方法绘制它:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}\pgfplotsset{compat=1.13}
\usetikzlibrary{arrows.meta,positioning,calc}
\begin{document}
\begin{tikzpicture}[
    ]
        \begin{axis}[
            xmin=0, xmax=100, 
            ymin=-1.5, ymax=1.5,
            axis x line = center, 
            axis y line = center,
            axis line style = {thick, gray},
            xlabel = {$x$},
            % every axis x label/.append style = {below, gray},
            ylabel = {$y$},
            legend style = {nodes=right},
            legend pos = north east,
            clip mode = individual,
            ]
            \addplot[blue]  table [x index=0, y index=1, each nth point={100}] {rawdata.dat};
        \end{axis}
\end{tikzpicture}
\end{document}

使用该each nth point功能。您将获得:

with aliasing

...这完全是错误的。噪声的周期似乎是真实周期的 10 倍;真实周期在以下gnuplot图表中可见:

aliasing explained

您可以看到错误来自何处。任何类型的子采样都必须小心执行以避免这种情况。

我通常会对数据进行预处理,并找出要抽取的每一片样本的平均值、最大值和最小值(将这段代码添加到上面的python脚本中):

SAMPLE=100
np.savetxt("sampledata.dat", raw[0::SAMPLE, :])
#
# create the file with t, y, ymin, ymax
#
reducedlen = math.floor(len(t1)/SAMPLE) 
reduced = np.zeros([reducedlen, 4])
for i in range(0, reducedlen):
    j = i*SAMPLE 
    reduced[i, 0] = t1[j]
    reduced[i, 1] = np.average(y1[j:j+SAMPLE])
    reduced[i, 2] = np.min(y1[j:j+SAMPLE])
    reduced[i, 3] = np.max(y1[j:j+SAMPLE])
np.savetxt("reduced.dat", reduced)

然后我滥用error bars它们在平均信号周围形成一个“噪声带”(顺便提一句:您应该在此处使用更好的抗锯齿过滤器。平均值只是一个例子,有时可能会失败)。代码将是:

 \addplot[red,
          error bars/.cd, 
          y dir=both, 
          y explicit, 
          % error bar style={line width=2pt,}, % if you need it!
          error mark options={
              red,
              mark size=0pt,
          }
          ] 
          table [x index=0, y index=1, header = false, 
              y error minus expr = \thisrowno{1}-\thisrowno{2}, 
              y error plus expr = \thisrowno{3}-\thisrowno{1},
          ]{reduced.dat};

结果如下——可能不是很好,但它是安全的

Final diagram

fill between顺便说一句,使用最小值和最大值也可以获得相同的图表,这可能更合乎逻辑:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}\pgfplotsset{compat=1.13}
\usetikzlibrary{arrows.meta,positioning,calc}
\usepgfplotslibrary{fillbetween}
\begin{document}
\begin{tikzpicture}[
    ]
        \begin{axis}[
            xmin=0, xmax=100, 
            ymin=-1.5, ymax=1.5,
            axis x line = center, 
            axis y line = center,
            axis line style = {thick, gray},
            xlabel = {$x$},
            % every axis x label/.append style = {below, gray},
            ylabel = {$y$},
            legend style = {nodes=right},
            legend pos = north east,
            clip mode = individual,
            ]
            \addplot[red, name path = minimum]
                table [x index=0, y index=2, header=false]{reduced.dat};
            \addplot[red, name path = maximum]
                table [x index=0, y index=3, header=false]{reduced.dat};
            \addplot[red] fill between [of=minimum and maximum];
        \end{axis}
\end{tikzpicture}
\end{document}

请注意,视觉混叠可以如果您使用全套数据,也会发生超出您控制范围的情况:在打印机中、在 PDF 查看器中等(它们应该具有内置的抗锯齿滤波器,但是——我更喜欢首先提供好的数据)。

答案2

光栅图像是一个好主意(可能最适合这种用例,矢量图像太大了)。

关键点是:您能否使用确定的边界框导出光栅图像,即您始终知道左下角的轴坐标和右上角的轴坐标?

如果是这样,您可以使用pgfplots它的\addplot graphics功能。手册中显示的第一个示例pgfplots

\begin{tikzpicture}
    \begin{axis}[enlargelimits=false,axis on top]
        \addplot graphics
            [xmin=-3,xmax=3,ymin=-3,ymax=3]
            {external1};
    \end{axis}
\end{tikzpicture}

假设这external1是一个具有紧密边界框的(光栅)图像,并且提供的限制分别是左下角和右上角的限制。

然而,生成具有明确边界框的图像并不像乍一看那么简单:许多程序会生成人工空间,而时间序列的 y 范围可能会影响导出图像的高度。

为了实现“开销小”的最佳实践,您可能需要编写一个代码生成器,它既生成外部图形,又生成相关的轴限值。在最简单的情况下,相关的轴限值是固定的,图像将始终适合。

参考文献: pgfplots 手册和相关问题pgfplots 中的三维直方图

相关内容