Ось X-паразитов на графике журнала - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть график, где ось X является температурой в ГэВ, но мне также нужно указать эталон температуры в Кельвинах, поэтому я подумал о том, чтобы поместить ось паразита с температурой в К. Попытка следовать этомуответ Как добавить вторую ось x в matplotlib , Вот пример кода.В верхней части графика я получаю вторую ось, но это не та температура в К, которая мне нужна.

import numpy as np
import matplotlib.pyplot as plt

tt = np.logspace(-14,10,100)
yy = np.logspace(-10,-2,100)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()

ax1.loglog(tt,yy)
ax1.set_xlabel('Temperature (GeV')

new_tick_locations = np.array([.2, .5, .9])

def tick_function(X):
    V = X*1.16e13
    return ["%.1f" % z for z in V]

ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(ax1Xs))
ax2.set_xlabel('Temp (Kelvin)')
plt.show()

Это то, что я получаю, когда запускаю код.

loglog plot loglog plot

Мне нужно, чтобы ось паразита была пропорциональна исходной оси x.И это может быть легко прочитать температуру в Кельвинах, когда кто-то видит график.Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Решение общего назначения может выглядеть следующим образом.Поскольку у вас есть нелинейный масштаб, идея состоит в том, чтобы найти позиции хороших тиков в Кельвинах, преобразовать в ГэВ, установить позиции в единицах ГэВ, но пометить их в единицах Кельвина.Это звучит сложно, но преимущество в том, что вам не нужно находить тиков самостоятельно, просто полагайтесь на matplotlib для их поиска.Однако для этого требуется функциональная зависимость между двумя шкалами, т. Е. Переход между ГэВ и Кельвином и его обратное.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

tt = np.logspace(-14,10,100)
yy = np.logspace(-10,-2,100)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()

plt.setp([ax1,ax2], xscale="log", yscale="log")
ax1.get_shared_x_axes().join(ax1, ax2)

ax1.plot(tt,yy)

ax1.set_xlabel('Temperature (GeV)')
ax2.set_xlabel('Temp (Kelvin)')

fig.canvas.draw()

# 1 GeV == 1.16 × 10^13 Kelvin
Kelvin2GeV = lambda k:  k / 1.16e13
GeV2Kelvin = lambda gev: gev * 1.16e13

loc = mticker.LogLocator()
locs = loc.tick_values(*GeV2Kelvin(np.array(ax1.get_xlim())))

ax2.set_xticks(Kelvin2GeV(locs))
ax2.set_xlim(ax1.get_xlim())

f = mticker.ScalarFormatter(useOffset=False, useMathText=True)
g = lambda x,pos : "${}$".format(f._formatSciNotation('%1.10e' % GeV2Kelvin(x)))
fmt = mticker.FuncFormatter(g)
ax2.xaxis.set_major_formatter(mticker.FuncFormatter(fmt))

plt.show()

enter image description here

0 голосов
/ 12 февраля 2019

Проблема выглядит следующим образом: Когда вы используете ax2.set_xlim(ax1.get_xlim()), вы в основном устанавливаете предел верхней оси X таким же, как и для нижней оси X.Теперь, если вы сделаете

print(ax1.get_xlim()) 
print(ax2.get_xlim()) 

, вы получите для обеих осей те же значения, что и

(6.309573444801943e-16, 158489319246.11108) 
(6.309573444801943e-16, 158489319246.11108) 

, но ваша нижняя ось х имеет логарифмическую шкалу .Когда вы назначаете пределы с помощью ax2.set_xlim(), пределы ax2 совпадают с , но шкала все еще линейная .Вот почему, когда вы устанавливаете отметки на [.2, .5, .9], эти значения отображаются в виде отметок в крайнем левом углу верхней оси x, как на вашем рисунке.

Решение состоит в том, чтобы установить верхнюю ось x также набыть логарифмической шкалой.Это необходимо, потому что ваш new_tick_locations соответствует фактическим значениям на нижней оси x.Вы просто хотите переименовать эти значения, чтобы показать метки в Кельвинах.Из ваших имен переменных ясно, что new_tick_locations соответствует новым позициям галочек.Я использую некоторые измененные значения new_tick_locations, чтобы выделить проблему.

Я использую научное форматирование '%.0e', потому что 1 ГэВ = 1,16e13 K и, следовательно, 0,5 ГэВ было бы очень большим значением со многими нулями.

Ниже приведен пример ответа:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick

tt = np.logspace(-14,10,100)
yy = np.logspace(-10,-2,100)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()

ax1.loglog(tt,yy)
ax1.set_xlabel('Temperature (GeV)')

new_tick_locations = np.array([0.000002, 0.05, 9000])

def tick_function(X):
    V = X*1.16e13
    return ["%.1f" % z for z in V]

ax2.set_xscale('log') # Setting the logarithmic scale
ax2.set_xlim(ax1.get_xlim())

ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(new_tick_locations))
ax2.xaxis.set_major_formatter(mtick.FormatStrFormatter('%.0e'))

ax2.set_xlabel('Temp (Kelvin)')
plt.show()

enter image description here

...