Ошибка памяти при построении больших файлов осциллографа в Ubuntu

#python-3.x #matplotlib #plot #garbage-collection

#python-3.x #pandas #matplotlib

Вопрос:

Я пытаюсь прочитать большие .trc файлы осциллографа и отобразить их. Построение одного файла работает, но как только я помещаю скрипт в цикл, пытаюсь отобразить все файлы (по 1 файлу в цикл) Я получаю MemoryError .

Код:

 import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import readTrc #external file, same location as script

foldername = 'trc_folder'
folder = os.listdir(foldername)
path = os.path.dirname(os.path.realpath(__file__))

for filenumber, i in enumerate(folder):
    trc = path   '/'   foldername   '/'   i

    print('reading trc file '   str(filenumber))

    datX, datY, m = readTrc.readTrc(trc)
    srx, sry = pd.Series(datX * 1000), pd.Series(datY * 1000)
    df_oszi = pd.concat([srx, sry], axis = 1)
    df_oszi.set_index(0, inplace = True)    

    #ERROR APPEARS with xticks argument
    #removing xticks does not help, because then errorpath changes to
    #/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py
    df_oszi.plot(grid = 1,
                 color = 'blue',
                 linewidth = 0.5,
                 figsize = (9,5),
                 legend = False,
                 xticks = np.arange(df_oszi.index[0], df_oszi.index[-1], 1))

    print('plotting file '   str(filenumber))
    plt.savefig('Plot_'   str(filenumber)   '.png', dpi = 300)
  

Похоже, проблема во внешнем модуле readTrc . Мне потребовалось довольно много времени, чтобы разобраться в этом, потому что python выдавал ошибки вокруг Matplotlib и Pandas вместо readTrc , что, похоже, является неофициальным сценарием для чтения .trc файлов. Я нашел это в сети, когда искал способ чтения .trc файлов на python. Если вы знаете лучший способ чтения файлов осциллографа, пожалуйста, дайте мне знать.

Я заархивировал все, что вам нужно для выполнения скрипта, в эту папку: папка

(Он довольно большой, 582MB потому что каждый .trc файл имеет примерно 200MB размер) Внутри вы найдете скрипт, папку с .trc файлами и внешний файл (модуль) python, readTrc который требуется для чтения .trc файлов. Выполнение скрипта должно отображать первый файл, но выбрасывать MemoryError при построении второго, по крайней мере, на моей машине Ubuntu. Меня смущает то, что я получаю это только MemoryError в Ubuntu (18.04), а не в Windows 10.

Я был бы признателен за помощь, чтобы я мог продолжить свой проект. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Редактировать:

Единственная загрузка для readTrc.py

Единственная загрузка для Script.py

print(type(datX)) ВОЗВРАТ:

 <class 'numpy.ndarray'>
  

печать datX возвращает объект с 50 миллионами значений:

 [-0.005 -0.005 -0.005 ...  0.005  0.005  0.005]
  

они округляются по print() функции и являются:

 -0.004999999906663635
-0.004999999806663634
-0.004999999706663633
-0.004999999606663631
-0.00499999950666363
  

Edit 2:

Чтобы запустить код с новой версией readTrc , внесите эти изменения:

 import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import readTrc

foldername = 'trc_folder'
folder = os.listdir(foldername)
path = os.path.dirname(os.path.realpath(__file__))

for filenumber, i in enumerate(folder):
    trc = path   '/'   foldername   '/'   i

    print('reading trc file '   str(filenumber))

    datX, datY, d = readTrc.Trc().open(trc)
    srx, sry = pd.Series(datX * 1000), pd.Series(datY * 1000)
    df_oszi = pd.concat([srx, sry], axis = 1)
    df_oszi.set_index(0, inplace = True)    

    df_oszi.plot(grid = 1,
                 color = 'blue',
                 linewidth = 0.5,
                 figsize = (9,5),
                 legend = False,
                 xticks = np.arange(df_oszi.index[0], df_oszi.index[-1], 1))

    print('plotting file '   str(filenumber))
    plt.savefig('Plot_'   str(filenumber)   '.png', dpi = 300)
  

