1. ホーム
  2. python

[解決済み] 2,000万点のサンプルとギガバイトデータの対話型大規模プロット

2023-02-21 06:07:07

質問

RAMに問題が発生しました。私は十分な HD 領域を持っています。私のデータセットのシャドウイングを回避するための解決策はありますか?

具体的には、私はデジタル信号処理を扱っており、高いサンプルレートを使用する必要があります。私のフレームワーク (GNU Radio) は、値をバイナリで保存します (あまりにも多くのディスクスペースを使用しないようにするために)。私はそれを解凍します。その後、私はプロットする必要があります。プロットはズーム可能で、インタラクティブである必要があります。そして、それは問題です。

これに対する最適化の可能性、またはより大きなデータセットを扱うことができる別のソフトウェア/プログラミング言語(Rなど)はありますか?実際、私は自分のプロットでより多くのデータが欲しいのです。しかし、私は他のソフトウェアを使った経験がありません。GNUplotは以下のようなアプローチで、失敗します。私はR(ジェット)を知りません。

import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import struct

"""
plots a cfile

cfile - IEEE single-precision (4-byte) floats, IQ pairs, binary
txt - index,in-phase,quadrature in plaintext

note: directly plotting with numpy results into shadowed functions
"""

# unpacking the cfile dataset
def unpack_set(input_filename, output_filename):
    index = 0   # index of the samples
    output_filename = open(output_filename, 'wb')

    with open(input_filename, "rb") as f:

        byte = f.read(4)    # read 1. column of the vector

        while byte != "":
        # stored Bit Values
            floati = struct.unpack('f', byte)   # write value of 1. column to a variable
            byte = f.read(4)            # read 2. column of the vector
            floatq = struct.unpack('f', byte)   # write value of 2. column to a variable
            byte = f.read(4)            # next row of the vector and read 1. column
            # delimeter format for matplotlib 
            lines = ["%d," % index, format(floati), ",",  format(floatq), "\n"]
            output_filename.writelines(lines)
            index = index + 1
    output_filename.close
    return output_filename.name

# reformats output (precision configuration here)
def format(value):
    return "%.8f" % value            

# start
def main():

    # specify path
    unpacked_file = unpack_set("test01.cfile", "test01.txt")
    # pass file reference to matplotlib
    fname = str(unpacked_file)
    plt.plotfile(fname, cols=(0,1)) # index vs. in-phase

    # optional
    # plt.axes([0, 0.5, 0, 100000]) # for 100k samples
    plt.grid(True)
    plt.title("Signal-Diagram")
    plt.xlabel("Sample")
    plt.ylabel("In-Phase")

    plt.show();

if __name__ == "__main__":
    main()

plt.swap_on_disk()のようなものは、SSD上のものをキャッシュすることができます ;)

どのように解決するのですか?

あなたのデータはそれほど大きくなく、プロットに問題があるということは、ツールの問題を指摘しています。 Matplotlib には多くのオプションがあり、出力も問題ありませんが、非常に多くのメモリを消費しますし、基本的にデータが小さいことを前提としています。 しかし、他の選択肢もあります。

そこで例として、20Mのデータポイントファイル'bigdata.bin'を以下のようにして生成してみました。

#!/usr/bin/env python
import numpy
import scipy.io.numpyio

npts=20000000
filename='bigdata.bin'

def main():
    data = (numpy.random.uniform(0,1,(npts,3))).astype(numpy.float32)
    data[:,2] = 0.1*data[:,2]+numpy.exp(-((data[:,1]-0.5)**2.)/(0.25**2))
    fd = open(filename,'wb')
    scipy.io.numpyio.fwrite(fd,data.size,data)
    fd.close()

if __name__ == "__main__":
    main()

これはサイズ ~229MB のファイルを生成し、それほど大きくはありません。しかし、さらに大きなファイルにしたいと表明しているので、いずれはメモリの限界に達するでしょう。

まず、非インタラクティブなプロットに集中しましょう。 20 M の点のそれぞれについて、そのほとんどがいずれにせよ重なり、小さな十字や円などをレンダリングしようとすると、巨大なファイルを生成して膨大な時間がかかるため、大惨事になりそうだということです。 これは、デフォルトでmatplotlibを沈没させているものだと私は思います。

Gnuplot はこれを扱うのに何の問題もありません。

gnuplot> set term png
gnuplot> set output 'foo.png'
gnuplot> plot 'bigdata.bin' binary format="%3float32" using 2:3 with dots

<イグ

そして、Matplotlibでさえも、いくつかの注意(ラスターバックエンドを選択し、ポイントをマークするためにピクセルを使用すること)で動作させることが可能です。

#!/usr/bin/env python
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

datatype=[('index',numpy.float32), ('floati',numpy.float32), 
        ('floatq',numpy.float32)]
filename='bigdata.bin'

def main():
    data = numpy.memmap(filename, datatype, 'r') 
    plt.plot(data['floati'],data['floatq'],'r,')
    plt.grid(True)
    plt.title("Signal-Diagram")
    plt.xlabel("Sample")
    plt.ylabel("In-Phase")
    plt.savefig('foo2.png')

if __name__ == "__main__":
    main()  

<イグ

さて、インタラクティブにしたいのであれば、プロットするデータをビン詰めし、その場でズームインする必要があります。 これを行うのに役立つPythonのツールを私は知らないのです。

一方、ビッグデータのプロットはかなり一般的なタスクであり、そのためのツールもあります。 パラビュー は私の個人的なお気に入りです。 VisIt はもう一つのお気に入りです。 どちらも主に3Dデータ用ですが、特にParaviewは2Dも扱え、非常にインタラクティブです(Pythonのスクリプトインターフェースもあります)。 唯一のコツは、Paraview が簡単に読めるファイル形式にデータを書き込むことでしょう。