2025, Nov 01 01:46
Единый шрифт для индексов в Matplotlib: Computer Modern
Почему индексы в Matplotlib меняют начертание и как это исправить: используем Computer Modern для подписей, \mathregular, настройки mathtext и Unicode-символы.
Сохранение визуальной согласованности графиков с отчётом важно, особенно когда внутри одной подписи шрифты расходятся. Частая неприятность в Matplotlib — надстрочные и подстрочные индексы в подписях выводятся другим начертанием, чем окружающий текст, даже если задано конкретное семейство шрифтов. Если вы используете Computer Modern (стандартный шрифт pdfLaTeX) и замечаете, что надстрочная 2 в «W/cm²» выглядит неуместно, решение простое.
Постановка задачи
Цель — использовать Computer Modern во всей фигуре: заголовки, подписи осей и единицы. Конфигурация ниже выбирает семейство с засечками и начертание cmr10 и включает обработку математического текста:
import matplotlib.pyplot as gp
import matplotlib as mp
mp.rcParams['font.family'] = "serif"
mp.rcParams['font.serif'] = "cmr10"
mp.rcParams['axes.formatter.use_mathtext'] = True
canvas, axes = gp.subplots()
axes.set_title('Results', fontsize=18)
axes.set_ylabel(r'Heat Flux (W/cm$^2$)', fontsize=18)
axes.set_xlabel('Wall Superheat (K)', fontsize=18)
axes.legend()
Подпись выводится, но надстрочная 2 не использует то же начертание, что остальной текст. Та же визуальная несовместимость проявляется и с подстрочными индексами.
Что происходит
Шрифт переключается в момент перехода к математическому тексту. В примере выше фрагмент внутри знаков доллара обрабатывается иначе, чем окружающая строка, поэтому надстрочная 2 набирается математическим шрифтом, который не совпадает с выбранной гарнитурой с засечками. В итоге возникает лёгкая, но заметная несогласованность между обозначением единиц и показателем степени.
Решение
Заставьте математический фрагмент использовать обычный текстовый шрифт. Проще всего обернуть строку с единицами в \mathregular, оставив надстрочный индекс внутри:
import matplotlib.pyplot as gp
import matplotlib as mp
mp.rcParams['font.family'] = "serif"
mp.rcParams['font.serif'] = "cmr10"
mp.rcParams['axes.formatter.use_mathtext'] = True
fig_obj, axis_ref = gp.subplots()
axis_ref.set_title('Results', fontsize=18)
axis_ref.set_ylabel('Heat Flux ($\mathregular{W/cm^{2}}$)', fontsize=18)
axis_ref.set_xlabel('Wall Superheat (K)', fontsize=18)
Так надстрочная 2 будет выведена тем же начертанием Computer Modern, что и остальная подпись.
Другой способ заставить математическую часть следовать выбранному шрифту — настроить параметры математического текста. В дополнение к текущим настройкам задайте:
mp.rcParams['mathtext.fontset'] = "custom"
mp.rcParams['mathtext.rm'] = "serif"
Если математический режим не требуется, можно вовсе обойтись без него, используя в строке подписи Unicode-символ надстрочной цифры:
axis_ref.set_ylabel('Heat Flux (W/cm\u00b2)', fontsize=18)
Почему это важно
Несогласованность шрифтов ломает ритм фигуры и делает иначе аккуратные графики неровными. Когда рисунки идут в статьи, диссертации или отчёты, где используется Computer Modern, несоответствующие надстрочные индексы отвлекают от данных. Если показатель степени и окружающий текст набраны одним и тем же начертанием, визуальный ряд остаётся цельным и профессиональным.
Выводы
Следите за тем, когда строки подписи переключаются в математический режим. Если нужны надстрочные или подстрочные индексы и при этом важно сохранить вид вашего текстового шрифта, оберните нужный фрагмент в \mathregular или подстройте параметры mathtext так, чтобы математика наследовала выбранную гарнитуру с засечками. Когда разбор математики не нужен, надстрочная цифра Unicode — простой и чистый альтернативный вариант. Последовательность в этом вопросе окупается читабельностью и качеством подачи.
Статья основана на вопросе на StackOverflow от simply_a_student и ответе от simply_a_student.