Ошибка памяти:

 Traceback (most recent call last):
  File "/home/artur/Desktop/zip_original/Script.py", line 27, in <module>
    xticks = np.arange(df_oszi.index[0], df_oszi.index[-1], 1))
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 2941, in __call__
    sort_columns=sort_columns, **kwds)
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 1977, in plot_frame
    **kwds)
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 1804, in _plot
    plot_obj.generate()
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 260, in generate
    self._make_plot()
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 985, in _make_plot
    **kwds)
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 1001, in _plot
    lines = MPLPlot._plot(ax, x, y_values, style=style, **kwds)
  File "/usr/local/lib/python3.6/dist-packages/pandas/plotting/_core.py", line 615, in _plot
    return ax.plot(*args, **kwds)
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/__init__.py", line 1805, in inner
    return func(ax, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/axes/_axes.py", line 1604, in plot
    self.add_line(line)
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/axes/_base.py", line 1891, in add_line
    self._update_line_limits(line)
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/axes/_base.py", line 1913, in _update_line_limits
    path = line.get_path()
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/lines.py", line 945, in get_path
    self.recache()
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/lines.py", line 649, in recache
    self._xy = np.column_stack(np.broadcast_arrays(x, y)).astype(float)
MemoryError
  

Редактировать 3:

Выборка набора данных, похоже, уменьшает значение данных. Это примеры одного и того же набора данных с sampling = 1, sampling = 10, sampling = 100

 srx, sry = pd.Series(datX[::sampling] * 1000), pd.Series(datY[::sampling] * 1000)
  

введите описание изображения здесь
введите описание изображения здесь
введите описание изображения здесь

Причиной этого является чрезвычайно короткий период импульса волн сверхвысокой частоты (УВЧ). Каждый импульс может состоять только из нескольких значений данных. Если вы укажете количество учитываемых значений, это приведет к большой потере данных. Хотя это решение заставляет код работать, оно также значительно снижает ценность данных.

Комментарии:

1. Не могли бы вы также загрузить только readTrc.py файл? Я действительно не хочу загружать ~ 600 МБ для этого 🙂 Помимо этого: что возвращает print(type(datX)) ? Это list , numpy.ndarray , dataframe ? Вы пробовали использовать этот модуль readTrc ?

2. Пожалуйста, найдите запрошенную информацию в разделе Редактировать

3. Что касается readTrc module : кажется, что я использую старую версию этого файла с 2017 года. Я просто попытался заменить старый на новый, но, похоже, для его работы требуются дополнительные усилия. Я попытаюсь запустить скрипт с новой версией.

4. Хорошо, итак, если datX=[1,2,3] это действительно список (к сожалению, вы не опубликовали возврат print(type(datX)) ), то print(10*a) выдаст вам [1, 2, 3, 1, 2, 3,…..] , то есть список, умноженный на десять. Вероятно, это не то, что вы хотите, поэтому сначала попробуйте сделать его массивом numpy, т.Е. datX=np.array(datX) и datY=np.array(datY) сразу после вызова readTrc.readTrc()

5. Извините, я перепутал print() с print(type()) . Я добавил его в раздел » Редактировать «. На самом деле это <class 'numpy.ndarray'>

Ответ №1:

О, вау, я не мог видеть дерево за деревьями, как говорится. Вы пытаетесь построить слишком много точек данных (т. 100000002 Я думаю, что это около 4 км бумаги, напечатанной со скоростью 600 точек на дюйм), что может быть разрешено либо путем выборки:

 sampling=100
srx, sry = pd.Series(datX[::sampling] * 1000), pd.Series(datY[::sampling] * 1000)
  

или выборочным изучением определенных диапазонов:

 srx, sry = pd.Series(datX[0:50000] * 1000), pd.Series(datY[0:50000] * 1000)
  

или комбинация обоих.

Комментарии:

1. Спасибо вам за ваши усилия до сих пор. Вы мне очень помогли. Хотя, боюсь, я не могу реализовать это решение. Пожалуйста, смотрите раздел Редактировать 3 .

2. Я боюсь, что вы путаете видимые функции с присутствующими функциями . Становятся ли ваши короткие импульсы видимыми на графике, зависит от размера вашего рисунка / разрешения / масштабирования. Вам нужно найти способ минимизировать объем данных, возможно, с помощью БПФ сигнала или путем отбрасывания значений, где, например, np.abs (y)<=1.

Ответ №2:

Это заняло довольно много времени, но мне удалось взять MemoryError под контроль. Мне приходилось не только ставить gc.collect() в конце каждого цикла, но и plt.close() . Только тогда ошибки прекратятся. Извините за путаницу. Я многому научился из этого.