Большой участок: ~20 миллионов образцов, гигабайт данных


У меня есть проблема (с моей ОЗУ) здесь: он не в состоянии держать данные, которые я хочу построить. У меня достаточно места для HD. Есть ли какое-либо решение, чтобы избежать этого "затенения" моего набора данных?

конкретно я имею дело с цифровой обработкой сигнала, и я должен использовать высокую частоту дискретизации. Мой фреймворк (GNU Radio) сохраняет значения (чтобы не использовать слишком много места на диске) в двоичном формате. Я распаковываю его. После этого мне нужно построить заговор. Мне нужен сюжет масштабируемый и интерактивный. И это проблема.

есть ли потенциал оптимизации для этого или другого программного обеспечения / языка программирования (например, R или так), который может обрабатывать большие наборы данных? На самом деле я хочу гораздо больше данных в мои планы. Но у меня нет опыта работы с другими программами. GNUplot терпит неудачу, с аналогичным подходом к следующему. Я не знаю R (jet).

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;)

5 55

5 ответов:

таким образом, ваши данные не так уж велики, и тот факт, что у вас возникли проблемы с его построением, указывает на проблемы с инструментами. Matplotlib.... разве это не хорошо. У него есть много вариантов, и выход в порядке, но это огромная память, и она принципиально предполагает, что ваши данные малы. Но есть и другие варианты.

Итак, в качестве примера, я сгенерировал файл 20M data-point ' bigdata.Бинь, используя следующие кнопки:

#!/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()

это создает файл размером ~229 МБ, который это не так уж и много; но вы выразили, что хотели бы перейти к еще большим файлам, поэтому в конечном итоге вы попадете в пределы памяти.

давайте сначала сосредоточимся на неинтерактивных сюжетах. Первое, что нужно понять, это то, что векторные графики с глифами в каждой точке будут катастрофой - для каждой из 20 м точек, большинство из которых все равно будут перекрываться, пытаясь отобразить маленькие кресты или круги или что-то будет диастером, генерируя огромные файлы и принимая тонны время. Это, я думаю, то, что тонет matplotlib по умолчанию.

Gnuplot не имеет никаких проблем с этим:

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

gnuplot

и даже 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()  

matplotlib

Теперь, если вы хотите интерактивную, вам придется бин данные для построения графика, и увеличить на лету. Я не знаю никаких инструментов python, которые поможет вам сделать это навскидку.

С другой стороны, построение больших данных-довольно распространенная задача, и есть инструменты, которые подходят для этой работы. Paraview мой личный фаворит, и посетить еще один. Они оба в основном предназначены для 3D-данных, но Paraview, в частности, также делает 2d и очень интерактивен (и даже имеет интерфейс сценариев Python). Единственный трюк будет заключаться в том, чтобы записать данные в формат файла, который Paraview может легко читать.

вы можете, конечно, оптимизировать чтение вашего файла: вы можете напрямую прочитать его в массив NumPy, чтобы использовать необработанную скорость NumPy. У вас есть несколько вариантов. Если ОЗУ является проблемой, вы можете использовать memmap, который держит большую часть файла на диске (а не в оперативной памяти):

# Each data point is a sequence of three 32-bit floats:
data = np.memmap(filename, mode='r', dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])

Если ОЗУ не является проблемой, вы можете поместить весь массив в ОЗУ с fromfile:

data = np.fromfile(filename, dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])

построение графика может быть сделано с обычным Matplotlib plot(*data) функция, возможно, через метод "увеличения", предложенный в другом решении.

более поздний проект имеет большой потенциал для больших наборов данных:размытие, который был создан с именно это в виду.

на самом деле, только данные, которые имеют отношение к масштабу графика, отправляются на бэкэнд дисплея. Этот подход намного быстрее, чем подход Matplotlib.

Я бы предложил что-то немного сложное, но это должно работать : построить свой график в разных разрешениях, для разных диапазонов.

подумайте о Google Earth, например. Если вы unzoom на максимальном уровне, чтобы охватить всю планету, разрешение является самым низким. При увеличении изображения меняются на более подробные, но только в том регионе, на который вы увеличиваете масштаб.

Так что в основном для вашего сюжета (это 2D ? 3D ? Я предполагаю, что это 2D), я предлагаю вам построить один большой график это охватывает весь диапазон [0, n] с низким разрешением, 2 меньших графика, которые охватывают [0, n/2] и [n/2 + 1, n] с удвоенным разрешением большого, 4 меньших графика, которые охватывают [0, n/4] ... [3 * n / 4 + 1, n] с удвоенным разрешением 2 выше, и так далее.

Не уверен, что мое объяснение очень ясно. Кроме того, я не знаю, обрабатывается ли такой график с несколькими разрешениями любой существующей программой построения.

интересно, есть ли выигрыш, чтобы ускорить поиск ваших очков? (Я был заинтригован r* (r star) деревья на некоторое время.)

интересно, если использовать что-то вроде дерева r* в этом случае может быть путь. (при уменьшении масштаба более высокие узлы в дереве могут содержать информацию о более грубом, уменьшенном рендеринге, узлы дальше к листьям содержат отдельные образцы)

может быть, даже карта памяти дерева (или любой структуры вы в конечном итоге использование) в память, чтобы сохранить производительность и низкое использование ОЗУ. (вы разгружаете задачу управления памятью в ядро)

надеюсь, что это имеет смысл.. немного бессвязно. уже поздно!