library for python performance matplotlib scientific-computing

python - for - Gran parcela: ~ 20 millones de muestras, gigabytes de datos



scipy for python (5)

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 una gran fuente de memoria y supone fundamentalmente 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 llegará a los límites de memoria con el tiempo.

Concentrémonos primero en parcelas no interactivas. Lo primero es darse cuenta de que las tramas vectoriales con glifos en cada punto serán un desastre, para cada uno de los 20 puntos M, la mayoría de los cuales se superpondrán de todos modos, tratando de hacer pequeños cruces o círculos o algo va a suceder ser un diaster, generar grandes archivos 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

E incluso se puede hacer que Matplotlib se comporte con precaución (eligiendo un fondo ráster y usando 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()

Ahora, si quieres interactividad, vas a tener que bin los datos para trazar, y hacer zoom sobre la marcha. No conozco ninguna herramienta de pitón que te ayude a hacer esto de forma espontánea.

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

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

En concreto, me ocupo del procesamiento digital de señales y tengo que usar una alta frecuencia de muestreo. Mi marco (Radio GNU) guarda los valores (para evitar usar demasiado espacio en el disco) en formato binario. Lo descomprimo Después, necesito trazar. Necesito el diagrama zoomable e interactivo. Y ese es un problema.

¿Hay algún potencial de optimización para esto u otro software / lenguaje de programación (como R o más) que pueda manejar conjuntos de datos más grandes? En realidad, quiero mucha más información en mis tramas. Pero no tengo experiencia con otro software. GNUplot falla, con un enfoque similar al siguiente. No sé R (chorro).

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


Me pregunto si habrá una victoria acelerando la búsqueda de tus puntos. (Me han intrigado los árboles R * (r star) por un tiempo).

Me pregunto si usar algo como un árbol r * en este caso podría ser el camino a seguir. (cuando se aleja, los nodos superiores en el árbol pueden 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 mapee el árbol (o la estructura que termine usando) en la memoria para mantener su rendimiento y el uso de RAM bajo. (descarga la tarea de gestión de memoria al kernel)

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


Sin duda, 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, puedes poner toda la matriz en la RAM con fromfile :

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

El trazado se puede hacer con la función de plot(*data) habitual plot(*data) Matplotlib, posiblemente a través del método "zoom in" propuesto en otra solución.


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

Piensa en Google Earth, por ejemplo. Si desciende al nivel máximo para cubrir todo el planeta, la resolución es la más baja. Cuando haces zoom, las imágenes cambian para obtener más detalles, pero solo en la región en la que estás haciendo zoom.

Así que, básicamente, para su trama (¿es 2D? 3D? Asumiré que es 2D), le sugiero que cree una gráfica 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 el 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 realmente clara. Además, no sé si este tipo de gráfico de resolución múltiple es manejado por cualquier programa de trazado existente.


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 relevantes en la escala de la trama se envían al backend de la pantalla. Este enfoque es mucho más rápido que el enfoque de Matplotlib.