Подтвердить что ты не робот

Matplotlib savefig() графики, отличные от show()

Когда я использую show() для построения графиков в X, графики выглядят очень хорошо. Однако, когда я начинаю использовать savefig() для генерации большого количества графиков, savefig() порожденных графов 'font, lines, polygons все выглядят меньше, чем построенный граф show(). Моя среда - Ubuntu, а бэкэнд для show() - Qt4Agg. Как сделать график show() и график savefig() выглядит согласованным?

4b9b3361

Ответ 1

savefig указывает DPI для сохраненной фигуры (по умолчанию 100, если она не указана в вашем .matplotlibrc, посмотрите dpi kwarg до savefig). Это не выводит его из DPI исходного рисунка.

DPI влияет на относительный размер текста и ширину штриха на линиях и т.д. Если вы хотите, чтобы все выглядело одинаково, перейдите fig.dpi в fig.savefig.

например.

import matplotlib.pyplot as plt

fig = plt.figure()
plt.plot(range(10))
fig.savefig('temp.png', dpi=fig.dpi)

Ответ 2

Вы делаете свои графики matplotlib на разных устройствах (например, на экране через Quartz и to-file через pdf, используя различные функции (график по сравнению с savefig), параметры которого почти одинаковы, но значения по умолчанию для этих параметров не одинаковы для обеих функций.

Другими словами, параметры savefig отличаются от параметров дисплея по умолчанию.

Выравнивание их просто, если вы делаете это в файле конфигурации matplotlib. Файл шаблона включается в исходный пакет и называется matplotlibrc.template. Если вы не создали его при установке matplotlib, вы можете получить этот шаблон из источника matplotlib или с сайта matplotlib.

После того, как вы настроили этот файл так, как хотите, переименуйте его в matplotlibrc (без расширения) и сохраните его в каталоге .matplotlib (обратите внимание на "ведущий". '), который должен находиться в вашем домашнем каталоге.

Параметры конфигурации для сохранения цифр начинаются примерно по строке 314 в прилагаемой таблице matplotlibrc.template(первая строка перед этим разделом: ### SAVING FIGURES).

В частности, вы захотите посмотреть на них:

savefig.dpi       : 100         # figure dots per inch
savefig.facecolor : white       # figure facecolor when saving
savefig.edgecolor : white       # figure edgecolor when saving
savefig.extension : auto        # what extension to use for savefig('foo'), or 'auto'

Ниже этих строк указаны параметры шрифта и различные параметры формата изображения.

Эти же параметры для отображения, т.е. PLT.show(), начинаются примерно с строки 277 a на матплот-линке. (этот раздел предшествует строке: ### FIGURE):

figure.figsize   : 8, 6          
figure.dpi       : 80            
figure.facecolor : 0.75       
figure.edgecolor : white     

Как вы можете видеть, сравнивая значения этих двух блоков параметров, настройки по умолчанию для одного и того же атрибута фигуры отличаются для savefig и display (show).

Ответ 3

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

Проблема, по-видимому, связана с рендерингом; каждый из них получает правильные значения для ширины линии, размера шрифта и т.д., но это выглядит немного больше при визуализации в формате PDF или PNG, чем при визуализации с помощью show().

Я добавил несколько строк в источник для генерации PNG в файле matplotlib/backends/backend_agg.py. Вы можете сделать аналогичные изменения для каждого используемого вами бэкэнд или найти способ сделать более умное изменение в одном месте;)

Добавлен в файл matplotlib/backends/backend_agg.py:

    # The top of the file, added lines 42 - 44
42  # @warning: CHANGED FROM SOURCE to draw thinner lines
43  PATH_SCALAR = .8
44  FONT_SCALAR = .95

    # In the draw_markers method, added lines 90 - 91
89  def draw_markers(self, *kl, **kw):
90      # @warning: CHANGED FROM SOURCE to draw thinner lines
91      kl[0].set_linewidth(kl[0].get_linewidth()*PATH_SCALAR)
92      return self._renderer.draw_markers(*kl, **kw)

    # At the bottom of the draw_path method, added lines 131 - 132:
130 else:
131     # @warning: CHANGED FROM SOURCE to draw thinner lines
132     gc.set_linewidth(gc.get_linewidth()*PATH_SCALAR)
133     self._renderer.draw_path(gc, path, transform, rgbFace)

    # At the bottom of the _get_agg_font method, added line 242 and the *FONT_SCALAR
241     font.clear()
242     # @warning: CHANGED FROM SOURCE to draw thinner lines
243     size = prop.get_size_in_points()*FONT_SCALAR
244     font.set_size(size, self.dpi)

Так что теперь это соответствует моим потребностям, но, в зависимости от того, что вы делаете, вы можете захотеть реализовать аналогичные изменения в других методах. Или найдите лучший способ сделать то же самое без стольких изменений в строке!

Обновление: После публикации проблемы в проекте matplotlib в Github я смог отслеживать источник моей проблемы: я изменил параметр figure.dpi в файле matplotlibrc. Если это значение отличается от значения по умолчанию, мои снимки savefig() выглядят иначе, даже если я установил dpi с разрешением, равным числу dpi. Таким образом, вместо изменения источника, как указано выше, я просто сохранил параметр figure.dpi как значение по умолчанию 80 и смог генерировать изображения с помощью savefig(), которые выглядели как изображения из show().

Леон, изменили ли вы эту настройку?

Ответ 4

Старый вопрос, но, по-видимому, Google это нравится, поэтому я подумал, что я отвечу здесь после некоторого исследования этой проблемы.

Если вы создаете фигуру с нуля, вы можете указать ей параметр размера при создании:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(3, 6))

plt.plot(range(10)) #plot example
plt.show() #for control

fig.savefig('temp.png', dpi=fig.dpi)

figsize (width, height) регулирует абсолютную размерность вашего сюжета и помогает убедиться, что обе графики выглядят одинаково.

Как указано в другом ответе, параметр dpi влияет на относительный размер текста и ширину штриха на линиях и т.д. Используя параметр dpi = fig.dpi, убедитесь, что их относительный размер одинаковый как для показа (например, ) и savefig().

В качестве альтернативы размер фигуры можно изменить после создания с помощью:

fig.set_size_inches(3, 6, forward=True)

вперед позволяет изменять размер на лету.

Если у вас возникли проблемы со слишком большими границами в созданном изображении, вы можете настроить их либо с помощью:

plt.tight_layout()
#or:
plt.tight_layout(pad=2)

или

fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight')
#or:
fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight', pad_inches=0.5)

Первый вариант просто сводит к минимуму макет и границы, а второй вариант позволяет вручную немного отрегулировать границы. Эти советы помогли мне хотя бы решить мою проблему с различными изображениями savefig() и show().