Gran ttwig: ~ 20 millones de muestras, gigabytes de datos.

Tengo un problema (con mi RAM) aquí: no es capaz de contener los datos que quiero trazar. Tengo suficiente espacio en HD. ¿Hay alguna solución para evitar la “sombra” de mi conjunto de datos?

Concretamente, trato con el procesamiento de señales digitales y tengo que utilizar una alta tasa de muestreo. Mi marco (GNU Radio) guarda los valores (para evitar utilizar demasiado espacio en disco) en binario. Lo desempaquetaré. Después necesito trazar. Necesito la ttwig con zoom, e interactiva. Y eso es un problema.

¿Existe algún potencial de optimización para esto, u otro software / lenguaje de progtwigción (como R o algo así) que pueda manejar conjuntos de datos más grandes? En realidad quiero muchos más datos en mis plots. Pero no tengo experiencia con otro software. GNUplot falla, con un enfoque similar al siguiente. No sé 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() 

Algo como plt.swap_on_disk () podría almacenar en caché las cosas en mi SSD;)

Entonces, sus datos no son tan grandes, y el hecho de que tenga problemas para trazarlos apunta a problemas con las herramientas. Matplotlib … no es tan bueno. Tiene muchas opciones y la salida está bien, pero es un gran problema de memoria y, fundamentalmente, supone que sus datos son pequeños. Pero hay otras opciones por ahí.

Entonces, como ejemplo, generé un archivo de punto de datos de 20M ‘bigdata.bin’ usando lo siguiente:

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

Esto genera un archivo de tamaño ~ 229MB, que no es tan grande; pero ha expresado que le gustaría ir a archivos aún más grandes, por lo que eventualmente alcanzará los límites de la memoria.

Concentrémonos primero en plots no interactivas. Lo primero que hay que tener en cuenta es que los diagtwigs vectoriales con glifos en cada punto serán un desastre: para cada uno de los 20 M puntos, la mayoría de los cuales se superpondrán de todos modos, al tratar de renderizar pequeñas cruces o círculos o algo está pasando. ser un diaster, generar archivos enormes y tomar toneladas de tiempo. Esto, creo que es lo que está hundiendo matplotlib por defecto.

Gnuplot no tiene problemas para lidiar con esto:

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

gnuplot

E incluso se puede hacer que Matplotlib se comporte con cierta precaución (elegir un fondo de ttwig y usar píxeles para marcar puntos):

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

Ahora, si desea interactiva, tendrá que agrupar los datos para trazar, y hacer zoom sobre la marcha. No conozco ninguna herramienta de python que te ayude a hacer esto de manera inmediata.

Por otro lado, trazar grandes datos es una tarea bastante común, y hay herramientas que están listas para el trabajo. Paraview es mi favorito personal, y VisIt es otro. Ambos son principalmente para datos 3D, pero Paraview, en particular, también hace 2d, y es muy interactivo (e incluso tiene una interfaz de scripts de Python). El único truco será escribir los datos en un formato de archivo que Paraview pueda leer fácilmente.

Ciertamente, puede optimizar la lectura de su archivo: puede leerlo directamente en una matriz NumPy, para aprovechar la velocidad bruta de NumPy. Tienes pocas opciones. Si la RAM es un problema, puede usar memmap , que mantiene la mayor parte del archivo en el disco (en lugar de en la RAM):

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

Si la RAM no es un problema, puede colocar toda la matriz en la RAM con fromfile :

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

Luego se puede realizar el trazado con la función de plot(*data) habitual de Matplotlib, posiblemente a través del método de “acercamiento” propuesto en otra solución.

Un proyecto más reciente tiene un gran potencial para grandes conjuntos de datos: Bokeh , que fue creado con exactamente esto en mente .

De hecho, solo los datos que son relevantes en la escala del gráfico se envían al backend de la pantalla. Este enfoque es mucho más rápido que el enfoque de Matplotlib.

Yo sugeriría algo un poco complejo, pero eso debería funcionar: construya su gráfica en diferentes resoluciones, para diferentes rangos.

Piense en Google Earth, por ejemplo. Si unzoom en el nivel máximo para cubrir todo el planeta, la resolución es la más baja. Cuando haces zoom, las imágenes cambian por imágenes más detalladas, pero solo en la región en la que te estás acercando.

Básicamente, para su gráfica (¿es 2D? 3D? Asumiré que es 2D), le sugiero que cree un gráfico grande que cubra todo el rango [0, n] con baja resolución, 2 gráficos más pequeños que cubran [0, n / 2] y [n / 2 + 1, n] con el doble de resolución que la grande, 4 gráficos más pequeños que cubren [0, n / 4] … [3 * n / 4 + 1, n] con dos veces La resolución de los 2 anteriores, y así sucesivamente.

No estoy seguro de que mi explicación sea muy clara. Además, no sé si este tipo de gráfico de resolución múltiple es manejado por algún progtwig de trazado existente.

Me pregunto si habrá una victoria al acelerar la búsqueda de sus puntos. (He estado intrigado por los árboles R * (estrella r) por un tiempo).

Me pregunto si usar algo como un r * tree en este caso podría ser el camino a seguir. (cuando se aleja, los nodos más altos en el árbol podrían contener información sobre la representación más gruesa, alejada, los nodos más hacia las hojas contienen las muestras individuales)

tal vez incluso la memoria asigne el árbol (o la estructura que termine usando) en la memoria para mantener su rendimiento y su uso de RAM bajo. (Usted descarga la tarea de administración de memoria al kernel)

Espero que tenga sentido … divagar un poco. ¡ya es tarde!